Unity中的人物buff状态的实现

    技术2023-05-26  77

    最近在考虑怎么写游戏中人物的技能与buff状态,在一些论坛里搜索了一些帖子和资料,但是讲的清楚明白的感觉比较少,这里讲一下如何最简单地实现游戏中人物技能和buff的实现。

    实现思路

    在游戏中Buff的作用是使人物产生被动的效果影响。比如提升人物的属性、增加人物判定成功的概率、在动作执行时附加额外动作等。

    实现的思路如下:

    编写ScriptableObject的子类BuffData,以创建保存Buff的id、图标、介绍等信息的asset文件;创建可持有BuffData对象的父类IBuff,其子类的对象将作为玩家在游戏进行中持有的Buff;在IBuff类中设置三个函数BuffStart、BuffEnd、BuffEffect,分别用于Buff添加、Buff消除、Buff触发。制作管理类BuffManager,声明添加Buff、消除Buff、层数叠加等管理方法。

    使用委托实现buff触发

    对于设计完备的游戏而言,在某一动作下可能触发的Buff数量可能是非常庞大的。如果给每一种buff都设置一个bool变量,每一次操作都对所有的变量进行判断,无论是代码的冗余量还是程序的运行效率都是非常糟糕的。

    因此,可以使用C#中的委托来实现Buff功能的动态添加与消除:

    在BuffManager类中声明buff触发的委托buffCall;当Buff被添加时,将IBuff类中的Buff触发函数BuffEffect添加至设置好的委托buffCall中;在需要触发的动作的方法中调用buffCall。

    具体的Unity委托用法可以参考我的这篇博文 C#的委托类(2分钟了解委托用法)

    整个系统的结构如图:

    代码编写

    BuffData类:

    /// <summary> /// 保存Buff的各项数据,如最高等级、持续时间、效果值等 /// </summary> [CreateAssetMenu(menuName = "BuffData", fileName = "buff")] public class BuffData : ScriptableObject { public int id; public string buffName; public int maxLevel; public float[] buffValue = new float[10]; public float[] lastTime = new float[10]; public float restTime; public Sprite buffIcon; [TextArea(2, 3)] public string description; }

    IBuff类:

    /// <summary> /// Buff类的父类,管理buff的变量和通用方法 /// 包括Buff的初始化、升级等 /// </summary> public class IBuff { public int buffLevel; public BuffData data; //初始化,获取对应BuffData,输入至IBuff子类 public IBuff() { buffLevel = 0; } //触发类buff单次发生 public virtual void BuffEffect() { } //状态类buff开始 public virtual void BuffStart() { } //状态类buff结束 public virtual void BuffEnd() { } public void BuffLevelUp() { //不能超过最大等级 if (buffLevel >= data.maxLevel) { return; } buffLevel++; } //获取buff的data数据 public void SetBuffData(BuffData inputdata) { if (this.data != null || inputdata == null) { return; } this.data = inputdata; } }

    BuffManager类:

    /// <summary> /// 管理角色拥有的buff /// </summary> public class BuffManager : MonoBehaviour { //Player相关Manager类的都做成单例模式 public static BuffManager instance; public IBuff[] buffs; public int buffQuantity; //buff执行效果的委托类 public delegate void BuffCall(); public BuffCall buffcall; void Awake() { if (instance == null) { instance = this; } if (instance != this) { Destroy(this); } DontDestroyOnLoad(this.gameObject); } // Start is called before the first frame update void Start() { buffs = new IBuff[5]; buffcall = delegate() { }; buffQuantity = 0; } //添加Buff public bool AddBuff(IBuff buff) { //寻找数组中的空位,添加buff for (int i = 0; i < buffs.Length; i++) { if (buffs[i] == null) { buffs[i] = buff; buffcall += buffs[i].BuffEffect; //添加响应函数 buffQuantity++; buffs[i].BuffStart(); return true; } //存在相同buff--buff升级 else if (buffs[i].id == buff.id) { buffs[i].BuffEnd(); //以防因为数据变化产生的bug buffs[i].BuffLevelUp(); buffs[i].BuffStart(); return true; } } return false; } //删除指定位置的Buff public bool RemoveBuff(int index) { //如果已经为空则不用进行 if (buffs[index] == null) { return false; } buffs[index].BuffEnd(); buffcall -= buffs[index].BuffEffect; //删除响应函数 buffQuantity--; //如果删除的位置不在末尾,则剩余buff队列前移 while (index < buffs.Length) { buffs[index] = null; buffs[index] = index + 1 >= buffs.Length ? null : buffs[index + 1]; index++; } return true; } }

    总结

    本文分享的内容就到这里,总的来说只是提供了一个最简单的buff实现思路,在这个基础上可以增加的内容包括且不限于:

    增加响应函数和buff委托的种类,以实现buff在不同行为时的触发响应;编写协程实现buff的计时功能;在BuffEffect方法中也可以结合工厂类和对象池制作buff触发的特效。

    本文内容更是我自己在开发过程中的一些学习的过程的思路,如果这篇文章有帮助到你,麻烦顺手在下面点个赞,谢谢!

    Processed: 0.013, SQL: 9