解析ET6框架的数值组件

1.介绍

在数值属性多,技能buff复杂且灵活性高的游戏,必须要有一套灵活的数值结构来搭配。 数值结构设计好了,实现技能系统就会非常简单,否则就是一场灾难。

2.核心代码解析

1.NumericType.cs

增加人物属性字段

    public enum NumericType
    {
		Max = 10000,

		Speed = 1000,
		SpeedBase = Speed * 10 + 1,
	    SpeedAdd = Speed * 10 + 2,
	    SpeedPct = Speed * 10 + 3,
	    SpeedFinalAdd = Speed * 10 + 4,
	    SpeedFinalPct = Speed * 10 + 5,
     }

2.NumericComponent.cs

获取,设置,刷新属性

        //设置属性值
        public long this[NumericType numericType]
		{
			get
			{
				return this.GetByKey((int) numericType);
			}
			set
			{
				long v = this.GetByKey((int) numericType);
				if (v == value)
				{
					return;
				}

				NumericDic[(int)numericType] = value;
                
				Update(numericType);
			}
		}
        //获取属性值
		private long GetByKey(int key)
		{
			long value = 0;
			this.NumericDic.TryGetValue(key, out value);
			return value;
		}
        //计算变更值并发出事件
        public void Update(NumericType numericType)
		{
			if (numericType < NumericType.Max)
			{
				return;
			}
			int final = (int) numericType / 10;
			int bas = final * 10 + 1; 
			int add = final * 10 + 2;
			int pct = final * 10 + 3;
			int finalAdd = final * 10 + 4;
			int finalPct = final * 10 + 5;

			// 一个数值可能会多种情况影响,比如速度,加个buff可能增加速度绝对值100,也有些buff增加10%速度,所以一个值可以由5个值进行控制其最终结果
			// final = (((base + add) * (100 + pct) / 100) + finalAdd) * (100 + finalPct) / 100;
			long old = this.NumericDic[final];
			long result = (long)(((this.GetByKey(bas) + this.GetByKey(add)) * (100 + this.GetAsFloat(pct)) / 100f + this.GetByKey(finalAdd)) * (100 + this.GetAsFloat(finalPct)) / 100f * 10000);
			this.NumericDic[final] = result;
			Game.EventSystem.Publish(new EventType.NumbericChange()
			{
				Parent = this.Parent, 
				NumericType = (NumericType) final,
				Old = old,
				New = result
			});

3.NumericWatcherComponent.cs

监视数值变化组件,分发监听

       //缓存所有numericWatcherAttribute特性到字典
         public void Load()
		{
			this.allWatchers = new Dictionary<NumericType, List<INumericWatcher>>();

			HashSet<Type> types = Game.EventSystem.GetTypes(typeof(NumericWatcherAttribute));
			foreach (Type type in types)
			{
				object[] attrs = type.GetCustomAttributes(typeof(NumericWatcherAttribute), false);

				foreach (object attr in attrs)
				{
					NumericWatcherAttribute numericWatcherAttribute = (NumericWatcherAttribute)attr;
					INumericWatcher obj = (INumericWatcher)Activator.CreateInstance(type);
					if (!this.allWatchers.ContainsKey(numericWatcherAttribute.NumericType))
					{
						this.allWatchers.Add(numericWatcherAttribute.NumericType, new List<INumericWatcher>());
					}
					this.allWatchers[numericWatcherAttribute.NumericType].Add(obj);
				}
			}
		}
        //分发变更类型的事件
		public void Run(NumericType numericType, long id, long value)
		{
			List<INumericWatcher> list;
			if (!this.allWatchers.TryGetValue(numericType, out list))
			{
				return;
			}
			foreach (INumericWatcher numericWatcher in list)
			{
				numericWatcher.Run(id, value);
			}
		}

 

3.使用

1.在NumericType.cs中写需要的属性字段枚举

     public enum NumericType
    {
		Max = 10000,

		Speed = 1000,
		SpeedBase = Speed * 10 + 1,
	    SpeedAdd = Speed * 10 + 2,
	    SpeedPct = Speed * 10 + 3,
	    SpeedFinalAdd = Speed * 10 + 4,
	    SpeedFinalPct = Speed * 10 + 5,
    }

2.设置属性

                    NumericComponent numericComponent = unit.AddComponent<NumericComponent>();
                    numericComponent.Set(NumericType.Speed, 6f); // 速度是6米每秒
                    numericComponent.Set(NumericType.AOI, 15000); // 视野15米

3.设置属性发出的事件

    public class NumericChangeEvent_NotifyWatcher: AEvent<EventType.NumbericChange>
	{
		protected override async ETTask Run(EventType.NumbericChange args)
		{
			NumericWatcherComponent.Instance.Run(args.NumericType, args.Parent.Id, args.New);
			await ETTask.CompletedTask;
		}
	}

4.监测对应类型的数值变化

    [NumericWatcher(NumericType.Speed)]
	public class NumericWatcher_Hp_ShowUI : INumericWatcher
	{
		public void Run(long id, long value)
		{
		}
	}

上一篇:CF5D--Follow Traffic Rules翻译


下一篇:网速小于某个值关机