我可以只有没有代表的活动吗?

时间:2018-01-25 11:29:24

标签: c# unity3d events delegates

我有一个玩家参加活动"拍摄"。如果玩家射击子弹我手动触发事件。一个不同的GameObject有一个脚本,如果监听器和if事件被触发,则监听器执行特定的方法。我是新事物。我真的不需要代表,只有事件。我在网上教自己编程,但到处都是如何只使用代表的事件。

我是否可以只有没有委托的事件,如果是,如何声明这样的事件?

3 个答案:

答案 0 :(得分:2)

事件是具有安全约束的委托。

  • 您只能从持有它的类中调用事件。
  • 您只能注册/取消注册课外活动(仅限+ = / - =)
  • 您无法将参数作为参数传递
  • 您只能从包含该事件的类中清除事件(eventName = null)

偏离主题:UnityEvent不是真实事件,它是一个包含委托列表(Action)的类。

当你调用一个事件(或一个委托)时,你应该总是检查是否为null,因为你永远不知道该引用是否指向一个对象。你不需要使用UnityEvent,因为我提到它不是真正的事件,然后如果集合是空的,没有任何事情发生。

public delegate void MyDel();
// The two following behaves the same
public MyDel myDel;
public Action myAction;

public event Action myEvent;

void Start(){
     if(myAction != null){ myAction(); }
     if(myEvent != null) { myEvent(); }
     if(myEvent != null) { myEvent.Invoke(); }
}

这些是相同的事情,但是选择一个或另一个是基于你想做什么。

在另一个类中考虑以下内容:

void Start(){
    refToClass.myAction = MyMethod;
    refToClass.myEvent += MyMethod;
}
void MyMethod(){}

第一种情况将删除附加到委托的所有方法,然后MyMethod是唯一可以监听的方法。 该事件不允许这样,只允许+ = / - =,因此您只能删除/添加方法而不影响其他方法。

答案 1 :(得分:1)

委托基本上描述了一种功能类型。 事件是一个钩子,当事件发生时,会调用与给定函数类型匹配的已注册函数。

将这两个简化的定义放在一起,委托也是事件的描述符,因此您不能拥有没有相关委托的事件。

无论如何,您不必为您声明的每个事件声明新的委托。相反,您可以使用任何预先存在的代理,例如EventHandlerEventHandler<TEventArgs>甚至任何Action重载,在每种情况下选择最适合您的代理。

答案 2 :(得分:0)

我相信你在技术上可以拥有没有委托的事件,如answers here中所述。

但是,代理人习惯于从引发事件的位置传递信息。没有它,程序不知道调用事件的位置以及要传递的信息。

这是一个good introduction,有很多关于SO的例子可以帮助解决利基案例。现在,如果您正在进行自学编程,我建议您先学习该模式并使其正常工作,然后再担心为什么代表和事件总是成对出现。

public delegate void ShootEventHandler(object sender, ShootEventArgs e);
public class ShootEventArgs
{
    public ShootEventArgs(string s) { Text = s; }
    public String Text {get; private set;} // readonly
}

它通常会在发件人中传递this,然后新建您创建的代理。如果你想打电话给你,你就会有这样的事情。

var handler = this.Shoot; // Get the event you want to fire
handler?.Invoke(this, new ShootEventArgs("Bang")); // tell eveything interested "Bang"

对拍摄事件感兴趣的GameObjects可以订阅如下信息:

this.Player.Shoot += this.ShootHandler;
public void ShootHandler(object sender, ShootEventArgs e) // common to use e for event args
{
    Console.WriteLine(e.Text); // print "Bang"
}