🎨
【Unity】デザインパターン Factory
Unityで開発をしていると、GameManagerのようなクラスに、
あらゆる処理を詰め込んでしまうことがよくあります。
しかし、これではコードが複雑になり、拡張性やメンテナンス性が低下してしまいます。
コードを整理するための「Factoryパターン」について調べたので、
内容をまとめてみました。
悪い例:直接オブジェクト生成をするコード
public class GameManager : MonoBehaviour
{
[SerializeField] private GameObject enemyPrefab;
[SerializeField] private GameObject itemPrefab;
void Start()
{
SpawnEnemy(new Vector3(0,0,1));
SpawnItem(new Vector3(0,0,2));
}
public void SpawnEnemy(Vector3 position)
{
GameObject enemy = Instantiate(enemyPrefab, position, Quaternion.identity);
enemy.name = "Enemy";
// 生成後の処理をここに追加 (例: コンポーネント取得)
}
public void SpawnItem(Vector3 position)
{
GameObject item = Instantiate(itemPrefab, position, Quaternion.identity);
item.name = "Item";
// 生成後の処理をここに追加 (例: パラメータ設定)
}
}
問題点
-
生成処理が散らかる
GameManager
が敵もアイテムも直接生成し、その後の初期化も担うため、管理が煩雑 -
拡張性が低い
新しい敵やアイテムを追加するときは、
GameManager
を修正する必要がある -
保守性に欠ける
問題が発生した場合、生成処理全体を見直す必要がある
Factoryパターンで生成処理を分離する
Assets/
├── Scripts/
│ ├── Interfaces/
│ │ └── IFactory.cs
│ ├── Factories/
│ │ ├── EnemyFactory.cs
│ │ ├── ItemFactory.cs
│ ├── Managers/
│ └── GameManager.cs
// 共通の生成インターフェース
public interface IFactory
{
GameObject Create(Vector3 position);
}
// 敵を生成するファクトリー
public class EnemyFactory : IFactory
{
[SerializeField] private GameObject enemyPrefab;
public GameObject Create(Vector3 position)
{
GameObject enemy = Instantiate(enemyPrefab, position, Quaternion.identity);
enemy.name = "Enemy";
// 初期化処理
return enemy;
}
}
// アイテムを生成するファクトリー
public class ItemFactory : IFactory
{
[SerializeField] private GameObject itemPrefab;
public GameObject Create(Vector3 position)
{
GameObject item = Instantiate(itemPrefab, position, Quaternion.identity);
item.name = "Item";
// 初期化処理
return item;
}
}
public class GameManager : MonoBehaviour
{
[SerializeField] private EnemyFactory enemyFactory;
[SerializeField] private ItemFactory itemFactory;
// 初期化時に生成するオブジェクトの座標
private Vector3 enemySpawnPosition = new Vector3(0, 0, 0);
private Vector3 itemSpawnPosition = new Vector3(2, 0, 0);
private void Start()
{
// Start時に敵とアイテムを生成
SpawnEnemy(enemySpawnPosition);
SpawnItem(itemSpawnPosition);
}
public void SpawnEnemy(Vector3 position)
{
GameObject enemy = enemyFactory.Create(position);
Debug.Log($"Enemy spawned at {position}");
}
public void SpawnItem(Vector3 position)
{
GameObject item = itemFactory.Create(position);
Debug.Log($"Item spawned at {position}");
}
}
改善点
-
生成処理が整理される
各
Factory
が生成処理を専任で担当し、GameManager
の責務が減る -
拡張性が向上
新しいオブジェクトを追加するときは、対応するFactoryを新たに作るだけで済む
-
保守性が向上
問題が発生しても、該当Factoryのみを調査すればよい
Discussion