[Unity3D] 04 - Event Manager

message消息管理

脚本与GameObject的关系

被显式添加到 Hierarchy 中的 GameObject 会被最先实例化,GameObject 被实例化的顺序是从下往上

GameObject 被实例化的同时,加载其组件 component 并实例化,

如果挂载了脚本组件,则实例化脚本组件时,将调用脚本的 Awake 方法,组件的实例化顺序是也是从下往上

在所有显式的 GameObject 及其组件被实例化完成之前,游戏不会开始播放帧。

当 GameObject 实例化工作完成之后,将开始播放游戏帧。每个脚本的第一帧都是调用 Start 方法,其后每一帧调用 Update,而且每个脚本在每一帧中的调用顺序是从下往上

总结:被挂载到 GameObject 下面的脚本会被实例化成 GameObject 的一个成员。

 

Unity 3种message消息管理使用

Ref: http://blog.csdn.net/u011484013/article/details/51487936

  1. BroadcastMessage(<接收函数名>)         广播消息
  2. SendMessage(<接收函数名>)                 发送消息
  3. SendMessageUpwards(<接收函数名>)   向上发送消息

 

举个例子:

MonoBehaviour 是 Unity 中所有脚本的基类,

  • 如果你使用JS的话,脚本会自动继承MonoBehaviour。
  • 如果使用C#的话,你需要显式继承MonoBehaviour。

 

  • 示范:

 

  • 发送消息
using UnityEngine;
using System.Collections;

public class xx1 : MonoBehaviour
{
    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 100, 50), "发送1"))  
        {
            SendMessage("myTest");      # <-- button 1 向当前对象挂载的所有脚本上面发送消息
     }
     if (GUI.Button(new Rect(10, 150, 100, 50), "发送2"))
        {
            BroadcastMessage("myTest");    # <-- button 2 朝物体和所有子物体发送消息
        }

        if (GUI.Button(new Rect(10, 200, 100, 50), "发送3"))
        {
            SendMessageUpwards("myTest");  # <-- button 3 朝物体和上级父物体发送信息
        }
    }
}
View Code
  • 接收消息
using UnityEngine;
using System.Collections;

public class XXX : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }

    void OnDrag(Vector2 delta)
    {
        Debug.Log("-------OnDrag--------");
    }

    public void myTest() {
        Debug.Log("this is a methord:" + gameObject.name);   
    }
}
View Code

 

 

EventManager的两种简单实现方式

From: http://blog.csdn.net/u010989951/article/details/79051299

第一种、调用Unity的事件系统来进行封装,

另一种、使用C#的事件与委托机制实现。

 

这里讲解第一种,即采用Unity事件系统API来实现;第二种详见原链接。

  • EventManager 定义
using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;  
using UnityEngine.Events;  

public class EventManager  
{  
    private Dictionary<string, UnityEvent> eventDictionary=new Dictionary<string, UnityEvent>();  
    private static EventManager eventManager = new EventManager();  
    private EventManager()  
    {  
  
    }  
public static EventManager GetInstance { get { return eventManager; } }
public void StartListening(string eventName, UnityAction listener) { UnityEvent thisEvent = null; if (eventManager.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent.AddListener(listener); // 给event [UnityEvent]附上listener } else { thisEvent = new UnityEvent(); thisEvent.AddListener(listener); eventManager.eventDictionary.Add(eventName, thisEvent); } } public void StopListening(string eventName, UnityAction listener) { if (eventManager == null) return; UnityEvent thisEvent = null; if (eventManager.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent.RemoveListener(listener); } } public void TriggerEvent(string eventName) { UnityEvent thisEvent = null; if (eventManager.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent.Invoke(); } } }

 

  • Event 注册
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using System;

public class EventTest : MonoBehaviour
{
    private Event_CallBack someListener;
    void Awake()
    {
        someListener = new Event_CallBack(SomeFunction);
    }

    void OnEnable()
    {
        EventManager.GetInstance.StartListening("test",    someListener);
        EventManager.GetInstance.StartListening("Spawn",   SomeOtherFunction);
        EventManager.GetInstance.StartListening("Destroy", SomeThirdFunction);
    }
    void OnDisable()
    {
        EventManager.GetInstance.StopListening("test",    someListener);
        EventManager.GetInstance.StopListening("Spawn",   SomeOtherFunction);
        EventManager.GetInstance.StopListening("Destroy", SomeThirdFunction);
    }

    void SomeFunction(object sender)
    {
        Debug.Log("Some Function was called!");
    }

    void SomeOtherFunction(object sender)
    {
        Debug.Log("Some Other Function was called!");
    }

    void SomeThirdFunction(object sender)
    {
        Debug.Log("Some Third Function was called!");
    }
}

 

  • Event 触发
using UnityEngine;  
using System.Collections;  
  
public class EventTriggerTest : MonoBehaviour  
{  
    void Update()  
    {  
        if (Input.GetKeyDown("q"))  
        {  
            EventManager.GetInstance.TriggerEvent("test");  
        }  
  
        if (Input.GetKeyDown("o"))  
        {  
            EventManager.GetInstance.TriggerEvent("Spawn");  
        }  
  
        if (Input.GetKeyDown("p"))  
        {  
            EventManager.GetInstance.TriggerEvent("Destroy");  
        }  
  
        if (Input.GetKeyDown("x"))  
        {  
            EventManager.GetInstance.TriggerEvent("Junk");  
        }  
    }  
}  

 

  • UnityAction和UnityEvent的用法详解

Ref: http://blog.csdn.net/inlet511/article/details/46822907

  1. UnityAction本质上是delegate,且有数个泛型版本(参数最多是4个),一个UnityAction可以添加多个函数 (多播委托)。

  2. UnityEvent本质上是继承自UnityEventBase的类,它的AddListener()方法能够注册UnityAction,RemoveListener能够取消注册UnityAction,还有Invoke()方法能够一次性调用所有注册了的UnityAction。UnityEvent也有数个泛型版本(参数最多也是4个),但要注意的一点是,UnityAction的所有带参数的泛型版本都是抽象类(abstract),所以如果要使用的话,需要自己声明一个类继承之,然后再实例化该类才可以使用。

 

不使用带参数的UnityEvent:

using UnityEngine;
using System.Collections;
using UnityEngine.Events;

public class UnityActionAndEvent : MonoBehaviour {

    public UnityAction action;
    public UnityEvent myEvent = new UnityEvent();

    void Start()
    {       
        action  = new UnityAction(MyFunction);
        action += MyFunction2;
        myEvent.AddListener(action);
    }

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.P))
        {
            myEvent.Invoke();
        }
    }

