某些游戏项目关卡地图场景很大,而对于玩家而言,他的可视区域只是场景地图一小部分。而那些非可视区域的游戏对象还是还一直在“后台”执行游戏逻辑中,其实是没必要的,而且会对性能造成很大影响。Unity引擎在渲染层面已经做了一些优化:
(1)自动对相机视图不可见的游戏对象避免去渲染,称之为“视锥剔除”技术;
(2)自动避免渲染隐藏在其他对象后面的对象,称之为“遮挡剔除”技术;
但是,它不会影响在CPU上执行任务的脚本组件,比如:AI脚本、UI界面和其他的游戏逻辑。这些必须由我们自己手动来控制。
因此,这里列举2种策略来禁用开启游戏对象或组件。
其一,通过可见性禁用对象。对于场景中一个游戏对象,当所有的相机都不可见时,会触发OnBecameVisible();当场景中任何一个相机可见时,就会触发OnBecameInvisible()的回调。
【注意】由于可见性回调与渲染管线通信,因此,GameObject游戏对象必须附加上MeshRenderer后SkinnedMeshRenderer组件。
测试脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* Author:W
* 性能优化:场景中游戏对象的可见与否的回调
* 1.OnBecameVisible
* 2.OnBecameInVisible
*/
public class OnBecameVisibleTest : MonoBehaviour {
/// <summary>
/// 游戏对象可见时
/// </summary>
void OnBecameVisible()
{
Debug.Log("====游戏对象可见时======");
this.enabled = true;
}
/// <summary>
/// 游戏对象不可见时
/// </summary>
void OnBecameInvisible()
{
Debug.Log("====游戏对象不可见时======");
this.enabled = false;
}
}
结果如下截图:通过拉动胶囊体对象的远近。
其二,通过距离玩家的远近禁用对象。当玩家离游戏对象足够远时,以至于几乎看不到它们,另外,玩家也不要关注到它们时,此时可以考虑禁用它们。
测试脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* Author:W
* 通过与玩家的距离来禁用对象
*/
public class DistanceVisibleTest : MonoBehaviour {
/// <summary>
/// 玩家
/// </summary>
public GameObject player;
/// <summary>
/// 距离玩家的最大距离
/// </summary>
public float maxDis;
/// <summary>
/// 检测频率
/// </summary>
public int frameDelay;
// Use this for initialization
void Start () {
//开启距离检测
StartCoroutine(CheckToPlayerDistance());
}
IEnumerator CheckToPlayerDistance()
{
while (true)
{
float disSqrd = (this.transform.position - player.transform.position).sqrMagnitude;
//距离玩家小于最大距离时,开启
if (disSqrd < maxDis * maxDis)
{
this.enabled = true;
Debug.Log("======开启=======");
}
else
{
this.enabled = false;
Debug.Log("======关闭=======");
}
//设置调用协程的频率
for (int i = 0; i < frameDelay; i++)
{
yield return new WaitForEndOfFrame();
}
}
}
}
结果如图
总结:上面讲述了2种禁用开启游戏对象策略,读者可以根据自己的项目特点来选择。