[置顶] Unity的优化系列4 - 最好使用Canvas Overlay代替Screen Space Camera

孙广东  2016.5.23


计算机生成了可选文字:


Unity提供了用于创建 UI 的画布。画布上有渲染模式如下 ︰

  • 屏幕空间相机 Screen Space Camera
  • 屏幕空间覆盖 Screen Space Overlay
  • 世界空间 World Space

         让我们了解哪种模式是更好,让我们以一个非常简单的示例测试这三项


1   屏幕空间相机


让我们创建一个Unity项目︰

脚本 ︰ MoveCamera.cs

  1. 在你的场景建立一个Canvas。
  2.  设置渲染模式为:  Screen Space Camera
  3. Main Camera,拖到render camera 选项(其他相机也可以)。
  4. sprite或图像中作为一个背景
  5. Canvas内创建尽可能多的panels UITexts Images
  6. 添加到Camera的脚本。


using UnityEngine; 
using System.Collections;

public class MoveCamera : MonoBehaviour
{
	private float velocity = 0.0f;
	private float smoothTime = 0.3f;
	private bool moveCamera = false;

	public Vector3 initialPosition;
	public Vector3 targetPosition;
	public float lerpSpeed;

	public float initialZ;
	public float targetZ;
	public Camera cam;
	void Update ()
	{
		if (Input.GetMouseButtonDown (0)) {
			initialPosition = transform.position;
			targetPosition = new Vector3 (transform.position.x + Random.Range (-5, 5), transform.position.y + 				Random.Range (-5, 5), transform.position.z);
			initialZ = transform.eulerAngles.z;
			targetZ = initialZ + Random.Range (-50, 50);
			moveCamera = true;
			lerpSpeed = 0;
		}
		if (moveCamera) {
			CameraMovementMethod ();
		}
	}

	private void CameraMovementMethod ()
	{
		lerpSpeed = Mathf.SmoothDamp (lerpSpeed, 1.0f, ref velocity, smoothTime);
		cam.transform.position = Vector3.Lerp (initialPosition, targetPosition, lerpSpeed);
		cam.transform.eulerAngles = new Vector3 (0, 0, Mathf.LerpAngle (initialZ, targetZ, lerpSpeed));
	}
}

  1. Build部署 Android 手机、 创建debugging build ,允许自动连接到profiler
  2.  在手机上运行该项目的,然后在处理随便点击屏幕
  3. Unity编辑器中profiler上搜索 "canvas"你会看到


计算机生成了可选文字:
cpu usage 
Time m. 
select Line


 正如你从图片中可以看到,有很多的画布的调用Calls,特别注意到CanvasRender.OnTransformChanged

每当相机移动大约每个帧上 50 调用。

注意   调用次数是依赖于Canvas上的 使用的UI 元素个数

我们可以更好地理解这与下面 gif:


screen-space-camera-gif


你可以看到上面,在游戏中移动Canvas相关的摄像机,因此每个UI 元素在画布上不得不由Unity引擎重新定位。因此越多的UI元素,就需要更多的处理


那么,解决方案是什么?


2   屏幕空间覆盖


在刚刚的测试项目中我们把 Canvas的渲染模式改为 Screen Space Overlay ,并重复之前的步骤,同样想在观察Profiler。

大约我们优化它约 90%


正如你可以看到以上,UI 画布保持原样在Unity空间,摄像机运动的不影响 UI Canvas根本。画布保持静态。


因此,不需要任何重新定位或所需的处理。


实现了高的优化。


3   世界空间


在世界空间模式,画布渲染手动更改为 World Space,测试结果和第一种一样。

结论


考虑screen space camera 类型的呈现进行大量的调用,所以非常推荐使用Overlay 绘制画布,使你的游戏在移动设备上更顺畅。(当然了这种只是限于纯UI),但是另外两种模式是有其特殊用处的!


ForEach 循环优化


计算机生成了可选文字:


这是个老生常谈的话题, 主要还是产生GC的问题:


public class ForEachLoopTest : MonoBehaviour
{ 
    #region PUBLIC_DECLARATIONS
    public List<GameObject> emptyGameObjects;
    #endregion

    #region UNITY_CALLBACKS
    void Update()
    {
        if (Input.GetKey(KeyCode.Space))
        {
            UpdateTextValue();
        }
    }
    #endregion
    #region PUBLIC_METHODS
    public void UpdateTextValue()
    {
        foreach (var item in emptyGameObjects)
        {
            // PROCESS ITEMS IN LIST
        }
//        for (int i = 0; i < emptyGameObjects .Count; i++)
//        {
        // PROCESS ITEMS IN LIST
//        }
    }
    #endregion
}

Profiler ForEach Loop


按下空格键 ,当是10~30大小的循环时  会看到如上图的 效果: 每帧产生 40B GC


foreach (SomeType sin someList)

    s.DoSomething();


现在编译, 编译器预处理的代码:


using (SomeType.Enumerator enumerator = this.someList.GetEnumerator())

{

    while (enumerator.MoveNext())

    {

        SomeType s = (SomeType)enumerator.Current;

        s.DoSomething();

    }

}


在每次迭代时,会创建一个 enumerator对象。



你可能感兴趣的:(canvas,unity,Camera,screen,overlay,space,优化系列)