每一个对象都有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、三者区别
项目层次:Camera,Panel,Btn,label,sprite 这五个对象都附加上了脚本,脚本代码分别如下:
Camera:
void Say(string name) {
        Debug.Log("camera " + name);
    }
Panel:
void Say(string name) {
        Debug.Log("panel " + name);
    }
label:
 void Say(string name) {
        Debug.Log("label " + name);
    }
sprite:
void Say(string name) {
        Debug.Log("sprite " + name);
    }
Btn:
    void Say(string name) {
        Debug.Log("btn " + name);
    }
1、如果btn按钮的OnClick事件代码用的是SendMessage:
void OnClick() {
        this.gameObject.SendMessage("Say", "zwh", SendMessageOptions.DontRequireReceiver);
    }
那么执行结果为:
2、如果btn按钮的OnClick事件代码用的是SendMessageUpwards:
void OnClick() {
        this.gameObject.SendMessageUpwards("Say", "zwh", SendMessageOptions.DontRequireReceiver);
    }
那么执行结果为:
3、如果btn按钮的OnClick事件代码用的是BroadcastMessage:
void OnClick() {
        this.gameObject.BroadcastMessage("Say", "zwh", SendMessageOptions.DontRequireReceiver);
    }
那么执行结果为:

4、总结

SendMessage 查找的方法是在自身当中去查找

SendMessageUpwards 查找的方法是在自身和父类中去查找,如果父类还有父类,继续查找,直到找到根节点为止

BroadcastMessage 查找的方法是在自身和子类中去查找,如果子类还有子类,继续查找,直到没有任何子类

5、多个对象执行同一个方法

