转自:http://www.unitymanual.com/home.php?mod=space&uid=32407&do=blog&id=1132
unity自带的消息函数:
每一个对象都有SendMessage,BroadcastMessage,SendMessageUpwards 三个发送消息的方法!
1、功能:
执行某个对象中的某个方法!
2、实现原理
反射
3、参数
参数 类型 说明
methodName string
The name of the method to call. // 方法名称
value object
An optional parameter value to pass to the called method. //方法参数
options SendMessageOptions
Should an error be raised if the method doesn't exist on the target object? //如果方法不存在
是
否生成错误信息 dontRequireReceiver不生成错误信息,RequireReceiver 生成错误信息
4、总结
SendMessage 查找的方法是在自身当中去查找
SendMessageUpwards 查找的方法是在自身和父类中去查找,如果父类还有父类,继续查找,直到找到根节点为止
BroadcastMessage 查找的方法是在自身和子类中去查找,如果子类还有子类,继续查找,直到没有任何子类
5、多个对象执行同一个方法
NGUITools类里面有一个重载的静态方法:Broadcast (代码如下),这个静态方法的作用就是遍历所有的对象,找到要执行的方法,然后执行对象的SendMessage方法!但是这个方法的效率不高,FindObjectsOfType这个方法肯定耗时间,因为我们项目中的对象肯定很多,这无疑是浪费时间,for循环更是耗时间,再说有可能遍历到没有此方法的对象,做无用功!我们最好的办法就是只执行那些我们需要的某些对象去执行某一方法,而不是遍历所有对象,却不管他有没有此方法,所以我们得寻求好的解决方法,请转到 6
6、多个对象执行同一个方法优化
这个代码主要意思就是把所有需要执行的对象加到一个集合中,然后遍历此集合执行他们的方法,我想大家都能看懂,我就不详细解释了
public class NotificationCenter
{
static Hashtable notificationTable = new Hashtable();
public static void AddGameObject(GameObject tmpObject, string methodname, object tmpparam)
{
if (string.IsNullOrEmpty(methodname))
{
Debug.Log("方法名字为null");
return;
}
//使用list 是可能同一个方法有多个脚本或者对象,这个list里面可能会存储多个 notification
if (!notificationTable.ContainsKey(methodname))
{
//如果不存在
Notification notification = new Notification(tmpObject, tmpparam);
List<Notification> list = new List<Notification>();
list.Add(notification);
notificationTable[methodname] = list;
}
else
{
List<Notification> notifiList = (List<Notification>)notificationTable[methodname];
if (notifiList.Find(a => a.gameObject == tmpObject) == null)
{
Notification notification = new Notification(tmpObject, tmpparam);
notifiList.Add(notification);
notificationTable[methodname] = notifiList;
}
}
}
public static void RemoveGameObject(GameObject tmpObject, string methodname)
{
if (string.IsNullOrEmpty(methodname))
{
Debug.Log("方法名字null");
return;
}
List<Notification> notifyList = (List<Notification>)notificationTable[methodname];
if (notifyList != null)
{
if (notifyList.Find(a => a.gameObject == tmpObject) != null)
{
notifyList.RemoveAll(a => a.gameObject == tmpObject);
notificationTable[methodname] = notifyList;
}
if (notifyList.Count == 0)
notificationTable.Remove(methodname);
}
}
public static void ExecuteMethod(string methodname)
{
if (string.IsNullOrEmpty(methodname))
{
Debug.Log("方法名为空");
return;
}
List<Notification> notifyList = (List<Notification>)notificationTable[methodname];
if (notifyList != null)
{
foreach (Notification fication in notifyList)
{
fication.gameObject.SendMessage(methodname, fication.param, SendMessageOptions.DontRequireReceiver);
}
}
}
class Notification
{
public GameObject gameObject;
public object param;
public Notification(GameObject notiObject, object notiParam)
{
gameObject = notiObject;
param = notiParam;
}
}
}
7、多个对象同时执行他们的方法
6有几个缺点:使用sendmessage,而sendmessage是利用反射原理实现的,我们知道使用反射在某些情况下效率是不高的,我们最好尽量避免使用反射,而且6传的参数只能为一个,是因为sendmessage的缘故,他只允许传一个参数,可扩展性不好!这里我们使用委托来解决这些问题,代码如下,代码也很简单,我也就不说了,如有问题,可以留言。
public class DelegateNotificationCenter
{
static Hashtable notificationTable = new Hashtable();
public delegate void MyFunc(object[] obj);
public static void AddGameObjec(GameObject tmpObject, string flag, MyFunc tmpFunc, object[] tmpParam)
{
if (string.IsNullOrEmpty(flag))
{
Debug.Log("方法名字为null");
return;
}
if (!notificationTable.ContainsKey(flag))
{
//不存在,则创建
DelegateNotification notification = new DelegateNotification(tmpObject, tmpFunc, tmpParam);
List<DelegateNotification> notifyList = new List<DelegateNotification>();
notifyList.Add(notification);
notificationTable[flag] = notifyList;
}
else
{
List<DelegateNotification> notifyList = (List<DelegateNotification>)notificationTable[flag];
if (notifyList.Find(a => a.gameObject == tmpObject) == null)
{
//表示list里面没有这个对象
DelegateNotification notification = new DelegateNotification(tmpObject, tmpFunc, tmpParam);
notifyList.Add(notification);
}
}
}
public static void RemoveGameObject(GameObject tmpObject,string flag)
{
if (string.IsNullOrEmpty(flag))
{
Debug.Log("flag为空");
return;
}
if (notificationTable.ContainsKey(flag))
{
List<DelegateNotification> notifyList = (List<DelegateNotification>)notificationTable[flag];
if (notifyList.Find(a => a.gameObject == tmpObject) != null)
{
//如果存在
notifyList.RemoveAll(a => a.gameObject == tmpObject);
}
if (notifyList.Count == 0)
notificationTable.Remove(flag);
else
notificationTable[flag] = notifyList;
}
}
public static void ExecuteMehod(string flag)
{
if (string.IsNullOrEmpty(flag))
{
return;
}
List<DelegateNotification> notifyList = (List<DelegateNotification>)notificationTable[flag];
if (notifyList.Count > 0)
{
foreach (DelegateNotification notification in notifyList)
{
notification.func(notification.param);
}
}
}
class DelegateNotification
{
public GameObject gameObject;
public MyFunc func;
public object[] param;
public DelegateNotification(GameObject tmpObject, MyFunc tmpFunc, object[] tmpParam)
{
gameObject = tmpObject;
func = tmpFunc;
param = tmpParam;
}
}
}