在這款遊戲中,我們共有兩個敵方單位、一個障礙物單位、兩個玩家單位,在這個範例中,我想用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單位,執行結果如下
設計模式與遊戲開發的完美結合(暢銷回饋版)
Turn Based Strategy Framework
流離之歌