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:
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:
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();
}
public float GetExtraHealth(){
return extraHealth;
}
}
}
AreaEffectConfig.cs:
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();
}
public float GetDamageToEachTarget(){
return damageToEachTarget;
}
public float GetRadius(){
return radius;
}
}
}
PowerAttackConfig.cs:
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();
}
public float GetExtraDamage(){
return extraDamage;
}
}
}



留言
張貼留言