4-2 Making Abstract Methods Concrete
本章繼上一章同樣要重構我們的技能系統,大家應該會發現在每一個技能的config裡面,無論是PowerAttackConfig、SelfHealConfig,還是AreaEffectConfig都有如下圖的AddComponent方法,並且都有同樣重複的一行:behaviourComponent.SetConfig(this)
所以這次重構也是將這重複的一行移動到父類別,而唯獨不重複的部分,亦即需要指定Behaviour的部分,則由子類別來實作。我們打開AbilityConfig.cs,並將AddComponent方法改成AttachAbilityTo,如下圖,其中呼叫了新的抽象方法GetBehaviourComponent則由子類別來實作。
接著,如下圖SelfHealConfig.cs要實作GetBehaviourComponent,則回傳SelfHealBehaviour,看起來簡單清爽多了。
以下提供修正過的所有程式碼:
AbilityConfig.cs:
SelfHealConfig.cs:
AreaEffectConfig.cs:
PowerAttackConfig.cs:
所以這次重構也是將這重複的一行移動到父類別,而唯獨不重複的部分,亦即需要指定Behaviour的部分,則由子類別來實作。我們打開AbilityConfig.cs,並將AddComponent方法改成AttachAbilityTo,如下圖,其中呼叫了新的抽象方法GetBehaviourComponent則由子類別來實作。
接著,如下圖SelfHealConfig.cs要實作GetBehaviourComponent,則回傳SelfHealBehaviour,看起來簡單清爽多了。
以下提供修正過的所有程式碼:
AbilityConfig.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | using System.Collections; using System.Collections.Generic; using UnityEngine; using RPG.Core; namespace RPG.Character{ public struct AbilityParams{ public Enemy target; public float baseDamage; public AbilityParams(Enemy target, float baseDamage){ this .target = target; this .baseDamage = baseDamage; } } public abstract class AbilityConfig : ScriptableObject { [Header( "Special Ability General" )] [SerializeField] float energyCost = 10f; [SerializeField] GameObject particlePrefab = null ; [SerializeField] AudioClip audioClip = null ; public AbilityBehaviour AttachAbilityTo (GameObject gameObjectAttachTo){ AbilityBehaviour behaviourComponent = GetBehaviourComponent(gameObjectAttachTo); behaviourComponent.SetConfig ( this ); return behaviourComponent; } public abstract AbilityBehaviour GetBehaviourComponent(GameObject gameObjectAttachTo); public float GetEnergyCost(){ return energyCost; } public GameObject GetParticlePrefab(){ return particlePrefab; } public AudioClip GetAudioClip(){ return audioClip; } } } |
SelfHealConfig.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using System.Collections; using System.Collections.Generic; using UnityEngine; namespace RPG.Character{ [CreateAssetMenu(menuName= ( "RPG/Special Ability/Self Heal" ))] public class SelfHealConfig : AbilityConfig { [Header( "Self Heal Specific" )] [SerializeField] float extraHealth = 5f; public override AbilityBehaviour GetBehaviourComponent (GameObject gameObjectAttachTo){ return gameObjectAttachTo.AddComponent<selfhealbehaviour>(); } public float GetExtraHealth(){ return extraHealth; } } } </selfhealbehaviour> |
AreaEffectConfig.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | using System.Collections; using System.Collections.Generic; using UnityEngine; namespace RPG.Character{ [CreateAssetMenu(menuName= ( "RPG/Special Ability/Area Effect" ))] public class AreaEffectConfig : AbilityConfig { [Header( "Area Effect Specific" )] [SerializeField] float radius = 5f; [SerializeField] float damageToEachTarget = 15f; public override AbilityBehaviour GetBehaviourComponent (GameObject gameObjectAttachTo){ return gameObjectAttachTo.AddComponent<areaeffectbehaviour>(); } public float GetDamageToEachTarget(){ return damageToEachTarget; } public float GetRadius(){ return radius; } } } </areaeffectbehaviour> |
PowerAttackConfig.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using System.Collections; using System.Collections.Generic; using UnityEngine; namespace RPG.Character{ [CreateAssetMenu(menuName= ( "RPG/Special Ability/Power Attack" ))] public class PowerAttackConfig : AbilityConfig { [Header( "Power Attack Specific" )] [SerializeField] float extraDamage = 10f; public override AbilityBehaviour GetBehaviourComponent (GameObject gameObjectAttachTo){ return gameObjectAttachTo.AddComponent<powerattackbehaviour>(); } public float GetExtraDamage(){ return extraDamage; } } } </powerattackbehaviour> |
留言
張貼留言