Unity中脚本之间的最佳通信方式是什么

时间:2018-09-16 17:45:40

标签: c# unity3d

例如,假设我有一个附加了Manager脚本的GameObject A,开始时会生成x个附加了B脚本的GameObjects。

当脚本B的GameObject这样说时,脚本C的另一个GameObject应该会做某事。

问题是,这三个人最好的交流方式是什么?

很明显,脚本B只能调用脚本C,但是我觉得这种方法缺乏结构和组织。

脚本A也可以引用脚本C,脚本B可以告诉脚本A对脚本C进行操作。

我觉得我应该遵循某种规则,但是我还没有遇到。任何帮助深表感谢!

4 个答案:

答案 0 :(得分:3)

  

很明显,脚本B可以调用脚本C,但是我感觉像这样   方法缺乏结构和组织。

是的。这就是GameObject.SendMessage函数的用途。不幸的是,它很慢,我不推荐它,但是值得一提。

如果您有许多需要与其他对象进行通信的对象,请使用eventdelegate来实现事件管理器。这是正确的方法。您可以找到完整的EventManager实现here

通过它,您可以通过以下方式向事件注册任意数量的功能:

EventManager.StartListening("jump", someFunction);

使用以下方法取消注册事件中的任何功能:

EventManager.StopListening("jump", someFunction);

从那里,您可以在侦听该事件的任何对象上调用该事件:

EventManager.TriggerEvent("jump");

答案 1 :(得分:2)

如果A已经具有对脚本C的引用,则可以在创建A时将此引用传递给B。因此,B可以与C通信,而无需经过A。

Script A:
// variables
     public ScriptC c;

// methods
void SpawnB(){
    // spawn B
    B.setC(c); // B's variable for script C is passed in from A
}

Script B:
// variables
     ScriptC c;
// methods
void setC(ScriptC v){
    c = v;
}

类似的事情。

答案 2 :(得分:0)

您还可以使用不是特定于Unity的ID CustId CustName Status 1 a1 A 1 2 a1 A 2 3 a2 B 1 4 a3 B 1 5 a4 C 1 6 a4 C 2 7 a4 D 2 8 a6 E 1 委托。我喜欢为此使用静态类,但您也可以在现有的一个类中实现它(只要您使用Action成员和方法)

例如

static

这使您的类完全独立(好吧,它们共享MyEvents类)并且易于模块化。

在脚本public static class MyEvents { public static event Action SomeEvent; public static void InvokeSomeEvent() { // Make sure event is only invoked if someone is listening if (SomeEvent == null) return; SomeEvent.Invoke(); } } 中添加“监听器”,例如

C

然后在脚本private void Start() { // It is save to remove a listener also if it wasn't there yet // This makes sure you are not listening twice by accident MyEvents.SomeEvent -= OnSomeEvent; // Add the listener for that event MyEvents.SomeEvent += OnSomeEvent; } private void OnSomeEvent () { // Do something if SomeEvent is invoked } 中的某个地方调用

B

因此MyEvents.InvokeSomeEvent(); 类不必知道或关心谁监听该事件;它只是调用它并关心它自己的事。

另一方面,B或(为事件添加侦听器的任何其他类)不必知道/关心调用来自何处;它只是处理它并执行其工作。

但是请注意,这也使调试变得更加困难,因为要知道调用的来源不再那么容易了;)


注意:您还可以将参数添加到C中,例如

Action

在这种情况下,所有方法都必须同时实现该参数

public static event Action<int> SomeParameterEvent;

public static InvokeSomeParameterEvent(int value) { if(SomeParameterAction == null) return; SomeParameterEvent.Invoke(value); } (侦听器)中,您还必须接收参数

C

当然也可以使用// name can be changed private void OnSomeParameterEvent(int value) { //... }

中的参数来调用它
B

然后您甚至可以更进一步地使用它,而不用值或引用传递完整的MyEvents.InvokeSomeParameterEvent(someInt); 方法作为参数。查看示例here

答案 3 :(得分:0)

如程序员所写,代表和事件通常用于通信。

为了获得更好的结构和组织性,我建议使用MVC模式或您喜欢的任何其他设计模式。在这里,您可以找到一个简单而强大的通知系统的Unity3D MVC实现的绝佳示例:

Unity with MVC by Eduardo Dias da Costa

在该示例中,您无需使用委托/事件进行通信,并且可以使一切井井有条。

引用的教程中使用的一些通信功能,以防不赞成使用该链接:

1。

// Iterates all Controllers and delegates the notification data
   // This method can easily be found because every class is “BounceElement” and has an “app” 
   // instance.
   public void Notify(string p_event_path, Object p_target, params object[] p_data)
   {
      BounceController[] controller_list = GetAllControllers();
      foreach(BounceController c in controller_list)
      {
         c.OnNotification(p_event_path,p_target,p_data);
      }
   }

   // Fetches all scene Controllers.
   public BounceController[] GetAllControllers() { /* ... */ }

2。

 // This class will give static access to the events strings.
class BounceNotification
{
   static public string BallHitGround = “ball.hit.ground”;
   static public string GameComplete  = “game.complete”;
   /* ...  */
   static public string GameStart     = “game.start”;
   static public string SceneLoad     = “scene.load”;
   /* ... */
}

3。

 // Handles the ball hit event
   public void OnNotification(string p_event_path,Object p_target,params object[] p_data)
   {
      switch(p_event_path)
      {
         case BounceNotification.BallHitGround:
            app.model.bounces++;
            Debug.Log(“Bounce ”+app.model.bounce);
            if(app.model.bounces >= app.model.winCondition)
            {
               app.view.ball.enabled = false;
               app.view.ball.GetComponent<RigidBody>().isKinematic=true; // stops the ball
               // Notify itself and other controllers possibly interested in the event
               app.Notify(BounceNotification.GameComplete,this);            
            }
         break;

         case BounceNotification.GameComplete:
            Debug.Log(“Victory!!”);
         break;
      } 
   }

4。

   // Callback called upon collision.
   void OnCollisionEnter() { app.Notify(BounceNotification.BallHitGround,this); }

当然,您仍然可以实现MVC并使用“委托和事件”。这只是显示另一种做事方式。