如果将一个装备装备到玩家身上,就要通过调用属性设置方法来改变玩家的属性值,比如攻击力,暴击率等,这里如果采用工厂模式,将每个属性成员值设置到玩家身上的时候要先判断玩家身上是否包含该属性,并且如果要给装备添加更多的属性增益类型,那么就要在工厂代码中添加对应的属性成员,添加对应的增益属性成员,这样的会很繁琐。而通过特性和反射可以将这一过程简化,虽然判断还是要进行,但是却变得更简洁优雅。
玩家类:
using System.Collections; using System.Collections.Generic; using System.Reflection; using UnityEngine; /// <summary> /// 玩家类 /// </summary> public class Init : MonoBehaviour { [EquipmentAttribute(PlayerAttribute.攻击力)]//表明a是玩家的攻击力 public int a;//攻击力 [EquipmentAttribute(PlayerAttribute.暴击)]//b是玩家的暴击率 public int b;//暴击率 public IEquipt e00; public IEquipt e01; private void Start() { e00.Test(); e01.Test(); e00.ChangePlayerAttribute(this); e01.ChangePlayerAttribute(this); } /// <summary> /// 获取玩家某个属性值,如果玩家的成员中没有这个属性,那么返回0 /// </summary> /// <param name="attribute"></param> /// <returns></returns> public object GetPlayerAttribute(PlayerAttribute attribute) { var type = GetType(); var fields = type.GetFields(); foreach (var field in fields) { var _attribute = field.GetCustomAttribute(typeof(EquipmentAttribute)); if (_attribute != null) { var attr = _attribute as EquipmentAttribute; if (attribute == attr.playerAttribute) { return field.GetValue(this); } } } return 0; } /// <summary> /// 设置玩家某个属性的值 /// </summary> /// <param name="attr"></param> /// <param name="value"></param> public void SetPlayerAttribute(PlayerAttribute attr,int value) { var type = GetType(); var fields = type.GetFields(); foreach (var field in fields) { var _attribute = field.GetCustomAttribute(typeof(EquipmentAttribute)); if (_attribute != null) { var _attr = _attribute as EquipmentAttribute; if (attr == _attr.playerAttribute) { field.SetValue(this, value); } } } } }
装备类:
装备基础类
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.Reflection; /// <summary> /// 装备类 /// </summary> public class IEquipt : MonoBehaviour { [TipAttribute] public int a; public virtual void Test() { } /// <summary> /// 将属性添加到玩家身上 /// </summary> /// <param name="player"></param> public void ChangePlayerAttribute(Init player) { var type = GetType(); foreach(FieldInfo f in type.GetFields()) { var attribute = f.GetCustomAttribute(typeof(EquipmentAttribute)); var equipmentAttribute = attribute as EquipmentAttribute; if (equipmentAttribute == null) continue; var before = player.GetPlayerAttribute(equipmentAttribute.playerAttribute); var after = f.GetValue(this); player.SetPlayerAttribute(equipmentAttribute.playerAttribute, (int)before + (int)after); } } }
装备00
using System.Collections; using System.Collections.Generic; using System.Reflection; using UnityEngine; /// <summary> /// 装备00 /// </summary> public class Equip00 : IEquipt { [EquipmentAttribute(PlayerAttribute.攻击力)] [TipAttribute] public int a0; [TipAttribute] public string b; [EquipmentAttribute(PlayerAttribute.暴击)] [TipAttribute] public int b2; public override void Test() { var type = GetType(); var fields = type.GetFields(); foreach(var field in fields) { var tip_attribute = field.GetCustomAttribute(typeof(TipAttribute)); if (tip_attribute != null) { Debug.Log(field.Name + ": " + field.GetValue(this)); } } } }
装备01
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Reflection; /// <summary> /// 装备01 /// </summary> public class Equip01 : IEquipt { [EquipmentAttribute(PlayerAttribute.攻击力)] public int t; [TipAttribute] public string c; [TipAttribute] public string d; public override void Test() { var type = GetType(); var fields = type.GetFields(); foreach (var field in fields) { var tip_attribute = field.GetCustomAttribute(typeof(TipAttribute)); if (tip_attribute != null) { Debug.Log(field.Name + ": " + field.GetValue(this)); } } } }
特性类:
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 玩家属性 /// </summary> public enum PlayerAttribute { 攻击力, 暴击 } /// <summary> /// 装备特性类 /// </summary> [AttributeUsage(AttributeTargets.Field)] public class EquipmentAttribute : Attribute { public PlayerAttribute playerAttribute;//注解玩家的属性类型,比如是攻击力,还是暴击率 public EquipmentAttribute(PlayerAttribute attr) { playerAttribute = attr; } } /// <summary> /// 提示特性类 /// </summary> [AttributeUsage(AttributeTargets.Field)] public class TipAttribute : Attribute { } public class Attributes : MonoBehaviour { }
参考哔哩哔哩开发者:https://www.bilibili.com/video/BV1nQ4y1T7et
结果如图,从上面的的 代码中可以看出,装备00有攻击力和暴击率,装备01只有攻击力,它们都使用了 ChangePlayerAttribute(t)方法将对应值添加到玩家身上。