转载自:http://www.omuying.com/article/126.aspx
大家在开发 Unity 的时候,肯定使用过 MonoBehaviour 中的 Update 函数,在每个类中调用 Update 有很多优点,当然也有非常多的缺点,下面我们说说他的优点与缺点。
优点部分(不完全)
缺点部分(不完全)
因为以前在开发 FLASH 游戏的时候,会经常使用帧管理器来统一管理游戏的运行,因为这样可以保证游戏对象都有统一的节奏,在一个帧中可能执行的逻辑有些复杂,但是这会确保游戏对象都有统一的时间延迟,根据以前的经验,用 Unity 实现了一个帧管理器,这样做的好处是只需要几个少数的 Update 函数就可以管理游戏中所有的对象节奏,保证逻辑统一,并且有序。
主要的类只有两个,一个是 FrameItem.cs 类,代码如下:
using UnityEngine;
using System;
/// <summary>
/// 帧对象,任何调用 Update 的类都应该交由 FrameItem 管理
/// </summary>
public class FrameItem
{
private Action callback;
/// <summary>
/// 构造函数,必须实例化
/// </summary>
/// <param name="callback">Callback.</param>
public FrameItem(Action callback)
{
this.callback = callback;
}
/// <summary>
/// 帧管理器
/// </summary>
/// <param name="callback">Callback.</param>
public virtual void FrameUpdate()
{
this.callback();
}
}
另一个是 FrameManager 类,代码如下:
using UnityEngine;
using System;
using System.Collections.Generic;
/// <summary>
/// 帧管理器
/// </summary>
public class FrameManager
{
public static Dictionary<object, FrameItem> frameList = new Dictionary<object, FrameItem>();
/// <summary>
/// 调用函数
/// </summary>
public static void Run()
{
FrameItem[] objectList = new FrameItem[frameList.Values.Count];
frameList.Values.CopyTo(objectList, 0);
// 锁定
foreach(FrameItem frameItem in objectList)
{
if(frameItem != null) frameItem.FrameUpdate();
}
}
/// <summary>
/// 注册帧管理器
/// </summary>
/// <param name="objectItem">Object item.</param>
/// <param name="callback">Callback.</param>
public static void Register(object objectItem, Action callback = null)
{
if(!frameList.ContainsKey(objectItem))
{
FrameItem frameItem = new FrameItem(callback);
frameList.Add(objectItem, frameItem);
}
}
/// <summary>
/// 取消注册帧管理器
/// </summary>
/// <param name="objectItem">Object item.</param>
public static void UnRegister(object objectItem)
{
if(frameList.ContainsKey(objectItem)) frameList.Remove(objectItem);
}
}
测试用例的代码如下(完整代码可以下载源代码运行):
using UnityEngine;
using System.Collections;
public class DemoItem : MonoBehaviour
{
public int index;
public void Init()
{
FrameManager.Register(this, this.UpdateCallback);
}
private void UpdateCallback()
{
// 处理一些事情等同于 Update
}
}
全局代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Demo : MonoBehaviour
{
private List<DemoItem> itemList;
void Awake()
{
this.itemList = new List<DemoItem> ();
GameObject objectItem = null;
DemoItem demoItem = null;
for(int index = 0; index < 500; index ++)
{
objectItem = new GameObject();
objectItem.name = "item_" + index;
demoItem = objectItem.AddComponent<DemoItem>();
demoItem.index = index;
this.itemList.Add(demoItem);
}
this.StartCoroutine (this.AwakeEnumerator());
}
private IEnumerator AwakeEnumerator()
{
yield return new WaitForSeconds (5f);
int length = this.itemList.Count;
for(int index = 0; index < length; index ++)
{
this.itemList[index].Init();
}
}
void Update()
{
FrameManager.Run ();
}
}
/*
* Unity3D 帧事件管理器(关于 MonoBehaviour 的 Update 函数)
* 大家在开发 Unity 的时候,肯定使用过 MonoBehaviour 中的 Update 函数,在每个类中调用 Update 有很多优点,当然也有非常多的缺点,下面我们说说他的优点与缺点。
* 优点部分(不完全)
* 1、方便,每个逻辑单独处理,比如每个子弹对象控制每个子弹的移动轨迹等等。
* 缺点部分(不完全)
* 1、每个类的 Update 函数都会自动运行,禁止自动运行一是禁用脚本,但是禁用脚本之后,其他的固定执行函数将无法继续进行,二是添加状态判断,这样又会增加每个类的执行效率开销。
* 2、每个类的 Update 执行顺序不能统一,比如一个子弹每帧移动 5 像素,另一个子弹每帧移动 5 像素,但是不能保证他们能在同帧中同时到达目标位置。
* 3、暂停比较麻烦,比如我们希望场景中的某些角色停止一分钟,这个时候我们最常用的就是添加一个状态,然后在 Update 中判断这个状态值,但是这样会增加每个类的执行效率开销。
*
* 因为以前在开发 FLASH 游戏的时候,会经常使用帧管理器来统一管理游戏的运行,因为这样可以保证游戏对象都有统一的节奏,在一个帧中可能执行的逻辑有些复杂,但是这会确保游戏对象都有统一的时间延迟,根据以前的经验,用 Unity 实现了一个帧管理器,这样做的好处是只需要几个少数的 Update 函数就可以管理游戏中所有的对象节奏,保证逻辑统一,并且有序。
*
* 主要的类只有两个,一个是 FrameItem.cs 类,代码如下:
* 另一个是 FrameManager 类,代码如下:
*
* 测试用例的代码如下(完整代码可以下载源代码运行):
*
* 最后我们只有一个 Update 函数,就是 Demo.cs 中的 Update 函数,这个函数控制着场景中创建的 500 个对象的 Update 函数,通过 FrameManager 类,我们可以非常容易控制某些对象暂停执行 Update,并且不会额降低代码执行的效率。
* */