私が言いたいことの例として、コード内の何かのケーススタディを使用すると思います。
現在、コンポーネント ベースのゲーム システムのビヘイビア/アクション システムに取り組んでいます。ゲームオブジェクトには IBehaviorComponent と IActionComponent をアタッチすることができ、関連する詳細のみを表示し、以下を公開します。
public interface IBehaviorComponent : IBaseComponent
{
IBehavior Behavior { get; }
}
public interface IActionComponent : IBaseComponent
{
IAction Action { get; }
void ExecuteAction(IGameObject target = null);
}
今のところ、これで問題ありません (少なくとも私にとっては!)。しかし、IActionComponent の実装を見ると、問題が発生し始めます。
たとえば、単純な IActionComponent の実装は次のとおりです。
public class SimpleActionComponent : IActionComponent
{
public IAction Action { get; protected set; }
public void ExecuteAction(IGameObject target = null)
{
Action.Execute(target);
}
public void Update(float deltaTime) { } //from IBaseComponent
}
しかし、時間指定されたスケジュールでアクションを実行できるようにする、より複雑な IActionComponent 実装を導入したいとしましょう。
public class TimedActionComponent : IActionComponent
{
public IAction Action { get; protected set; }
public float IdleTime { get; set; }
public float IdleTimeRemaining { get; protected set; }
public void ExecuteAction(IGameObject target = null)
{
IdleTimeRemaining = IdleTime;
}
public void Update(float deltaTime)
{
if (IdleTimeRemaining > 0f)
{
IdleTimeRemaining -= deltaTime;
}
else
{
Action.Execute(target);
}
}
}
そして今、IdleTime を公開して、外部の影響によって変更できるようにしたいとしましょう。最初の私の考えは、新しいインターフェースを作成することでした:
public interface ITimedActionComponent : IActionComponent
{
float IdleTime { get; set; }
float IdleTimeRemaining { get; set; }
}
ただし、ここでの問題は、コンポーネント システムがすべてを IBaseComponent の 1 レベル上に格納することです。したがって、GameObject のアクション コンポーネントは、ITimedActionComponent、IRandomizedActionComponent、さらには ICrashTheProgramActionComponent などではなく、IActionComponent として取得されます。コンポーネントの基本的なタイプ (IActionComponent、IRenderableComponent、IPhysicsComponent など) を超えて何が必要かを正確に知る必要なく、ゲームオブジェクトのコンポーネントの 1 つを照会できるようにしたいので、この理由が明らかであることを願っています。
取得した IActionComponent を対象の型にキャストしなくても、子クラスで定義されたこれらのプロパティを公開できる、これを処理するよりクリーンな方法はありますか? それとも、これを達成するための唯一の/最良の方法ですか?何かのようなもの:
public void IWantYouToAttackSuperSlow(IGameObject target)
{
//Let's get the action component for the gameobject and test if it's an ITimedActionComponent...
ITimedActionComponent actionComponent = target.GetComponent<IActionComponent>() as ITimedActionComponent;
if (actionComponent != null) //We're okay!
{
actionComponent.IdleTime = int.MaxValue; //Mwhaha
}
}
今、私はそれが唯一の方法だと考えていますが、私が知らない木工品にパターンが隠れているかどうか、または誰かがこれを達成するためのより良い方法を最初から提案できるかどうかを確認すると思いました.
ありがとう!