unity3d消息机制研究之二--------javascript 的 NotificationCenter

来源:互联网 发布:vue.js ui框架 编辑:程序博客网 时间:2024/06/05 07:38

使用系统自带的方法有一些限制,比如不能在处于不同父级物体之下的两个物体间通讯,也无法传递参数等等,因此,比较好的办法是用NotificationCenter.

这里贴出UnityCommunity wiki 中的post:

点击打开链接

顺便把源码贴在这里,方便查阅:

NotificationCenter.js

//    NotificationCenter is used for handling messages between GameObjects. //    GameObjects can register to receive specific notifications.  When another objects sends a notification of that type, all GameObjects that registered for it and implement the appropriate message will receive that notification. //    Observing GameObjetcs must register to receive notifications with the AddObserver function, and pass their selves, and the name of the notification.  Observing GameObjects can also unregister themselves with the RemoveObserver function.  GameObjects must request to receive and remove notification types on a type by type basis. //    Posting notifications is done by creating a Notification object and passing it to PostNotification.  All receiving GameObjects will accept that Notification object.  The Notification object contains the sender, the notification type name, and an option hashtable containing data. //    To use NotificationCenter, either create and manage a unique instance of it somewhere, or use the static NotificationCenter.  // We need a static method for objects to be able to obtain the default notification center.// This default center is what all objects will use for most notifications.  We can of course create our own separate instances of NotificationCenter, but this is the static one used by all.private static var defaultCenter : NotificationCenter;static function DefaultCenter () {    // If the defaultCenter doesn't already exist, we need to create it    if (!defaultCenter) {        // Because the NotificationCenter is a component, we have to create a GameObject to attach it to.        var notificationObject: GameObject = new GameObject("Default Notification Center");        // Add the NotificationCenter component, and set it as the defaultCenter        defaultCenter = notificationObject.AddComponent(NotificationCenter);    }     return defaultCenter;} // Our hashtable containing all the notifications.  Each notification in the hash table is an ArrayList that contains all the observers for that notification.var notifications: Hashtable = new Hashtable(); // AddObserver includes a version where the observer can request to only receive notifications from a specific object.  We haven't implemented that yet, so the sender value is ignored for now.function AddObserver (observer, name: String) { AddObserver(observer, name, null); }function AddObserver (observer, name: String, sender) {    // If the name isn't good, then throw an error and return.    if (name == null || name == "") { Debug.Log("Null name specified for notification in AddObserver."); return; }    // If this specific notification doens't exist yet, then create it.    if (!notifications[name]) {        notifications[name] = new ArrayList();    }     var notifyList: ArrayList = notifications[name];     // If the list of observers doesn't already contains the one that's registering, then add it.    if (!notifyList.Contains(observer)) { notifyList.Add(observer); }} // RemoveObserver removes the observer from the notification list for the specified notification typefunction RemoveObserver (observer, name: String) {    var notifyList: ArrayList = notifications[name];     // Assuming that this is a valid notification type, remove the observer from the list.    // If the list of observers is now empty, then remove that notification type from the notifications hash.  This is for housekeeping purposes.    if (notifyList) {        if (notifyList.Contains(observer)) { notifyList.Remove(observer); }        if (notifyList.Count == 0) { notifications.Remove(name); }    }} // PostNotification sends a notification object to all objects that have requested to receive this type of notification.// A notification can either be posted with a notification object or by just sending the individual components.function PostNotification (aSender, aName: String) { PostNotification(aSender, aName, null); }function PostNotification (aSender, aName: String, aData) { PostNotification(new Notification(aSender, aName, aData)); }function PostNotification (aNotification: Notification) {    // First make sure that the name of the notification is valid.    if (aNotification.name == null || aNotification.name == "") { Debug.Log("Null name sent to PostNotification."); return; }    // Obtain the notification list, and make sure that it is valid as well    var notifyList: ArrayList = notifications[aNotification.name];    if (!notifyList) { Debug.Log("Notify list not found in PostNotification."); return; }     // Create an array to keep track of invalid observers that we need to remove    var observersToRemove = new Array();     // Itterate through all the objects that have signed up to be notified by this type of notification.    for (var observer in notifyList) {        // If the observer isn't valid, then keep track of it so we can remove it later.        // We can't remove it right now, or it will mess the for loop up.        if (!observer) { observersToRemove.Add(observer);        } else {            // If the observer is valid, then send it the notification.  The message that's sent is the name of the notification.            observer.SendMessage(aNotification.name, aNotification, SendMessageOptions.DontRequireReceiver);        }    }     // Remove all the invalid observers    for (observer in observersToRemove) {        notifyList.Remove(observer);    }} // The Notification class is the object that is send to receiving objects of a notification type.// This class contains the sending GameObject, the name of the notification, and optionally a hashtable containing data.class Notification {    var sender;    var name : String;    var data;    function Notification (aSender,  aName: String) { sender = aSender; name = aName; data = null; }    function Notification (aSender, aName: String, aData) { sender = aSender; name = aName; data = aData; }}

使用非常简单,直接丢在assets里面,项目里的所有脚本就可以使用,不需要加给任何物体。因为它是静态方法。

发送消息端用PostNotification方法,接受消息端用AddObserver方法,并实现这个方法。

使用实例:

场景里建一个cube,给它挂上以下js:

function OnMouseEnter()

{

NotificationCenter.DefaultCenter().PostNotification(this,"Enter");//告诉NotificationCenter鼠标进入

}

再建一个GUIText,脚本如下:

function Awake()

{

NotificationCenter.DefaultCenter().AddObserver(this,"Enter");// 使这个GUI成为一个Observer,这样NotificationCenter就能向其发送信息。

}

function Enter()

{

guiText.text = "something Enter!"; 

}


这样,鼠标进入cube,GUIText内容便显示。

NotificationCenter 使得场景中任意脚本件的通讯成为可能,而且只需要一行代码就能搞定,实在是不可多得的神器。


当然神器不光是传话员这么简单,我们看看Notification这个类:

// The Notification class is the object that is send to receiving objects of a notification type.// This class contains the sending GameObject, the name of the notification, and optionally a hashtable containing data.class Notification {    var sender;    var name : String;    var data;    function Notification (aSender,  aName: String) { sender = aSender; name = aName; data = null; }    function Notification (aSender, aName: String, aData) { sender = aSender; name = aName; data = aData; }}

可见其中有个重载的函数可以传递aData。

加入另外一个GUIText,脚本这样:

function Awake () { NotificationCenter.DefaultCenter().AddObserver(this,"Enter");}function Enter(note:Notification){var messageAcc:String = "从"+note.sender+"接收到一个信息,内容是"+note.data+"信息名称是"+note.name;guiText.text = messageAcc;}

cube发送消息的脚本改成:

NotificationCenter.DefaultCenter().PostNotification(this,"Enter","hello");//发送一个消息hello

鼠标移入cube:



这就厉害了,快无所不能了。


最后,aData传递的是string类型,让我们传递一个int过去看看

新建一个GUIText,脚本如下:

function Awake () { NotificationCenter.DefaultCenter().AddObserver(this,"Enter");}function Enter(note:Notification){var dataTimes:int = note.data;//转换string为intguiText.text = "mouseOver"+dataTimes+"times";}

cube发送消息的脚本改成:

var clickTimes:int=0;function OnMouseEnter(){clickTimes++;NotificationCenter.DefaultCenter().PostNotification(this,"Enter",clickTimes);//注意clickTime是按字符串传送}


原创粉丝点击