【问题标题】:[SOLVED]Subscriber don't receive delegate[已解决]订阅者没有收到委托
【发布时间】:2020-11-24 21:05:45
【问题描述】:

抱歉,如果我再次提出与代表相关的愚蠢问题... 我会尽量准确。 我有这种情况: 对象 A + 脚本 A, 对象 B、D、E... + 脚本 B。 脚本 B 有一个委托,并且应该通过作为订阅者的脚本 A 在对象 A 中触发反应。 例如

public class ScriptA : MonoBehaviour
{
    void Start() {
        FindObjectOfType<ScriptB>().onScriptBEvent += DoSomethingInA;
    }

    void DoSomethingInA (string s, float q) {

        print("String: "+s+"; Float: "+q);
    }

}

public class ScriptB : MonoBehaviour
{
        
    public delegate void ScriptBDelegate(string name, float q);
    public event ScriptBDelegate onScriptBEvent;

    void Start() {
    }
    
    void RandomMethodInB (string s, float q) {
    
        if(onScriptBEvent != null){
        onScriptBEvent (s, q);
        }
    }
    
}

但它不起作用。 添加一些 Debug 代码我注意到尽管订阅了脚本 A,但 onScriptBEvent 没有通过无效测试。

在我的程序中,我已经编写了许多其他代表,并且每个代表都工作得很好。 我尝试将脚本 A 订阅给其他代表,他们工作得很好。 我看到的唯一区别是脚本 B 被添加到许多对象(B、C、D..)中,而其他带有委托的脚本总是被实例化一次。

有什么提示吗?

将解决方案编辑为 Ruzihm: 问题是 FindObjectOfType 找到第一个实例化的对象,不一定是发送消息的对象。 最简单的解决方案(对我来说)是创建一个脚本 B 数组,然后订阅它们中的每一个:

public class ScriptA : MonoBehaviour
    {
        private ScriptB[] scriptList = new ScriptB[100];
        
        void Start() {
            scriptList = FindObjectOfType<ScriptB>();

            foreach (var script in scpritList){
            script.onScriptBEvent += DoSomethinInA;
            }
        }
    
        void DoSomethingInA (string s, float q) {
    
            print("String: "+s+"; Float: "+q);
        }
    }

它有效!

【问题讨论】:

  • 你有OnScriptBEventonScriptBEvent,只是大小写不同。这是一个错字,还是你两者都有?如果两者兼而有之,则您没有订阅要解雇的那个。
  • 听起来您没有通过FindObjectOfType&lt;ScriptB&gt;() 获得您正在寻找的实例。 ^ 哦,好收获
  • @madreflection 这只是一个例子
  • @Ruzihm 是的!这就是问题!太简单!在每个实例化的脚本 B 中,我无法找到正确的发送消息的人!我该如何解决?
  • ScriptA 的 Start 运行后是否正在实例化 B?如果没有,只需遍历 FindObjectsOfType&lt;ScriptB&gt;() 的结果并将委托附加到每个 onScriptBEvent

标签: c# unity3d delegates


【解决方案1】:

场景中是否同时存在多个带​​有 ScriptB 的对象?如果有多个,FindObjectOfType 将只返回它找到的第一个对象。

为确保您引用了正确的对象,您应该执行以下操作之一:

  • 如果物体B已经在场景中,你应该将物体B拖到物体A的ScriptB字段中

      [SerializeField] ScriptB m_ObjectB; //drag object B into this field in inspector
      void Start()
      {
          m_ObjectB.onScriptBEvent += DoSomethingInA;
      }
    
  • 如果对象 B 是从脚本中实例化的,则获取引用并使用它添加委托

      ScriptB newObjectB = Instantiate(objectBPrefab).GetComponent<ScriptB>();
      newObjectB.onScriptBEvent += DoSomethingInA;
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多