質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

7581閲覧

方向キーの入力を一度だけ取りたい

jum6948

総合スコア20

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2017/10/21 05:29

###前提・実現したいこと
タイトル画面にて、以下のような感じの選択肢があるのですが

▶ ゲームスタート
_ランキング
_コンフィグ

コントローラーの左スティックを倒した時にカーソルを一段だけ下げたい。
また、カーソルが一番上に有る時にスティックを上に倒すと一番下(この場合コンフィグ)、カーソルが一番下に有る時にスティックを上に倒すと一番上(この場合ゲームスタート)にカーソルが行くようにしたいです。
(現在使用中のコントローラーはXbox360のものを使用中)
動的に動かしているのを見せたいので【iTween】を使用しています。

###発生している問題・エラーメッセージ

カーソルが、下に行き過ぎたり、上に行き過ぎたり、画面外に出たり、Updateで入力を受け付けているので、かなりのスピードでカーソルが動く。

###該当のソースコード

C#で作成中

1 2public class GameDirectorTitle : MonoBehaviour { 3 4 [Header("ゲームモードを選ぶ")] 5 public GameObject SelectIcon; 6 public int SelectIconPosition; 7 8 // Use this for initialization 9 void Start () { 10 SelectIconPosition = 0; 11 } 12 13 // Update is called once per frame 14 void Update() { 15 StartCoroutine(SelectIconMove()); 16 } 17 18 IEnumerator SelectIconMove() 19 { 20 //カーソルがゲームスタートの時 21 if (SelectIconPosition == 0) 22 { 23 //十字キーを上 24 if (Input.GetAxisRaw("Vertical") == 1) 25 { 26 //カーソル移動 27 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -160f, "time", 0.25f)); 28 //【Config】 29 SelectIconPosition = 2; 30 Debug.Log("0,+1"); 31 yield return new WaitForSeconds(0.25f); 32 } 33 //十字キーを下 34 else if (Input.GetAxisRaw("Vertical") == -1) 35 { 36 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -80f, "time", 0f)); 37 //【ランキング】 38 SelectIconPosition = 1; 39 Debug.Log("0,-1"); 40 yield return new WaitForSeconds(0.25f); 41 } 42 //決定ボタンを押す 43 else if (Input.GetButtonDown("AtackX")) 44 { 45 SceneManager.LoadScene("new-stage1"); 46 } 47 } 48 //カーソルがランキングの時 49 else if (SelectIconPosition == 1) 50 { 51 //十字キーを上 52 if (Input.GetAxisRaw("Vertical") == 1) 53 { 54 //カーソル移動 55 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 80f, "time", 0.01f)); 56 //【ゲームスタート】 57 SelectIconPosition = 0; 58 Debug.Log("1,+1"); 59 yield return new WaitForSeconds(0.25f); 60 } 61 //十字キーを下 62 else if (Input.GetAxisRaw("Vertical") == -1) 63 { 64 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -80f, "time", 0f)); 65 //【Config】 66 SelectIconPosition = 2; 67 Debug.Log("1,-1"); 68 yield return new WaitForSeconds(0.25f); 69 } 70 //決定ボタンを押す 71 else if (Input.GetButtonDown("AtackX")) 72 { 73 74 } 75 } 76 //カーソルがConfigの時 77 else if (SelectIconPosition == 2) 78 { 79 //十字キーを上 80 if (Input.GetAxisRaw("Vertical") == 1) 81 { 82 //カーソル移動 83 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 80f, "time", 0.01f)); 84 //【ランキング】 85 SelectIconPosition = 1; 86 Debug.Log("2,+1"); 87 yield return new WaitForSeconds(0.25f); 88 } 89 //十字キーを下 90 else if (Input.GetAxisRaw("Vertical") == -1) 91 { 92 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 160f, "time", 0f)); 93 //【ゲームスタート】 94 SelectIconPosition = 0; 95 Debug.Log("2,-1"); 96 yield return new WaitForSeconds(0.25f); 97 } 98 //決定ボタンを押す 99 else if (Input.GetButtonDown("AtackX")) 100 { 101 102 } 103 104 } 105 } 106 107} 108

###試したこと
コンフィグ画面、ランキング画面はまだ作っておりません。
【SelectIconPosition】は選んでいるカーソルの位置で、
ゲームスタート【0】
ランキング__【1】
コンフィグ__【2】
で0の時に上を押せば、カーソルが一番下に行くという考えで作ったのですが、カーソルが画面外に出ていってしまいました。
また、一回の動作ごとにコルーチンで休みを挟めばいいかと思って移動ごとに【0.25f】一時停止するようにしてみましたが、コレもダメ。
【void PositionUp】というクラスを別に作って、みましたが、根本がUpdateから取っているのでその関数が連続で実行されてしまって、これもダメ。ダレカタスケテッ!

###補足情報(言語/FW/ツール等のバージョンなど)
【環境】
Unity5.6.1f1 personal
win10
MicrosoftVisualStudio
上記が作成環境になっております。

【おまけのおたすけ】
いつも私の質問に答えていただいている皆様、本当にありがとうございます。

根本的に、本を2冊ほどしか読んでいないので、知ってる知識が少なすぎる問題なんだとは思います。
ただ、友達がオススメしてくれる本が、字ばっかりでまったく理解が出来ません。自分は、図解がないとイメージがわかず、理解が出来ない、のだと分析します。

てめぇのクソ質問に答えるのがうんざりだと言う方、もし宜しければ、わかりやすいオススメの本とかあれば教えてください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

C#

1 // Update is called once per frame 2 void Update() { 3 StartCoroutine(SelectIconMove()); 4 }

上記を書いてしまっているので、毎フレーム、コルーチンを開始していることになります。
そのため、yield return new WaitForSeconds(0.25f);としても、Update()で別のコルーチンが開始されてしまうので、意味の無い状態になります。

解決策としては、以下のいずれかをとればよいです。

・コルーチンが終了するまで、新たなコルーチンを開始させない

C#

1 // コルーチンが実行中かどうか 2 bool nowExecCoroutine_ = false; 3 4 // …(中略) 5 6 // Update is called once per frame 7 void Update() 8 { 9 if (!nowExecCoroutine_) 10 { 11 nowExecCoroutine_ = true; 12 StartCoroutine(SelectIconMove()); 13 } 14 } 15 16 IEnumerator SelectIconMove() 17 { 18 // …(中略) 19 20 nowExecCoroutine_ = false; 21 }

・コルーチンではなく関数で定義、Update()上で最後の操作から何秒経過したかを取得・計算し、0.25秒以上経過していればその関数を実行する

C#

1 // 最後に十字キーが押された時間 2 float lastTimeArrowKeyDown_ = 0f; 3 4 // …(中略) 5 6 // Update is called once per frame 7 void Update() 8 { 9 if (Time.time - lastTimeArrowKeyDown_ > 0.25f) 10 { 11 SelectIconMove(); 12 } 13 } 14 15 void SelectIconMove() 16 { 17 //カーソルがゲームスタートの時 18 if (SelectIconPosition == 0) 19 { 20 //十字キーを上 21 if (Input.GetAxisRaw("Vertical") == 1) 22 { 23 //カーソル移動 24 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -160f, "time", 0.25f)); 25 //【Config】 26 SelectIconPosition = 2; 27 Debug.Log("0,+1"); 28 lastTimeArrowKeyDown_ = Time.time; 29 } 30 //十字キーを下 31 else if (Input.GetAxisRaw("Vertical") == -1) 32 { 33 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -80f, "time", 0f)); 34 //【ランキング】 35 SelectIconPosition = 1; 36 Debug.Log("0,-1"); 37 lastTimeArrowKeyDown_ = Time.time; 38 } 39 //決定ボタンを押す 40 else if (Input.GetButtonDown("AtackX")) 41 { 42 SceneManager.LoadScene("new-stage1"); 43 } 44 } 45 //カーソルがランキングの時 46 else if (SelectIconPosition == 1) 47 { 48 //十字キーを上 49 if (Input.GetAxisRaw("Vertical") == 1) 50 { 51 //カーソル移動 52 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 80f, "time", 0.01f)); 53 //【ゲームスタート】 54 SelectIconPosition = 0; 55 Debug.Log("1,+1"); 56 lastTimeArrowKeyDown_ = Time.time; 57 } 58 //十字キーを下 59 else if (Input.GetAxisRaw("Vertical") == -1) 60 { 61 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -80f, "time", 0f)); 62 //【Config】 63 SelectIconPosition = 2; 64 Debug.Log("1,-1"); 65 lastTimeArrowKeyDown_ = Time.time; 66 } 67 //決定ボタンを押す 68 else if (Input.GetButtonDown("AtackX")) 69 { 70 71 } 72 } 73 //カーソルがConfigの時 74 else if (SelectIconPosition == 2) 75 { 76 //十字キーを上 77 if (Input.GetAxisRaw("Vertical") == 1) 78 { 79 //カーソル移動 80 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 80f, "time", 0.01f)); 81 //【ランキング】 82 SelectIconPosition = 1; 83 Debug.Log("2,+1"); 84 lastTimeArrowKeyDown_ = Time.time; 85 } 86 //十字キーを下 87 else if (Input.GetAxisRaw("Vertical") == -1) 88 { 89 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 160f, "time", 0f)); 90 //【ゲームスタート】 91 SelectIconPosition = 0; 92 Debug.Log("2,-1"); 93 lastTimeArrowKeyDown_ = Time.time; 94 } 95 //決定ボタンを押す 96 else if (Input.GetButtonDown("AtackX")) 97 { 98 99 } 100 101 } 102 }

・コルーチン上でループさせる。コルーチン自体はStart()で一度だけ実行する

C#

1 // Use this for initialization 2 void Start() 3 { 4 SelectIconPosition = 0; 5 StartCoroutine(SelectIconMove()); 6 } 7 8 IEnumerator SelectIconMove() 9 { 10 bool breakFlag = false; 11 do 12 { 13 //カーソルがゲームスタートの時 14 if (SelectIconPosition == 0) 15 { 16 //十字キーを上 17 if (Input.GetAxisRaw("Vertical") == 1) 18 { 19 //カーソル移動 20 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -160f, "time", 0.25f)); 21 //【Config】 22 SelectIconPosition = 2; 23 Debug.Log("0,+1"); 24 yield return new WaitForSeconds(0.25f); 25 } 26 //十字キーを下 27 else if (Input.GetAxisRaw("Vertical") == -1) 28 { 29 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -80f, "time", 0f)); 30 //【ランキング】 31 SelectIconPosition = 1; 32 Debug.Log("0,-1"); 33 yield return new WaitForSeconds(0.25f); 34 } 35 //決定ボタンを押す 36 else if (Input.GetButtonDown("AtackX")) 37 { 38 SceneManager.LoadScene("new-stage1"); 39 breakFlag = true; 40 } 41 } 42 //カーソルがランキングの時 43 else if (SelectIconPosition == 1) 44 { 45 //十字キーを上 46 if (Input.GetAxisRaw("Vertical") == 1) 47 { 48 //カーソル移動 49 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 80f, "time", 0.01f)); 50 //【ゲームスタート】 51 SelectIconPosition = 0; 52 Debug.Log("1,+1"); 53 yield return new WaitForSeconds(0.25f); 54 } 55 //十字キーを下 56 else if (Input.GetAxisRaw("Vertical") == -1) 57 { 58 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", -80f, "time", 0f)); 59 //【Config】 60 SelectIconPosition = 2; 61 Debug.Log("1,-1"); 62 yield return new WaitForSeconds(0.25f); 63 } 64 //決定ボタンを押す 65 else if (Input.GetButtonDown("AtackX")) 66 { 67 breakFlag = true; 68 } 69 } 70 //カーソルがConfigの時 71 else if (SelectIconPosition == 2) 72 { 73 //十字キーを上 74 if (Input.GetAxisRaw("Vertical") == 1) 75 { 76 //カーソル移動 77 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 80f, "time", 0.01f)); 78 //【ランキング】 79 SelectIconPosition = 1; 80 Debug.Log("2,+1"); 81 yield return new WaitForSeconds(0.25f); 82 } 83 //十字キーを下 84 else if (Input.GetAxisRaw("Vertical") == -1) 85 { 86 iTween.MoveBy(SelectIcon.gameObject, iTween.Hash("y", 160f, "time", 0f)); 87 //【ゲームスタート】 88 SelectIconPosition = 0; 89 Debug.Log("2,-1"); 90 yield return new WaitForSeconds(0.25f); 91 } 92 //決定ボタンを押す 93 else if (Input.GetButtonDown("AtackX")) 94 { 95 breakFlag = true; 96 } 97 98 } 99 100 yield return null; //これがないと固まる 101 } while (!breakFlag); 102 }

投稿2017/10/21 06:25

fiveHundred

総合スコア9796

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jum6948

2017/10/22 03:06

いろんなやり方があるんですね。 【高評価】じゃなく、【超評価】のボタンが欲しいすばらしい回答ありがとうございます。+100にしたい位勉強になる回答です。アプローチの方法を複数書いてもらえて本当に感謝です! 勉強のために全部動作テストしましたが、全部同じ動きしました。凄い! 「一回だけ実行」をnull(このnullすら理解しきれてない)しか知らなかったので、書く方法がわからなかったので、こういう新しいやり方を教えてもらえるので、回答者さんもteratailも本当に最高です。ありがとうございます。 今回は、ネットでUpdate使わない方がいいと見たことが有るので、コルーチンでループさせる方法を使うことにしました。「do while」という自分がまだ、使ったことがない技があるので、これは要勉強ですね。これは他でも使えそうですね。本当にありがとうございました!
fiveHundred

2017/10/22 03:45 編集

解決できてよかったです。 補足ですが、「yield return null;」は、「処理を中断して、1フレーム分待機する」という意味です。 Unityは基本的にシングルスレッドで動作するため「yield return ~;」で処理を中断しないと、他の処理ができず、Unity全体が固まってしまいます。 待機時間が1フレーム分長くなってしまっている可能性がありますが、自分はそこまで気にならなかったのと、正確に時間を測る必要性は無いと判断したため、この点は特に考慮してないです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問