Related Posts Plugin for WordPress, Blogger...

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:

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;
  }
 }
}



留言