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)
{
}
}