NGUITools类里面有一个重载的静态方法:Broadcast (代码如下),这个静态方法的作用就是遍历所有的对象,找到要执行的方法,然后执行对象的SendMessage方法!但是这个方法的效率不高,FindObjectsOfType这个方法肯定耗时间,因为我们项目中的对象肯定很多,这无疑是浪费时间,for循环更是耗时间,再说有可能遍历到没有此方法的对象,做无用功!我们最好的办法就是只执行那些我们需要的某些对象去执行某一方法,而不是遍历所有对象,却不管他有没有此方法,所以我们得寻求好的解决方法,请转到 6

     static public void Broadcast (string funcName)
{
GameObject[] gos = GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[];
for (int i = , imax = gos.Length; i < imax; ++i) gos[i].SendMessage(funcName, SendMessageOptions.DontRequireReceiver);
} /// <summary>
/// Call the specified function on all objects in the scene.
/// </summary> static public void Broadcast (string funcName, object param)
{
GameObject[] gos = GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[];
for (int i = , imax = gos.Length; i < imax; ++i) gos[i].SendMessage(funcName, param, SendMessageOptions.DontRequireReceiver);
}
6、多个对象执行同一个方法优化
这个代码主要意思就是把所有需要执行的对象加到一个集合中,然后遍历此集合执行他们的方法,我想大家都能看懂,我就不详细解释了

 public class NotificationCenter : MonoBehaviour {

     static Hashtable notifications = new Hashtable();

     /// <summary>
/// 增加对象
/// </summary>
/// <param name="gameobject">对象</param>
/// <param name="methodname">方法名</param>
/// <param name="param">参数</param>
public static void AddGameObject(GameObject gameobject, String methodname, object param) {
if (string.IsNullOrEmpty(methodname)) {
Debug.Log("方法名为空");
return;
}
if (!notifications.ContainsKey(methodname)) {
Notification notification = new Notification(gameobject, param);
List<Notification> list = new List<Notification>();
list.Add(notification);
notifications[methodname] = list;
} else {
List<Notification> notifyList = (List<Notification>)notifications[methodname];
if (notifyList.Find(a => a.gameobject == gameobject) == null) {
Notification notification = new Notification(gameobject, param);
notifyList.Add(notification);
notifications[methodname] = notifyList;
}
}
}
/// <summary>
/// 移除对象
/// </summary>
/// <param name="gameobject">对象</param>
/// <param name="methodname">方法名</param>
public static void RemoveGameObject(GameObject gameobject, String methodname) {
if (string.IsNullOrEmpty(methodname)) {
Debug.Log("方法名为空");
return;
}
List<Notification> notifyList = (List<Notification>)notifications[methodname];
if (notifyList != null) {
if (notifyList.Find(a => a.gameobject == gameobject) != null) {
notifyList.RemoveAll(a => a.gameobject == gameobject);
notifications[methodname] = notifyList;
}
if (notifyList.Count == ) {
notifications.Remove(methodname);
}
}
}
/// <summary>
/// 执行方法
/// </summary>
/// <param name="methodName">要执行的方法名称</param>
public static void ExecuteMethod(string methodName) {
if (string.IsNullOrEmpty(methodName)) {
Debug.Log("方法名为空");
return;
}
List<Notification> notifyList = (List<Notification>)notifications[methodName];
if (notifyList == null) {
Debug.Log("对象不存在");
return;
}
foreach (Notification notification in notifyList) {
notification.gameobject.SendMessage(methodName, notification.param, SendMessageOptions.DontRequireReceiver);
}
}
public class Notification {
public GameObject gameobject;
public object param;
public Notification(GameObject gameobject, object param) {
this.gameobject = gameobject;
this.param = param;
}
}
}
7、多个对象同时执行他们的方法
6有几个缺点:使用sendmessage,而sendmessage是利用反射原理实现的,我们知道使用反射在某些情况下效率是不高的,我们最好尽量避免使用反射,而且6传的参数只能为一个,是因为sendmessage的缘故,他只允许传一个参数,可扩展性不好!这里我们使用委托来解决这些问题,代码如下,代码也很简单,我也就不说了,如有问题,可以留言。
 public class delegateNotificationCenter : MonoBehaviour {

     static Hashtable notifications = new Hashtable();

     public delegate void MyFunc(object[] obj);
/// <summary>
/// 增加对象
/// </summary>
/// <param name="gameobject"></param>
/// <param name="methodname"></param>
/// <param name="param"></param>
public static void AddGameObject(GameObject gameobject, String flag, MyFunc func, object[] param) {
if (string.IsNullOrEmpty(flag)) {
Debug.Log("不存在");
return;
}
if (!notifications.ContainsKey(flag)) {
Notification notification = new Notification(gameobject, func, param);
List<Notification> list = new List<Notification>();
list.Add(notification);
notifications[flag] = list;
} else {
List<Notification> notifyList = (List<Notification>)notifications[flag];
if (notifyList.Find(a => a.gameobject == gameobject) == null) {
Notification notification = new Notification(gameobject, func, param);
notifyList.Add(notification);
notifications[flag] = notifyList;
}
}
}
/// <summary>
/// 移除对象
/// </summary>
/// <param name="gameobject"></param>
/// <param name="flag"></param>
public static void RemoveGameObject(GameObject gameobject, String flag) {
if (string.IsNullOrEmpty(flag)) {
Debug.Log("不存在");
return;
}
List<Notification> notifyList = (List<Notification>)notifications[flag];
if (notifyList != null) {
if (notifyList.Find(a => a.gameobject == gameobject) != null) {
notifyList.RemoveAll(a => a.gameobject == gameobject);
notifications[flag] = notifyList;
}
if (notifyList.Count == ) {
notifications.Remove(flag);
}
}
}
/// <summary>
/// 执行方法
/// </summary>
/// <param name="flag"></param>
public static void ExecuteMethod(string flag) {
if (string.IsNullOrEmpty(flag)) {
Debug.Log("不存在");
return;
}
List<Notification> notifyList = (List<Notification>)notifications[flag];
if (notifyList == null) {
Debug.Log("对象不存在");
return;
}
foreach (Notification notification in notifyList) {
notification.func(notification.param);
}
}
public class Notification {
public GameObject gameobject;
public MyFunc func;
public object[] param;
public Notification(GameObject gameobject, MyFunc func, object[] param) {
this.gameobject = gameobject;
this.func = func;
this.param = param;
}
}
}

以上是个人的总结,如有不当,希望大家多多批评指正!

 

