一人称視点でロッカーの中に入って隠れるのワープやアニメーションをした後の処理をデリゲートを使ってわかりやすくしてみました。
Action method;
// キャラクターコントローラーをオフにしてTransformで移動した後
void EndWarp()
{
// ...
if(method != null) method();
}
// アニメーションで移動した後
void EndMotion()
{
// ...
if(method != null) method();
}
void Method1()
{
// ...
method = Method2;
StartMotion();
}
void Method2()
{
// ...
method = Method3;
StartWarp();
}
void Method3()
{
// ...
method = null
}
ロッカーをクリックするとまずキャラクターコントローラーをオフにして、キー入力を受けずにトランスフォームでFPSプレイヤーの位置や回転を変えてロッカーの前まで移動し、アニメーションでロッカーの中に入ります。ロッカーに入る時以外でもそういった移動方法を使うことがあります。
トランスフォームでの移動が終了した後、その次にアニメーションでの移動に移る場合もあれば、そこで立ち止まってプレイヤーの位置や回転をロックしたり、アニメーションが終わった後にもう一度トランスフォームで移動させてからキャラクターコントローラーをオンに戻したりする場合もあります。
上の記事では、プレイヤーの状態や引数の値などで場合分けして処理を変えていましたがわかりにくいので、トランスフォームでの移動やアニメーションが終わった時に毎回デリゲートを実行するようにして、その中身を変えることにしました。
例えば、下のようにデリゲートにMethod1を入れて、トランスフォームでの移動をします。
Action method;
// ---
method = Method1;
StartWarp();
移動が終わった後に呼ばれるメソッドの中でデリゲートを呼びます。
// キャラクターコントローラーをオフにしてTransformで移動した後
void EndWarp()
{
// ...
if(method != null) method();
}
この時にMethod1()が実行され、その中でデリゲートの中身をMethod2に入れ替え、アニメーションを開始します。
void Method1()
{
// ...
method = Method2;
StartMotion();
}
すると、アニメーションが終わる時に呼ばれるメソッドの中でMethod2()が実行されます。
// アニメーションで移動した後
void EndMotion()
{
// ...
if(method != null) method();
}
さらに続けてトランスフォームで移動したい時はMethod2でそのためのメソッドを呼びます。デリゲートの変数にMethod3を代入しておきます。
void Method2()
{
// ...
method = Method3;
StartWarp();
}
すると、トランスフォームでの移動が終わったときに呼ばれるメソッドが再度呼ばれますが、この時はデリゲートの中身が違い、通常の移動方法に戻りたいときは、キャラクターコントローラーをオンに戻します。
デリゲートの中身をnullにしておけば、次にデリゲートを呼んだときに何もしないこともできます。
void Method3()
{
// ...
method = null
}
デリゲートを呼ぶ時にnullでないことを確認しようとすると簡略化できると言われますが、書かないとnullのときエラーになりました。
デリゲートの中身を入れ替えることで、連続的な挙動を簡単に作ることができました。