unity3dui注视屏幕

2018-03-27 08:03:03 Skying_ 阅读数 5110
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    阅读此篇文章之前,你应该初步熟悉Unity的UGUI系统操作。

    如果仅想实现屏幕自适应,那么只需观看斜体带下划线的文字即可,其他的文字都是解释。

    我们都知道,不同的设备,屏幕分辨率也通常是不同的,我们开发游戏或者应用的时候肯定要考虑到这个问题,总不能只在开发者你的手机上运行吧,那么这篇文章讨论的就是关于Unity的UGUI系统的屏幕自适应问题。

   Canvas,unity的画布,相信对UGUI有初步了解的人应该会知道他的功能,我们2d游戏会显示在画布上,包括一些控件,图片。

    

    我们鼠标点击画布,在Hierarchy视图中会出现Canvas的一些属性

    我们把Render Mode的属性设置为Screen Space。我们来看Canvas里面的Render Mode属性,Screen Space - Overlay这个属性的作用是让画布直接覆盖屏幕,好处是我们不需要相机,坏处是我们无法在被画布覆盖的范围添加其他画布,不是添加不了,而是添加后无法显示,因为Overlay这个属性找不到层次.Screen Space - Camera这个属性的作用是让画布覆盖相机,我们知道相机可以有很多个,但屏幕只能有一个,所以在这种模式下,我们可以建两个画布,建两个相机与之对应,我们给两个相机的z附上不同的值,这样的话,两个画布就有了层次,并且能同时显示.WorldSpace属性,这个属性我们一看名字就能明白,这个属性是针对世界坐标的,意思是我们可以创建3D的UI,并且能在UI上显示出三维的效果。

    在Screen Space模式下,我们可以给Canvas拖一个相机,因为这里我们只有一个Canvas,所以我们给之一个主相机就可以了。

    Canvas Scaler中,UI Scale Mode属性表示了在不同分辨率下,UI怎么缩放,我们要让UI自适应屏幕,1。所以我们选Scale With Screen Size,属性,这种情况下有个好处,看我们下面的 XY值分别设置成了1280,720,在Scale With Screen Size下,意味着我们游戏中的参数只需针对1280,720设置就可以了,大家可能不太懂,举个例子,下面Match的值,Match Width or Height,我们吧Match的值设为0,就代表屏幕针对宽进行缩放,就意味着,如果屏幕的宽变成了640,那么你在游戏中写脚本,让物体移动1280,那么他真实的移动并不是1280,而是640,因为Unity自动进行了适应.2。当我们把UI Scale Mode设置为Constant Pixel Size的时候,Unity不会对长宽进行缩放,就代表我们的屏幕宽度为640,那么你在脚本中写让物体移动1280,其实他实际就是移动了1280.这两种属性各有各的好处,Constant Pixel Size我们需获取Screen.width和Screen.height,并且游戏中所有关于UI像素的值都需要针对Screen.width和Screen.height设置.Scale With Screen Size我们在脚本中的所有关于像素的值,仅需按照我们设置的长宽进行适应,即那个1280,720,这样会给我们很多方便,但是有些时候会出现一些小问题,当然如果技术精的话,选哪个都是没有问题的。

    那么我们对画布的设置已经完成了,我们基本也实现了自适应,但是有一个问题没有解决,我们上面设置的是让屏幕针对画布的宽进行自适应,如果我们编辑的宽高为1280和720 ,但真实的屏幕宽高为640和480,那么匹配为宽度的话,代码中的宽1280对应着480,那高720对应着多多呢?480?我们可以计算一下,1280/640 =?/ 480,对,没错,“?”就是我们想要的值,?= 1280 / Screen.width * Screen.height,为什么要计算这个值呢,我们在游戏中,一旦涉及到屏幕高的时候,我们一定要用“?”的值,而不要用那个720,至此结束,附上这个最后一段适应高的代码。

int width = 1280;

