失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 【Unity】动作游戏开发实战详细分析-06-技能系统设计

【Unity】动作游戏开发实战详细分析-06-技能系统设计

时间:2023-12-09 13:42:05

相关推荐

【Unity】动作游戏开发实战详细分析-06-技能系统设计

【Unity】动作游戏开发实战详细分析-06-技能系统设计

基本思想

不同的技能可以设计为技能模版,当角色释放技能时,会通过模版ID将它进行实例化,这个实例技能类可以是一个挂载的MonoBehaviour组件或者通过上下文传入的独立对象

其次,考虑技能是否共用的问题,如果一个技能,玩家和敌人都可以使用,是否需要设计更为严谨的上下文接口?在动作游戏中,真正需要共用技能的情况相对比价多见。

系统设计

我们首先设计技能基本接口

它包含了:

属性-技能ID方法-序列化恢复方法-执行

public interface ISkillBase{int ID { get; }//技能IDvoid SerializeRecovery(SkillContext skillContext);//序列化恢复void Execute(Action onFinished);//技能执行}

其中序列化恢复需要传入技能上下文,它是一个结构体,定义如下,它存储了该技能的技能释放者以及使用按键

public struct SkillContext{public GameObject GameObject { get; set; }//技能释放者引用public KeyCode TriggerKey { get; set; }}

然后,我们继续设计技能接口

新增接口包含:

模版注册回调函数模版注销回调函数技能实例化

public interface ISkill : ISkillBase{void OnTemplateRegist();//模板注册回调void OnTemplateUnregist();//模板反注册回调ISkillBase Instantiate(SkillContext skillContext);//技能对象实例化}

最后,定义我们的抽象类技能模版

它包含基本属性和字段

属性:ID

这里有一点需要注意,Skill实现了ISkill接口,它就会有一个公开的ID,这个ID和现在我们定义的ID不是一个东西。其次,模版类中的东西均是不可访问,对技能的访问只能通过ISkill接口进行访问,这里使用了类似的技术使的所有东西被封闭封装

using System;namespace ACTBook{public abstract class Skill : ISkill, ICloneable{protected abstract int ID { get; }protected SkillContext mSkillContext;protected abstract void Execute(Action onFinished);protected virtual void OnTemplateRegist(){}protected virtual void OnTemplateUnregist(){}protected virtual void OnInstantiate(){}protected virtual void SerializeRecovery(SkillContext skillContext){}protected virtual ISkillBase SkillInstantiate(SkillContext skillContext){var instantiateSkill = Clone() as Skill;instantiateSkill.mSkillContext = skillContext;instantiateSkill.OnInstantiate();return instantiateSkill;}#region --- ISkillBase Members ---int ISkillBase.ID { get { return this.ID; } }void ISkillBase.Execute(Action onFinished){this.Execute(onFinished);}ISkillBase ISkill.Instantiate(SkillContext skillContext){return SkillInstantiate(skillContext);}void ISkill.OnTemplateRegist(){OnTemplateRegist();}void ISkill.OnTemplateUnregist(){OnTemplateUnregist();}void ISkillBase.SerializeRecovery(SkillContext skillContext){SerializeRecovery(skillContext);}#endregion#region --- ICloneable Members ---public object Clone(){return base.MemberwiseClone();}#endregion}}

仅仅这些,我们还无法实例化技能,我们还需要一个技能管理类

它是一个单例,并且作为一个可用组件

通过技能模版字典存储所有的基本技能模版,通过公共接口对公共技能进行访问获取,这样的设计使的所有的技能都只需要实例化一次,因为它是共用的。

public class SkillManager : MonoBehaviour{static bool mIsDestroying;static SkillManager mInstance;//单例对象public static SkillManager Instance{get{if (mIsDestroying) return null;if (mInstance == null){mInstance = new GameObject("[SkillManager]").AddComponent<SkillManager>();DontDestroyOnLoad(mInstance.gameObject);}return mInstance;}}Dictionary<int, ISkill> mSkillTemplateDict;//技能模板字典void Awake(){mSkillTemplateDict = new Dictionary<int, ISkill>(10);}void OnDestroy(){mIsDestroying = true;//单例处理}public void RegistToTemplate(ISkill skill)//模板注册{mSkillTemplateDict.Add(skill.ID, skill);}public bool UnregistFromTemplate(int skillID)//模板反注册{return mSkillTemplateDict.Remove(skillID);}public ISkillBase InstantiateSkill(int skillID, SkillContext skillContext)//技能实例化{return mSkillTemplateDict[skillID].Instantiate(skillContext);}}

然后我们最后只需要定义一个技能初始化的类,来对我们自己个性化的技能进行模版注册即可

并使用[DefaultExecutionOrder(-100)]来让它的执行顺序优先,防止出现空异常

[DefaultExecutionOrder(-100)]public class SkillManagerInitialization : MonoBehaviour{void Awake(){SkillManager.Instance.RegistToTemplate(new PlayerSkill_Roll());SkillManager.Instance.RegistToTemplate(new PlayerSkill_SkillAttack1());SkillManager.Instance.RegistToTemplate(new PlayerSkill_SkillAttack2());}}

如果觉得《【Unity】动作游戏开发实战详细分析-06-技能系统设计》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。