Unity Advent Calendar 2019 3日目の記事です
経緯
キャラクターgameobjectにコンポーネントがいっぱいつくのが嫌になってきました。
- Inspectorが埋まり、パラメータ編集したいコンポーネントを探すのがしんどい
- GetComponentで取得でき実質public
- MonoBehaviour継承すると知りたくもない関数がいっぱい継承され無駄
- VisualStudio intellisenseに使わない関数わらわら出てきてうっとうしい
そもそもpureC#で済むならそっちでいいですよね。
そう思ってCharacterControllerみたいな神様にいっぱいメンバ変数という形でpureC#インスタンス持たせてました。しかし当然ながらキャラクターの外からアクセスしたいこともあります。
- CharacterControllerにpublicプロパティ
だんだん不格好になってきました…CharacterController縛りも扱いにくいです。VechicleControllerだったらどうするんだ
pureC#インスタンスの入れ物としての役割+publicでアクセス許したい
そうだGetCSharpComponent関数作ろう
作ってみました
public class CSharpComponentContainer : MonoBehaviour
{
private readonly Dictionary<System.Type, object> _dic = new Dictionary<System.Type, object>();
public void AddCSharpComponent<T>(T c)
{
var key = typeof(T);
if (_dic.ContainsKey(key))
{
Debug.LogError($"すでに持ってる={key} name={name}");
}
else
{
_dic.Add(key, c);
}
}
public T GetCSharpComponent<T>()
{
var key = typeof(T);
if( _dic.ContainsKey(key))
{
return (T)_dic[key];
}
else
{
Debug.LogError($"ない={key} name={name}");
return default(T);
}
}
private void OnDestroy()
{
_dic.Clear();
}
}
わりと使い勝手いいです。AddCSharpComponent<Interface>とすれば実体を隠すこともできます。where T : System.IDisposableくらいは制約でつけてもいいかもしれません(OnDestroyでDipose呼び出し用
外部に公開しないクラスは相変わらずCharacterControllerが持ってます。
キャラクターとはメッセージシステム的なものでやり取りしては?
キャラクター自体、一つの境界付けられたコンテキストみたいなものなので、メッセージシステムを使うのもアリかなと思ってました
が、オフラインゲーム+個人開発でそこまで疎結合にするとコードが追いにくいデメリットの方が大きくなったので没にしました。