iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0

在這款遊戲中,我們共有兩個敵方單位、一個障礙物單位、兩個玩家單位,在這個範例中,我想用Factory模式來實作生成單位在地圖上的功能。

如果今天要實作一個隨機生成敵人跟障礙物的關卡,就會需要一個工廠來製造,而在這次的案例中,會用Method Type的方式去製作這個功能,而獲取Prefab的方式用Resource獲取,有興趣的話可以參考Unity Resource的相關資料,這邊就不做太多解釋。

UnitType.cs

namespace LinXuan.TBSF.Enums
{

    public enum PlayerUnitType
    {
        PushBoy,
        HydroMagicGirl,
    }

    public enum EnemyUnitType
    {        
        Slave,
        Musketeer
    }

    public enum ObstacleUnitType
    {        
        Stone
    }

    public enum FoodUnitType
    {
        Bread
    }
}

在這邊我將單位分成了四種,並且在enum中填上每個類別所會擁有的職稱,主要是想要未來用這種方式來做為工廠創造單位的判斷方式。

IUnitFactory.cs

using LinXuan.TBSF.Enums;
using LinXuan.TBSF.Units;

namespace LinXuan.TBSF.Factory.Units
{
    public interface IUnitFactory
    {
        public PlayerUnit CreatePlayerUnit(PlayerUnitType playerUnitType);
        public EnemyUnit CreateEnemyUnit(EnemyUnitType enemyUnitType);
        public ObstacleUnit CreateObstacleUnit(ObstacleUnitType obstacleUnitType);
        public FoodUnit CreateFoodUnit(FoodUnitType foodUnitType);
    }
}

UnitFactory.cs

using LinXuan.TBSF.Data;
using LinXuan.TBSF.Enums;
using LinXuan.TBSF.Units;
using UnityEngine;

namespace LinXuan.TBSF.Factory.Units
{
    public class UnitFactory : IUnitFactory
    {
        public EnemyUnit CreateEnemyUnit(EnemyUnitType enemyUnitType)
        {
            GameObject tempGameObject = GameObject.Instantiate(Resources.Load<GameObject>("Prefabs/UnitComponent/UnitComponentTemplate"));
            tempGameObject.AddComponent<EnemyUnit>();
            EnemyUnit enemyUnit = tempGameObject.GetComponent<EnemyUnit>();

            Debug.Log(tempGameObject);
            switch (enemyUnitType)
            {
                case EnemyUnitType.Musketeer:
                    enemyUnit.UnitData = ScriptableObject.Instantiate(Resources.Load<UnitData>("ScriptableObject/UnitData/MusketeerUnitData"));
                    Debug.Log(enemyUnit.UnitData);
                    return null;
                case EnemyUnitType.Slave:
                    enemyUnit.UnitData = ScriptableObject.Instantiate(Resources.Load<UnitData>("ScriptableObject/UnitData/SlaveUnitData"));
                    Debug.Log(enemyUnit.UnitData);
                    return enemyUnit;
                default:
                    Debug.LogError("Can't create enemy unit.");
                    return null;
            }
        }

        public FoodUnit CreateFoodUnit(FoodUnitType foodUnitType)
        {
            Create foodUnit... 
        }

        public ObstacleUnit CreateObstacleUnit(ObstacleUnitType obstacleUnitType)
        {
            Create obstacleUnit... 
        }

        public PlayerUnit CreatePlayerUnit(PlayerUnitType playerUnitType)
        {
            Create playerUnit... 
        }
    }

}

Instantiate是用來創建一個新的GameObject跟ScriptableObject的方式,不然要是直接使用Resource Load的資料會改到Asset裡的內容,這點要特別去注意。
當然這種直接在生成時獲取Resource的作法,要是今天是大量讀入的話,以效能來說其實不是太好,如果是很常取用的話建議做個ObjectPool來存在背景一次生成會比較好。

UnitCreator.cs

using LinXuan.TBSF.Factory.Units;
using LinXuan.TBSF.Units;
using UnityEngine;

namespace LinXuan.TBSF.Misc
{
    public class UnitCreator : MonoBehaviour
    {
        private void Start()
        {
            UnitFactory unitFactory = new UnitFactory();
            EnemyUnit enemyUnit = unitFactory.CreateEnemyUnit(Enums.EnemyUnitType.Slave);
            Debug.Log(enemyUnit.UnitData.CurrentStamina);
        }
    }
}

最後在UnitCreator使用UnitFactory並創造一個Slave單位,執行結果如下
https://ithelp.ithome.com.tw/upload/images/20220930/20151894m4KAkTWgTJ.png

參考資料

設計模式與遊戲開發的完美結合(暢銷回饋版)
Turn Based Strategy Framework
流離之歌


上一篇
Day 15:Factory模式(一)
下一篇
Day 17:Observer模式(一)
系列文
如何在Unity裡寫出具有一定擴充性的遊戲30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言