Unity-SendMessage的更多相关文章

  1. Unity SendMessage方法

    我们今天研究下SendMessage方法, 如果我们需要执行某一个组件的方法时候可以使用SendMessage gameObject.SendMessage("A"); 即可通知当 ...

  2. Unity 发布的 WebGL 使用SendMessage传递多个参数

    如果要实现Unity与浏览器的数据交互一般都会采用两种方式 方法一: Application.ExternalCall("SayHello","helloworld&qu ...

  3. Unity 发布的 WenGL 使用SendMessage传递多个参数

    如果要实现Unity与浏览器的数据交互一般都会采用两种方式 方法一: Application.ExternalCall("SayHello","helloworld&qu ...

  4. Unity的3种消息传递方法(SendMessage等)

    为了方便多个物体间的消息传达与接收,Unity中包含了几种消息推送机制 : 分别为SendMessage.SendMessageUpwards.BroadcastMessage. 我们首先以SendM ...

  5. Unity中SendMessage和Delegate效率比较

    网上直接搜的代码.需要的使用也简单,所以就不过多说明. 但是网上都说,他们之间的差距,delegate比较快,效果高.怎么个高法呢?还是自己来测试下时间. 故此, 个人之用来比较下时间差别. 一.直接 ...

  6. Unity的sendmessage用法

    刚学完sendmessage用法,自己也尝试测试了一下,用法如下: 1.在unity2017新建一个场景test 2.在场景中添加一个立方体cube作为主角,另添加一个胶囊体capsule,调整为如图 ...

  7. Unity的SendMessage方法

    用法(该对象所有脚本都能收到): gameObject.SendMessage("要执行的方法名"); 通知的另一种实现: gameObject.GetComponent<脚 ...

  8. 【Unity系统知识】关于SendMessage的用法

    [Message相关有3个函数] 一.功能:用于向某个GameObject发送一条信息,让它完成特定功能. 1.执行GameObject自身的Script中“函数名”的函数SendMessage (& ...

  9. Unity插件之plyGame教程:DiaQ对话系统

    本文为孤月蓝风编写,转载请注明出处:http://fengyu.name/?cat=game&id=296 DiaQ是plyGame旗下的一款对话及任务系统.拥有可视化的对话及任务编辑器,能够 ...

  10. Unity 最佳实践

    转帖:http://www.glenstevens.ca/unity3d-best-practices/ 另外可以参考:http://devmag.org.za/2012/07/12/50-tips- ...

随机推荐

  1. 模拟水题,查看二维数组是否有一列都为1(POJ2864)

    题目链接:http://poj.org/problem?id=2864 题意:参照题目 哈哈哈,这个题discuss有翻译哦.水到我不想交了. #include <cstdio> #inc ...

  2. Oracle数据库几种启动方式及查询当前状态

    Oracle数据库几种启动方式 1.startup nomount: 非安装启动,这种方式下启动可执行:重建控制文件.重建数据库,读取init.ora文件,启动instance,即启动SGA和后台进程 ...

  3. 2017.10.9 JVM入门学习

    1.什么是JVM JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现 ...

  4. css3阴影 box-shadow

    语法 box-shadow:X轴偏移量 y轴偏移量 [阴影模糊半径] [阴影扩展半径] [阴影颜色] [投影方式] 参数介绍: 注:inset 可以写在参数的第一个或最后一个,其它位置是无效的. 阴影 ...

  5. C语言中%p,%u,%lu都有什么用处

    %p表示输出这个指针, %d表示后面的输出类型为有符号的10进制整形, %u表示无符号10进制整型, %lu表示输出无符号长整型整数 (long unsigned)

  6. 关于win10深度学习安装配置 CUDA9.0+VS2017+Cudnn7.4.1.5+Anaconda3(cupy安装包)+python3.7+pycharm

    0 查看电脑系统版本(非常重要) WIN+R->输入winver, 系统版本号必须高于1703,否则CUDA9.0难以运行!!!! 1 安装 NVIDIA 显卡驱动程序 下载地址:驱动程序 选择 ...

  7. 第41章 RS-485通讯实验—零死角玩转STM32-F429系列

    第41章     RS-485通讯实验 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...

  8. DTcms网站伪静态逻辑

    我们之前写伪静态就是web.config里面配置好.-->配置伪静态(URL重写),DTcms网站写的伪静态跟之前的不一样,他是静态页面和代码现实了分离.http://demo.dtcms.ne ...

  9. 第33题:LeetCode255 Verify Preorder Sequence in Binary Search Tree 验证先序遍历是否符合二叉搜索树

    题目 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 考点 1.BST 二叉搜索树 2.递归 思路 1.后序 ...

  10. Oracle多表连接方法

    笛卡尔连接[结果集为各表记录的乘积] SELECTt * FROM table_1, table_2, table_n SELECTt * FROM table_1 CROSS JOIN table_ ...