質問: ユニティでキー入力をしたらオブジェクトを動かすスクリプトを書いています。 連続してキーの入力をすると予期せぬ動きをしてしまうので、オブジェクトが動いている最中はキー入力を受け付けないようにしたいです。 どのようなスクリプトを書いたらいいでしょうか。 よろしくお願いいたします。
回答: ※僕はUnityやってないし、ゲームプログラマーでもないから参考程度に 現在のアクションの実行状態を何等かの形で管理しましょう。 複数通りの管理方法があると思います。 1.コルーチンで実行中受け付けないようにする ``` private bool IsDoingSomething; IEnumarator DoSomething() { if (IsDoingSomething) yield break; IsDoingSomething = true; animation.Play("DoSomething"); // 戻ってくる条件を返す。例えばアニメーションが終わるまで、とか。 yield return new WaitUntil(() => !animation.IsPlaying("DoSomething")); IsDoingSomething = false; } ``` コルーチンの停止について参照するといいでしょう。 http://tsubakit1.hateblo.jp/entry/2015/04/06/060608 コルーチン自体がまだよくわからない場合はこっちの情報を参照するといいかな。 https://cfm-art.sakura.ne.jp/sys/archives/419 ようはアクション中にもう一度実行依頼が来ても実行しないよー、という単純なスクリプトです。 欠点もあります。 先行入力や、アクション中に違うアクションにする、等がこのままだと実装しにくいことです。 ゼルダの伝説で箱を動かすぐらいの動作ならこれでも困らないと思います。 2.実行状態を厳密に管理する アクション実行中、どこかに現在の状態を纏めて管理しておき、状態を参照して次のアクションを決定しましょう。 1の方法でいうところの、IsDoingSomethingをもっと具体的なクラスに状態としてまとめておき、次のアクションに利用します。 アクションの実行状態を複雑に管理する場合はこういう方法がどうしてもいると思います。 ``` if (/*現在何も受け付けない状態なら*/) { return Action.None; } // 各入力の優先順に処理.. if (Input.GetButton("Attack")) { if (State.IsAttacking) { // 何もしない } else if (State.IsJumping) { return Action.JumpAttack; } else { return Action.Attack; } } // .. return Action.None; ``` 追記 == コルーチンの呼び出し方がわからない、という意味でしょうか。 僕に書けるのはリファレンスから想像して書くぐらいですが マニュアル通りだと、あるアニメーションの排他制御は以下のような形になると思います。 ``` public class Sample : MonoBehaviour { private Animation animation; private bool isRunning; void Start() { animation = GetComponent(); } void Update() { if (Input.GetKey(KeyCode.Space)) { StartCoroutine(Concurrent()); } } private IEnumerable Concurrent() { if (isRunning) yield break; isRunning = true; animation.Play("Sample1"); yield return new WaitUntil(() => !animation.IsPlaying("Sample1")); isRunning = false; } } ``` yield return で次にいつアクションを実行するのかを制御するようですから、例えば1秒かけて動作させるとかそういった条件を合わせて書いておくといいでしょう。 Updateメソッドは毎フレーム呼ばれますが、Concurrentが1度実行状態に入るとアニメーションが終わるまでは`yield return new WaitUntil`を超えることができません。 そして、アニメーションが終わった後にフラグがfalseになる、という想定です。