int height =(int)(Screen.height * 1280.0 / Screen.width);

//我们在游戏中设计到屏幕宽高的时候要用width度和height的值

 


    由于本人也是小白,有哪些问题的话欢迎交流。

 

 

 

 

2013-01-14 16:35:58 jeksonal 阅读数 21050
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

android手机屏幕分辨率五花八门,导致开发时不好把握,还好各个引擎对这个屏幕分辨率问题都有较好的处理方式;unity3D 也为我们提供了一个不错的解决方案。

在Unity3D 进行 android 游戏开发时,对于不同分辨率下的显示效果就像是摄像机的自动平移了一般,看了不少游戏,对于 Unity3D 开发 android 游戏貌似都没有做相应的屏幕分辨率的处理,而是随摄像机的自动移动,把场景做大些不至于出现空白背景。

其实 Unity3D 开发3D游戏,对于不同的分辨率,我们只需要设置 1 个唯一的屏幕显示区域比(说白了就是宽高比),这样显示区域就不会随分辨率的改变而拉升。

上代码:

using UnityEngine;
using System.Collections;


public class Resolution : MonoBehaviour {
    public Camera mainCamera;
    void Start()
    {
        //Screen.SetResolution(1280, 800, true, 60);
        mainCamera = Camera.mainCamera;
        //  float screenAspect = 1280 / 720;  现在android手机的主流分辨。
        //  mainCamera.aspect --->  摄像机的长宽比(宽度除以高度)
        mainCamera.aspect = 1.78f;
    }
}

把此代码脚本绑定在  MainCamera 上就OK了,这样就不会导致不同分辨率下屏幕显示区域大小不一的问题!

2017-12-22 09:53:48 qq_38456478 阅读数 5194
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

在生成的html里面修改代码
    <script type="text/javascript">
    function Reset() {
 var canvas = document.getElementById("#canvas"); 
canvas.height= document.documentElement.clientHeight;
 canvas.width = document.documentElement.clientWidth; 
console.log(canvas.width );
 } 
    </script>
  </head>
  <body onload="Reset()" onresize="Reset()">
      <div class="webgl-content"style="width: 100%; height: 100%" >
      <div id="gameContainer" style="width: 100%; height: 100%"></div>
    </div>
  </body>
</html>
来实现网页版随浏览器自适应
2017-05-08 17:42:02 yongh701 阅读数 23421
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

Unity3D由于是在三维世界中编程,而最终的结果是需要反馈到肉眼所示的2D屏幕之上的。这就产生了一种比较需要考虑的问题,尤其在一些涉及屏幕与Unity3D的3D世界交互的情况。网络上对于这方面的文字,大部分罗列了许许多多文字与代码或者API,甚至连什么视口坐标也带上了。其实在于我个人看来,关键是世界坐标与屏幕坐标之间的互转。

在Unity3D中一打开就会有一个主照相机Main Camera,根据版本不同的初始坐标会在不同的位置。拿Unity3D 4.x的(0,-1,-10)做例子,他的视距,默认是0.3~1000。


主摄像机会对外无间断的发出投影面,将投影面所截取得到的东西,通通投影到屏幕。比如下图,这是一张极其简单的图,(0,-1,-10)的主摄像机将(0,0,0)的正方体投影出来的结果。


现在这个正方体的世界坐标是(0,0,0),如果我们要获取屏幕坐标该怎么做呢?这注定需要用脚本来获取的,而且根据上面的示意图大家也可以知道,屏幕的大小的不同导致最后产生出来的屏幕坐标是不同的。因为Unity3D对屏幕坐标定义是这样的:


以下脚本展示了屏幕坐标和世界坐标的互转:

using UnityEngine;
using System.Collections;

