经常遇到需要监控某一个值的情况。
以金币(Coin)举例,某Text组件始终显示Coin值。可以在Coin值改变的时候,设置Text。
但如果有更多组件关心Coin值的变化,Coin改变时,挨个去修改组件,麻烦且易出错。
一个简单的解决思路:Subscribe/Unscribe,组件订阅Coin值,注册委托。当Coin改变时,调用委托。
定义一个基类,实现Subscribe/UnSubscribe功能。
using System.Collections.Generic;
using UnityEngine.Events;
public abstract class BaseDataSingleton<T> where T : class, new()
{
#region 单例实现
private static T instance;
public static T Instance
{
get
{
return instance ??= new T();
}
}
#endregion
private readonly Dictionary<string, UnityAction> _DicAction = new();
public void Subscribe(string attriName, UnityAction action)
{
if(!_DicAction.ContainsKey(attriName)){
_DicAction.Add(attriName,null);
}
_DicAction[attriName]+=action;
action?.Invoke();
}
public void UnSubscribe(string attriName, UnityAction action)
{
if(_DicAction.ContainsKey(attriName)){
_DicAction[attriName] -= action;
}
}
protected void Fire(string attriName)
{
if(_DicAction.ContainsKey(attriName)){
_DicAction[attriName]?.Invoke();
}
}
}
数据类中,值改变时,调用Fire(),通知属性变化:
public class GameData : BaseDataSingleton<GameData>
{
private int _coin = 0;
public int Coin
{
get => _coin;
set
{
if (_coin != value)
{
_coin = value;
Fire("Coin");
}
}
}
}
将Text绑定到Coin属性:
//订阅属性
GameData.Instance.Subscribe("Coin",OnCoinChange);
//取消订阅
GameData.Instance.UnSubscribe("Coin",OnCoinChange);
//显示值
private void OnCoinChange(){
_Text.text = GameData.Instance.Coin+"";
}
//当不需要取消订阅时,可简化写法
GameData.Instance.Subscribe("Coin",()=>{
Text.text = GameData.Instance.Coin+"";
});