SendMessage(Unity)

本文详细介绍了Unity中SendMessage方法的不同使用方式及其性能对比。包括只发送给当前游戏对象的脚本、递归向上发送给所有父级对象以及广播给自身及所有子对象。并通过实例代码展示了与委托调用在性能上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下有关SendMessage的发送消息的方法,都需要继承 MonoBehaviour,属于Mono封装的方法。

    1、SendMessage();  只发送给悬挂在当前方法所悬挂的游戏物体上的脚本

        SendMessage(string methodName);                                (方法名)

        SendMessage(string methodName, object value);            ( 方法名,传参)

        SendMessage(string methodName, SendMessageOptions options);(方法名,如果找不到要调用的方法,是否引发错误)=》第二个参数解析:

                                    ① SendMessageOptions.DontRequireReceiver,不引发报错。

                                    ②SendMessageOptions.RequireReceiver,引发报错。

        SendMessage(string methodName, object value, SendMessageOptions options);(方法名,参数,查找不到方法是否引发报错)

    2、SendMessageUpwards(); 发送给本身和其所有父物体,参数类型同1

    3、BroadcastMessage();发送给本身和其所有子物体,参数类型同1

与委托调用速度的比较,调用50000次的结果,SendMessage比委托慢10倍(很久以前看的一篇文章的测试方法,具体在哪找不到了)。代码如下 :

  public delegate void MyDelegate(string arg1);
    public MyDelegate myDelegate;
    bool isStart;
    float timeStart;
    int count;
    bool isStartSendMessage;
    void Start()
    {
        myDelegate += myFunciton1;
    }
    void Update()
    {
        if (isStart)
        {
            isStart = false;
            count = 0;
            timeStart = Time.realtimeSinceStartup;
            Debug.Log("Start = " + timeStart);
            for (int i = 0; i < 50000; i++)
            {
                if (myDelegate != null) myDelegate("");
            }
        }


        if (isStartSendMessage)
        {
            isStartSendMessage = false;
            count = 0;
            timeStart = Time.realtimeSinceStartup;
            Debug.Log("Start = " + timeStart);
            for (int i = 0; i < 50000; i++)
            {
                this.gameObject.SendMessage("myFunciton1", "", SendMessageOptions.DontRequireReceiver);
            }
        }
    }

    void OnGUI()
    {
        if (GUILayout.Button("INVOKE Delegate"))
        {
            isStart = true;
        }


        if (GUILayout.Button("SendMessage"))
        {
            isStartSendMessage = true;
        }


    }

    void myFunciton1(string s)
    {
        count++;
        if (count == 50000)
        {
            Debug.Log("End = " + Time.realtimeSinceStartup);
            Debug.Log("Time Spent = " + (Time.realtimeSinceStartup - timeStart));
        }
    }

### Unity 中 `SendMessage` 方法的使用场景 #### 场景一:对象间解耦 当多个游戏对象需要相互通信时,可以利用 `SendMessage` 实现松散耦合的设计模式。这种方式允许开发者无需显式引用目标对象即可完成操作[^1]。 ```csharp using UnityEngine; public class Sender : MonoBehaviour { public GameObject targetObject; private void Start() { // 向目标对象发送名为 "ReceiveMessage" 的消息 targetObject.SendMessage("ReceiveMessage", "Hello from Sender!"); } } ``` 接收端代码如下: ```csharp using UnityEngine; public class Receiver : MonoBehaviour { public void ReceiveMessage(string message) { Debug.Log($"Received: {message}"); } } ``` 此示例展示了如何通过 `SendMessage` 将字符串数据传递给另一个对象的方法。 --- #### 场景二:动态事件触发 在某些情况下,可能无法提前预知哪个对象会响应某个事件。此时可以通过广播机制实现多对象监听同一事件的功能。例如,在玩家拾取物品时通知所有相关脚本更新状态。 ```csharp private void OnTriggerEnter(Collider other) { if (other.CompareTag("Item")) { // 广播消息至当前对象上的所有组件以及子对象 SendMessageUpwards("OnItemPicked"); } } ``` 上述代码片段中,`SendMessageUpwards` 是一种变体形式,它不仅作用于指定的目标对象本身,还会沿父级链路逐层传播直至根节点。 --- #### 场景三:跨平台交互支持 除了内部逻辑处理外,`SendMessage` 还可用于外部系统的集成工作,比如安卓原生插件与Unity引擎之间的通讯过程。Android 层可通过调用 `UnityPlayer.UnitySendMessage` 函数来触发生命周期内的任意公共函数[^2]。 假设有一个简单的例子——从Java侧传入一条日志信息到C#环境里打印出来,则对应的配置应如下所示: **Java部分** ```java import com.unity3d.player.UnityPlayer; ... String logContent = "This is a test."; UnityPlayer.UnitySendMessage("MainCamera", "LogFromAndroid", logContent); ``` **Unity部分** ```csharp void LogFromAndroid(string content){ Debug.Log(content); } ``` 这里需要注意的是,第一个参数代表接受者的名字(通常是挂载该脚本的游戏物件),第二个则是具体要执行的动作名称,最后一个是可选的数据负载项。 --- #### 性能考量与局限性分析 尽管如此便利,但在实际开发过程中也需注意性能开销问题。因为每次调用都会遍历整个继承树寻找匹配方法名的操作可能会带来额外负担,特别是在大规模复杂项目环境下尤为明显。因此建议仅限必要场合下采用此类技术手段,并考虑替代方案如观察者模式或者事件总线架构等更高效的方式解决同类需求。 --- ### 注意事项 - 如果找不到对应的方法则不会抛出异常而是静默失败。 - 只有标记为 `public` 或声明成无访问修饰符(默认即公开级别)才能被正常寻址成功。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值