public class CoordinateChange : MonoBehaviour
{
    void Start()
    {
        Debug.Log("屏幕宽:" + Screen.width + "高:" + Screen.height);//获取屏幕的长和宽
        Vector2 screenPos = Camera.main.WorldToScreenPoint(new Vector3(0, 0, 0));//世界坐标(0,0,0),一般可以用transform.position获取->屏幕坐标

        //屏幕坐标->世界坐标
        Debug.Log(screenPos.x + "," + screenPos.y);
        Vector3 worldPos1 = Camera.main.ScreenToWorldPoint(new Vector3(0, 0, Camera.main.nearClipPlane));
        Debug.Log(worldPos1.x + "," + worldPos1.y + "," + worldPos1.z);
        Vector3 worldPos2 = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, -Camera.main.transform.position.z));
        Debug.Log(worldPos2.x + "," + worldPos2.y + "," + worldPos2.z);
    }
}
运行结果如下:


上面脚本有几点需要说明的:

1、Camera.main.XX能够直接对主摄像机操作,无须像网上部分文章需要利用的GameObject.Find之类的找主摄像机。

2、世界坐标与屏幕坐标互转直接就是用WorldToScreenPoint/ScreenToWorldPoint两个方法,这方法凡是照相机对象就有。在部分设置多摄像机编程的程序,就是转换到调用的摄像机所对应的屏幕的世界。

3、WorldToScreenPoint世界坐标转屏幕坐标,很好理解,大家也看到(0,0,0)这个世界的三维坐标转到的(431.5,174.4537)这个屏幕的二维坐标Vector2 screenPos。这里屏幕宽:863高:422,处于(0,0,0)的长方体被投影到屏幕的中央偏下的位置,这和实际是吻合的。

当然实际操作中,其实这个屏幕坐标的多少对于我们来说是没意义的,但这个屏幕坐标所处的位置是在屏幕的百分之多少是很有意义的。所以,这一般还要配合Screen.width/height求屏幕的宽和高用。

4、对于ScreenToWorldPoint,屏幕坐标转世界坐标,可能有人会有疑问,屏幕坐标不是一个二维坐标,怎么这里试图对一个三维坐标转换?还在Z轴附带一些奇怪奇怪的位置。这里的Z轴,是投影面底部所处的Z轴位置距离摄像机Z轴的多少。上面的投影示意图,已经可以说明投影面是多个的,但只会投影到一个2D屏幕平面而已,世界中的物体/对象只能有一个,那么就形成一种 一个世界坐标只会对应一个屏幕坐标,一个屏幕坐标可能对应多个世界坐标。所以我们要补上一个Z轴,告诉程序,我要的是哪个屏幕坐标。

这里展示了将(0,0)这个左下角的屏幕坐标,转到距离摄像机最近的投影面上面,要拿这个投影面,如脚本所示,可以直接用Camera.main.nearClipPlane来取。还展示了将(Screen.width, Screen.height)这个右上角的屏幕坐标,放到Z轴为0,也就是世界屏幕的这个位置,因为摄像机所处的Z=-10,要放到世界坐标z=0,所以这里的Z轴要填上-Camera.main.transform.position.z,刚好就是-10-0。结果如上图所示。

理论上,投影面距离摄像头越近,他的投影面越小。所以大家看到如果转到距离摄像机最近的投影面上面,边角的坐标是0.x级别的,放到z=0这个投影面上面,边角的坐标则去到个位数级别。

2018-01-03 14:49:44 q764424567 阅读数 5439
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

这里写图片描述

Input.mousePosition就是鼠标所在的位置的坐标

函数Camera.main.ScreenToWorldPoint就是屏幕坐标转化三维空间的函数

Camera.main.ScreenToWorldPoint

这里写图片描述

把脚本挂载在主摄像机上
运行
这里写图片描述

就得到屏幕坐标映射在三维世界中的坐标了
不过有一点是,转化之后z轴是-10
这个时候只要z轴+10就是屏幕映射到三维世界的正确坐标了

Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition) + new Vector3(0, 0, 10);