    public void MyFunction()
    {
        print ("Hello: ");
    }

    public void MyFunction2()
    {
        print ("Hello2: ");
    }
}

 

使用带参数的UnityEvent:

using UnityEngine;
using System.Collections;
using UnityEngine.Events;

//因为UnityEvent<T0>是抽象类,所以需要声明一个类来继承它
public class MyEvent:UnityEvent<int>{}

public class UnityActionWithParameter : MonoBehaviour {

    public MyEvent myEvent = new MyEvent();
    public UnityAction<int> action;

    void Start () {
        action  = new UnityAction<int>(MyFunction);
        action += MyFunction2;
        myEvent.AddListener(action);
    }   

    void Update () {
        if(Input.GetKeyDown(KeyCode.A))
        {
            myEvent.Invoke(10);
        }
    }

    public void MyFunction(int i)
    {
        print (i);
    }
    public void MyFunction2(int i)
    {
        print(i*2);
    }
}

Unity中通过面板中添加的Listener和通过脚本添加的Listener实际上是两种不同类型的Listener:

  1. 在脚本中通过AddListener()添加的是一个0个参数的delegate(UnityAction)回调。是不可序列化的,在Inspector中是无法看到的。这种Listener是常规Listener。
  2. 在Inspector中添加的则是永久性的Listener(persistent listener)。他们需要指定GameObject、方法以及方法需要的参数。他们是序列化的,用脚本是无法访问到的。

 

添加任意多个参数的函数

另外在脚本中使用lamda表达式来添加listener是非常方便的。 

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class EventAndLamda : MonoBehaviour {

    void Start () { 
        //lamda方式可以添加包含任意参数的函数,非常方便
        GetComponent<Button>().onClick.AddListener( ()=>{
//此处其实可以直接写Myfuction(.....),因为是同一个脚本里的函数 //这样写是为了说明调用其他组件中的函数也是可以的。如果有其他组件的引用,可以直接写: //someReference.theMethod(arguments);
this.GetComponent<EventAndLamda>().MyFunction(10,20.0f,new Vector3(1,1,1)); } ); } public void MyFunction(int i, float f, Vector3 v) { print (i.ToString()+"\n" + f.ToString() + "\n" + v.ToString()); } }

 

 

Package: UnityEditor.Events

Class: UnityEventTools

Description: Editor tools for working with persistent UnityEvents.

AddBoolPersistentListener Adds a persistent, preset call to the listener.
AddFloatPersistentListener Adds a persistent, preset call to the listener.
AddIntPersistentListener Adds a persistent, preset call to the listener.
AddObjectPersistentListener Adds a persistent, preset call to the listener.
AddPersistentListener Adds a persistent, call to the listener. Will be invoked with the arguments as defined by the Event and sent from the call location.
AddStringPersistentListener Adds a persistent, preset call to the listener.
AddVoidPersistentListener Adds a persistent, preset call to the listener.
RegisterBoolPersistentListener Modifies the event at the given index.
RegisterFloatPersistentListener Modifies the event at the given index.
RegisterIntPersistentListener Modifies the event at the given index.
RegisterObjectPersistentListener Modifies the event at the given index.
RegisterPersistentListener Modifies the event at the given index.
RegisterStringPersistentListener Modifies the event at the given index.
RegisterVoidPersistentListener Modifies the event at the given index.
RemovePersistentListener Removes the given function from the event.
UnregisterPersistentListener Unregisters the given listener at the specified index.

 

 

 

 

 

posted @ 2018-02-14 13:45  郝壹贰叁  阅读(1132)  评论(0编辑  收藏  举报