香雨站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 95|回复: 0

游戏开发 Delegate、Action、Event

[复制链接]

1

主题

4

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2023-2-9 17:57:11 | 显示全部楼层 |阅读模式




总结学习下委托和事件相关知识与用法

  • Delegate很灵活,特殊类型需求
  • Action无返回值,可带参数
  • Func有返回值,可带参数
  • Predicate通常用于集合判断是否符合条件
  • Event事件封装好利于项目管理
  • 可以多使用Action或者Func与Event结合
  • UnityAction继承自Action,就是封装好的委托,一模一样
  • UnityEvent不带参数直接实例化,带参数是抽象类需要自己声明类继承使用
1. Delegate

  • 定义

  • 前面需要声明公有还是私有,类似函数
  • 增加关键词delegate,设定返回值类型,设置参数
  • 参数与返回值类型需与委托函数相同

//无参数无返回值     public delegate void testDelegate();     private testDelegate TestDelegate;       //有参数有返回值     public delegate bool testDelegate(int i);     private testDelegate TestDelegate;



  • 使用

  • 简单使用

void Start()     {         //TestDelegate = new testDelegate(TestFunction);         //TestDelegate += TestFunction;         TestDelegate = TestFunction;//赋值,这句话与上两句话是等价的         TestDelegate += TestFunction2;          TestDelegate();//直接调用     }       void TestFunction()     {         Debug.Log("TestFunction");     }       void TestFunction2()     {         Debug.Log("TestFunction2");     }





  • 匿名函数
            缺点是无法移除委托中的匿名方法

void Start()     {         TestDelegate = delegate (int i) {             return true;         };          TestDelegate();     }



  • Lambda
            缺点是无法移除委托中的匿名方法

void Start()     {         TestDelegate += (int i) => {             return true;         };          TestDelegate();     }


2. Action

  • 无返回值的委托,可通过泛型传递参数

Action:         public delegate void Action();     Action<T1,T2>:         public delegate void Action<T1,T2> (T1 arg1, T2 arg2);



  • 使用

public Action<bool> testAction;     void Start()     {         testAction+= (bool m) =>Debug.Log(m);         testAction(true);     }


<hr/>3. Func

  • 有返回值的委托,可通过泛型传递参数
  • 定义的泛型参数的最后一个参数类型是委托的返回值类型

Func< TResult >:         public delegate TResult Func< TResult > ();     Func< T1,T2,TResult >:         public delegate TResult Func< T1, T2, TResult > (T1 arg1, T2 arg2);



  • 使用

public Func<int,bool> testFunc;     void Start()     {         testFunc += (int i) => { return i>0 } ;         testFunc(1);     }


<hr/>4. Predicate

  • 表示定义一组条件并确定指定对象是否符合这些条件的方法
  • 此方法常在集合的查找中被用到,如:数组,正则拼配的结果集中被用到,更加快捷方便

public Predicate<int> tsetPredicate;     void Start()     {         tsetPredicate = (int i) => { return i>0 } ;     }      void StartPredicate()     {         int[] myNum = new int[8] { -12, 33, -89, 21, 15, -29, 40, 52 };         int[] myResult = Array.FindAll(myNum, tsetPredicate);     }


<hr/>5. Event

  • 定义

  • 事件时属于类的成员,C#中的事件处理实际上是一种具有特殊签名的delegate
  • 委托属于一个定义
  • 事件主要是从封装性和易用性上去考虑,并且事件应该由事件发布者触发,而不应该由客户端来触发


  • 使用1:一个事件直接添加这四个方法 VS 一个事件添加两个委托,每个委托分别还添加两个方法

public delegate void Delegate1(string str);     public Delegate1 D1;     public Delegate1 D2;     public event Delegate1 E;      void Start()     {         D1 += P1;         D1 += P2;          D2 += P3;         D2 += P4;          //单独委托添加方法,单独委托单独调用         //D1("1");         //D2("1");          //事件添加多个委托,通过事件调用         //E += D1;         //E += D2;         //E.Invoke("1");          //事件添加多个方法,通过事件调用         E += P1;         E += P2;         E += P3;         E += P4;         E.Invoke("1");     }      void P1(string s)     {         print(s + "!");     }      void P2(string s)     {         print(s + "!!!");     }      void P3(string s)     {         print(s + "-");     }      void P4(string s)     {         print(s + "---");     }



  • 使用2:一个事件直接添加这四个方法 VS 一个事件添加两个委托,每个委托分别还添加两个方法

// 定义委托 public delegate void Delegate1(int i);  // 定义事件订阅者 public class Subscriber {     public void P1(int i) {         print(i);     } }  // 定义事件发布者 public class Publishser {     private int count;     public Delegate1 D1;         // 声明委托变量     //public event Delegate1 E1; // 声明一个事件      public void DoSomething() {         if (D1!= null) {    // 触发事件             count++;             D1(count);         }     } }  class Program {     static void Main(string[] args) {         Publishser pub = new Publishser();         Subscriber sub = new Subscriber();                  pub.D1 += new Delegate1(sub.P1);          //按照规范应该这样触发事件         pub.DoSomething();         //但是也可以这样来触发事件,这样不是很恰当         pub.D1(100);     } }


<hr/>6. UnityAction && UnityEvent

  • UnityAction
            继承自Action,就是封装好的委托,一模一样
  • UnityEvent
            可以拖拽,比较方便,用Serializable序列化,可以在Editor中显示

  • 不带参数的不是抽象类,可以直接实例化

public class Test{       public UnityEvent myEvent = new UnityEvent();   }



  • 带参数的是抽象类,不能直接使用,需要自己声明一个类继承

//使用Serializable序列化IdolEvent, 否则无法在Editor中显示   [System.Serializable]   public class MyEvent: UnityEvent<string> {}   public class Test{       public MyEvent myEvent = new MyEvent();   }


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|香雨站

GMT+8, 2025-3-15 06:19 , Processed in 0.474359 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.. 技术支持 by 巅峰设计

快速回复 返回顶部 返回列表