游戏 Notification

        在游戏中,个模块间数据交互更新甚为常见。比如我们购买了一件装备,我们在背包里穿上这件装备,

对应的游戏场景中需要替换上新的服装模型或者特效等等。为了实现这种功能,我们需要一个通知的机制,

告诉对应的模块取改变状态。新建一个脚本命名为 NotificationCenter

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SSGame {

public static class TypeDefinition {
    public static string NOTICE_COLOR_CHANGE = "notice_color_change";
}


public delegate void NotificationDelegate(params object[] param);   //广播委托也就是广播需要做的事情//

public class NotificationObserver {
    public string name;    //每种广播都有自己的名字//
    public object target;   //这个就代表的谁的广播//
    public NotificationDelegate selector;  //这个呢就是广播要做的事情了//

    public NotificationObserver(string _name, object _target, NotificationDelegate _selector) {
        SetAttr(_name, _target, _selector);
    }
    public void SetAttr(string _name, object _target, NotificationDelegate _selector) {
        this.name = _name;
        this.target = _target;
        this.selector = _selector;
    }

    //广播唤醒//
    public void PerformSelector(params object[] param) {
        if(target != null) {
            selector.Invoke(param);
        }
    }

}
//调度中心需要能随时注册新的广播,删除废弃广播,唤醒需要执行的广播
public class NotificationCenter {
    //在一个系统中只需要一个广播调度//
    private static NotificationCenter instance;

    //同一个名称,同一个目标只会有一个广播//
    //比如每个村子只有一个通知开会的广播,但是还会有其他功能的广播//
    private Dictionary<string, List<NotificationObserver>> dict;

    public NotificationCenter() {
        dict = new Dictionary<string, List<NotificationObserver>>();
    }

    public static NotificationCenter Share() {
        if(instance == null) {
            instance = new NotificationCenter();
        }
        return instance;
    }

    //新增的广播必须要在广播中心来注册//
    public void RigistObsever(string name, object target, NotificationDelegate selector) {
        List<NotificationObserver> delegateList;
        if(!dict.TryGetValue(name, out delegateList)) {
            delegateList = new List<NotificationObserver>();
            NotificationObserver observer = new NotificationObserver(name, target, selector);
            delegateList.Add(observer);
            dict.Add(name, delegateList);
        } else {
            for(int i = delegateList.Count - 1; i >= 0; i--) {
                if(delegateList[i].name == name && delegateList[i].target == target) {
                    //已经存在了//
                    return;
                }
            }
            NotificationObserver observer = new NotificationObserver(name, target, selector);
            observer.SetAttr(name, target, selector);
            delegateList.Add(observer);
        }
    }


    //既然有注册必然需要消除,为内存优化考虑//
    public void UnRigistObsever(string name, object target) {
        List<NotificationObserver> delegateList;
        if(!dict.TryGetValue(name, out delegateList)) {
            return;
        }
        for(int i = delegateList.Count - 1; i >= 0; i--) {
            if(delegateList[i].name == name && delegateList[i].target == target) {
                delegateList.RemoveAt(i);
                break;
            }
        }
    }

    //还需要一个广播播放的机制//
    public void PostNotification(string name, params object[] obj) {
        List<NotificationObserver> delegateList;
        if(!dict.TryGetValue(name, out delegateList)) {
            return;
        }
        for(int i = delegateList.Count - 1; i >= 0; i--) {
            delegateList[i].PerformSelector(obj);
        }
    }
}

}
以下是一个简单的粒子,我们通过点击按钮来随机一个颜色来模拟换装。我们建立一个UI 上面一个按钮用来点击随机颜色。场景中放两个模型,模型上附着同一个材质球。然后在UI上挂载脚本UINoticeForm模型的控制节点上增加脚本SceneNotice
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


namespace SSGame {
public class UINoticeForm : MonoBehaviour {

    public Button RandomBtn;

    void Start() {
        RandomBtn.onClick.AddListener(() => {
            RandomColor();
        });
    }

    private void RandomColor() {
        float r, g, b;
        r = Random.Range(0f, 1f);
        g = Random.Range(0f, 1f);
        b = Random.Range(0f, 1f);
        Color color = new Color(r, g, b);
        NotificationCenter.Share().PostNotification(TypeDefinition.NOTICE_COLOR_CHANGE, color);
    }

}

}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SSGame {
public class SceneNotice : MonoBehaviour {

    public GameObject[] objects;

    void OnEnable() {
        NotificationCenter.Share().RigistObsever(TypeDefinition.NOTICE_COLOR_CHANGE, this, ColorChange);
    }

    void OnDisable() {
        NotificationCenter.Share().UnRigistObsever(TypeDefinition.NOTICE_COLOR_CHANGE, this);
    }

    private void ColorChange(object[] objs) {
        if(objs.Length < 1)
            return;
        Color color = (Color)objs[0];
        for(int i = 0; i < objects.Length; i++) {
            objects[i].transform.GetComponent<MeshRenderer>().material.color = color;
        }
    }

}
}

运行结果

  


猜你喜欢

转载自blog.csdn.net/struugle_guy/article/details/80510013