🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Unity

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

Q&A

解決済

2回答

2840閲覧

オブジェクトをランダムに動かす操作を繰り返したい(カップシャッフルゲーム)

actionstudio

総合スコア39

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Unity

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

0グッド

0クリップ

投稿2021/01/05 13:14

編集2021/01/08 12:57

オブジェクトをランダムに動かす操作を繰り返したい

unityで、C#を使ってマグカップを何度か動かし、最初に目印を入れておいたマグカップがどこに移動したかを当てるカップシャッフルゲームを作っています。
ランダムに移動させたのちに、また同じ操作を繰り返して何度も位置を変えたいのですが、うまくいきません。

発生している問題

1.ランダムに移動する操作が一度しか行えず、複数回行う方法がわからない。
2.時間計測でオブジェクトを動かしているため、時間計測を合わせて実行しなければいけないが、処理を繰り返す場合にその実行方法がわからない。
3.カップを移動させた後もう一度入れ替えの操作を繰り返した場合、カップが想定した位置でなくなってしまうため、想定外の場所に移動してしまう。

該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Operator : MonoBehaviour 6{ 7 //動かす物体を指定 8 public GameObject Mug1; 9 public GameObject Mug2; 10 public GameObject Mug3; 11 12 13 //クラス内で使えるようにする 14 int value; 15 16 //ワールド座標の中心点 17 private Vector3 _center = new Vector3(0.0f, 0.0f, 0.0f); 18 //回転軸 19 private Vector3 _axis = Vector3.up; 20 //円運動周期 21 public float _period; 22 //実行時間指定 23 public float seconds; 24 25 26 //マグを動かす 27 void Update() 28 { 29 //ランダムな数値を生成 30 value = Random.Range(0, 1); 31 32 //ワールド座標の中心点を決める 33 if (value == 1) 34 { 35 _center.z = 25.0f; 36 } 37 else if (value == 2) 38 { 39 _center.z = -25.0f; 40 } 41 42 seconds += Time.deltaTime; 43 44 if (seconds <= _period) 45 { 46 //端のマグが動く 47 if (value == 0) 48 { 49 // 中心点centerの周りを、軸axisで、period周期で円運動 50 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 51 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 52 } 53 else if (value == 1)//右側のマグが動く 54 { 55 // 中心点centerの周りを、軸axisで、period周期で円運動 56 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 57 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 58 } 59 else//左側のマグが動く 60 { 61 // 中心点centerの周りを、軸axisで、period周期で円運動 62 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 63 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 64 } 65 } 66 } 67}

試したこと

C#

1 2 //マグを動かす 3  vois Start() 4 { 5 Mug() 6  Mug() 7 } 8 9 void Update() 10  { 11 seconds += Time.deltaTime; 12 } 13 14 void Mug() 15 { 16 //ランダムな数値を生成 17 value = Random.Range(0, 1); 18 19 //ワールド座標の中心点を決める 20 if (value == 1) 21 { 22 _center.z = 25.0f; 23 } 24 else if (value == 2) 25 { 26 _center.z = -25.0f; 27 } 28 29 30 31 while(seconds <= _period) 32 { 33 //端のマグが動く 34 if (value == 0) 35 { 36 // 中心点centerの周りを、軸axisで、period周期で円運動 37 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 38 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 39 } 40 else if (value == 1)//右側のマグが動く 41 { 42 // 中心点centerの周りを、軸axisで、period周期で円運動 43 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 44 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 45 } 46 else//左側のマグが動く 47 { 48 // 中心点centerの周りを、軸axisで、period周期で円運動 49 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 50 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 51 } 52 } 53 } 54}

###このように変更しました

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Operator : MonoBehaviour 6{ 7 //動かす物体を指定 8 public GameObject Mug1; 9 public GameObject Mug2; 10 public GameObject Mug3; 11 12 13 //クラス内で使えるようにする 14 int value; 15 16 //ワールド座標の中心点 17 private Vector3 _center = new Vector3(0.0f, 0.0f, 0.0f); 18 //回転軸 19 private Vector3 _axis = Vector3.up; 20 //円運動周期 21 public float _period; 22 //実行時間指定 23 public float seconds; 24 25 bool counting = false; 26 27 void Start() 28 { 29 counting = false; 30 31 StartCoroutine("transformMug"); 32 33 } 34 35 void Update() 36 { 37 if(counting == true) 38 { 39 seconds += Time.deltaTime; 40 } 41 } 42 43 44 //マグを動かす 45 IEnumerator transformMug() 46 { 47 counting = false; 48 49 //ランダムな数値を生成 50 value = Random.Range(0, 1); 51 52 //ワールド座標の中心点を決める 53 if (value == 1) 54 { 55 _center.z = 25.0f; 56 } 57 else if (value == 2) 58 { 59 _center.z = -25.0f; 60 } 61 62 counting = true; 63 while(seconds <= _period) 64 { 65 //端のマグが動く 66 if (value == 0) 67 { 68 // 中心点centerの周りを、軸axisで、period周期で円運動 69 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 70 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 71 } 72 else if (value == 1)//右側のマグが動く 73 { 74 // 中心点centerの周りを、軸axisで、period周期で円運動 75 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 76 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 77 } 78 else//左側のマグが動く 79 { 80 // 中心点centerの周りを、軸axisで、period周期で円運動 81 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 82 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 83 } 84 } 85 counting = false; 86 87 88 Mug1.transform.Translate(0, 20, 50); 89 Mug2.transform.Translate(0, 20, 0); 90 Mug3.transform.Translate(0, 20, -50); 91 92 } 93}

#その次にこのように変更しました

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Operator : MonoBehaviour 6{ 7 //動かす物体を指定 8 public GameObject Mug1; 9 public GameObject Mug2; 10 public GameObject Mug3; 11 12 13 //クラス内で使えるようにする 14 int value; 15 16 //ワールド座標の中心点 17 private Vector3 _center = new Vector3(0.0f, 0.0f, 0.0f); 18 //回転軸 19 private Vector3 _axis = Vector3.up; 20 //円運動周期 21 public float _period; 22 //実行時間指定 23 public float seconds; 24 25 26 bool counting = false; 27 28 void Start() 29 { 30 for (int i = 0; i < 3; i++) 31 { 32 33 34 StartCoroutine("transformMug"); 35 } 36 37 } 38 39 void Update() 40 { 41 Debug.Log("計測中"); 42 if(counting == true) 43 { 44 seconds += Time.deltaTime; 45 } 46 } 47 48 49 //マグを動かす 50 IEnumerator transformMug() 51 { 52 Debug.Log("コルーチン開始"); 53 counting = false; 54 55 //ランダムな数値を生成 56 value = Random.Range(0, 3); 57 58 //ワールド座標の中心点を決める 59 if (value == 1) 60 { 61 _center.z = 25.0f; 62 } 63 else if (value == 2) 64 { 65 _center.z = -25.0f; 66 } 67 68 Debug.Log("マグ移動開始"); 69 counting = true; 70 while(seconds <= _period) 71 { 72 //端のマグが動く 73 if (value == 0) 74 { 75 // 中心点centerの周りを、軸axisで、period周期で円運動 76 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 77 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 78 yield return null; 79 } 80 else if (value == 1)//右側のマグが動く 81 { 82 // 中心点centerの周りを、軸axisで、period周期で円運動 83 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 84 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 85 yield return null; 86 } 87 else//左側のマグが動く 88 { 89 // 中心点centerの周りを、軸axisで、period周期で円運動 90 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 91 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 92 yield return null; 93 } 94 } 95 counting = false; 96 97 98 //初期位置に移動 99 Transform Mug1t = Mug1.transform; 100 Transform Mug2t = Mug2.transform; 101 Transform Mug3t = Mug3.transform; 102 103 Vector3 pos1 = Mug1.transform.position; 104 pos1.z = 50f; 105 Vector3 pos2 = Mug2.transform.position; 106 pos2.z = 0f; 107 Vector3 pos3 = Mug3.transform.position; 108 pos3.z = -50f; 109 110 Mug1.transform.position = pos1; 111 Mug2.transform.position = pos2; 112 Mug3.transform.position = pos3; 113 114 yield return new WaitForSeconds(1.0f); 115 116 yield break; 117 } 118}

初期位置に移動はあまり気にしないでください。
コルーチンを使って、処理を行うようにしました。
######しかし、問題も発生してしまいました。
なぜか、二度目のカップを移動させる処理で、前回の処理と同じように移動してしまいます。毎度ランダムな数値を設定しているはずなのですがうまくいきません。どうすればいいでしょうか。

補足情報(FW/ツールのバージョンなど)

2020.2.0のバージョンを使っていて、3Dで作っています。

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

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

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

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

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

guest

回答2

0

コルーチンを使ってみては?

追記: コルーチンについて

関数と同じような書き方になります。
以下、テストで組んだコード

C#

1using System.Collections; 2using UnityEngine; 3 4public class CoroutineTest : MonoBehaviour 5{ 6 7 int num; // 動かす回数 8 9 void Start() { 10 StartCoroutine("TestEnumerator"); 11 } 12 13 IEnumerator TestEnumerator() { 14 Debug.Log("コルーチン開始"); 15 16 num = 5; // 回数指定 17 18 for (var i = 0; i < num; i++) { 19 Debug.Log("繰り返し: " + (i + 1).ToString() + "回目"); 20 21 // 1秒待つ 22 yield return new WaitForSecondsRealtime(1f); 23 } 24 25 Debug.Log("コルーチン終了"); 26 27 yield break; 28 } 29}

実行結果
コルーチンの実行結果

こんな感じで、**「指定秒待つ」「指定の処理が終わるまで待つ」**といったことが簡単に行えます。
Update()で管理するよりははるかに楽だと思うので検討してみてください。

ただ、この場でコルーチンについて語るのは厳しいので詳しい使い方は調べていただくことになります…。

追記: コルーチンについて2

コルーチンは一度実行してしまえば独自で処理をやり切ります。
ですので、Update()と併用も可能です。

C#

1using System.Collections; 2using UnityEngine; 3 4public class CoroutineTest : MonoBehaviour 5{ 6 7 int num; // 動かす回数 8 9 bool counting = false; // カウントするかどうか 10 float elapsedTime = 0.0f; // 経過時間 11 12 void Start() { 13 // カウント用変数の初期化 14 counting = false; 15 elapsedTime = 0.0f; 16 17 StartCoroutine("TestEnumerator"); 18 } 19 20 void Update() { 21 if (counting) { 22 elapsedTime += Time.deltaTime; 23 24 // ログが多量に出るので、経過時間を四捨五入してわざとログがダブるようにしています。 25 Debug.Log("カウント: " + Mathf.RoundToInt(elapsedTime).ToString() + "秒"); 26 } 27 } 28 29 IEnumerator TestEnumerator() { 30 Debug.Log("コルーチン開始"); 31 32 // countingをtrueにしてカウントスタート 33 counting = true; 34 Debug.Log("カウント開始"); 35 36 num = 5; // 回数指定 37 38 for (var i = 0; i < num; i++) { 39 Debug.Log("繰り返し: " + (i + 1).ToString() + "回目"); 40 41 // 1秒待つ 42 yield return new WaitForSecondsRealtime(1f); 43 } 44 45 Debug.Log("コルーチン終了"); 46 47 counting = false; 48 Debug.Log("カウント停止"); 49 50 yield break; 51 } 52}

コルーチンの実行結果2

投稿2021/01/06 05:07

編集2021/01/07 12:42
PinoMatcha

総合スコア368

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

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

actionstudio

2021/01/07 08:29

どのように使うのか具体的に教えていただきたいです。
PinoMatcha

2021/01/07 08:55

回答に追記しました。
actionstudio

2021/01/07 10:12

ありがとうございます。 コルーチンを使って、指定の処理が終わるまで待つというやり方はうまく使えそうな気がします。しかし、時間処理でマグカップを動かしているので、コルーチンを実行しながら時間を計測するやり方がわかりません。もしかしたらもっといいやり方があるかもしれないので、探してみようと思います。 コルーチンで処理を繰り返すときに、時間計測を並行できるやり方があれば教えてください。
PinoMatcha

2021/01/07 10:18

繰り返し処理中に、しょっちゅう経過時間のカウントを止めるなどトリッキーなことを行わないのであれば普通に時間計測だけupdate()でいいと思います。
actionstudio

2021/01/07 10:30 編集

しかし、コルーチンをstart()で呼び出してそのまま処理を続けていけば、update()はstart()の後に呼ばれるために、実行されることはありませんよね?その場合どうしたらよいのでしょうか。 また、今作っているゲームでは、何秒間処理を実行するというやり方でやっているので、ゲームの開始からの時間経過を測るのでは難しい気がします。 時間処理はやはり難しいですか? 例えば、決まった時間だけ処理をするとか、オブジェクトが指定した場所まで移動したらストップするとかのほうがいい気がします。
PinoMatcha

2021/01/07 12:43

回答に追記しました。
actionstudio

2021/01/07 23:40

ありがとうございます。 参考にして、改善しましたが、うまくいかない部分も出てきてしまいました。
PinoMatcha

2021/01/08 06:08 編集

yield break;はコルーチンの終了を表すものです。 最後に添えておいてください。 また、条件分岐でyield break;すれば任意のタイミングでコルーチンを終了することもできます。 あと、コルーチンでwhileを扱う場合、 yield return null; を記述しておかないと実行時にunityがフリーズする可能性があります。 以下、参考 * IEnumerator TestEnumerator() {   while (条件) {     yield return null;   }   yield break; ←コルーチン終了 }
actionstudio

2021/01/08 09:39 編集

ありがとうございます。 編集したところを見てください。変更点を書き加えました。 しかし問題も発生してしまいました。
guest

0

自己解決

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Operator : MonoBehaviour 6{ 7 //動かす物体を指定 8 public GameObject Mug1; 9 public GameObject Mug2; 10 public GameObject Mug3; 11 12 13 //クラス内で使えるようにする 14 int value; 15 16 //ワールド座標の中心点 17 private Vector3 _center = new Vector3(0.0f, 0.0f, 0.0f); 18 //回転軸 19 private Vector3 _axis = Vector3.up; 20 //円運動周期 速度 21 public float _period; 22 //実行時間指定 23 public float seconds = 0.0f; 24 25 //カウントするか否かのboolの初期化 26 bool counting = false; 27 28 //待ち時間の設定 29 public float WFS; 30 31 void Start() 32 { 33 StartCoroutine("transformMug"); 34 } 35 36 void Update() 37 { 38 if (counting == true) 39 { 40 Debug.Log("計測中"); 41 seconds += Time.deltaTime; 42 } 43 else 44 { 45 Debug.Log("seconds初期化"); 46 seconds = 0.0f; 47 } 48 } 49 50 51 //マグを動かす 52 IEnumerator transformMug() 53 { 54 Debug.Log("コルーチン開始"); 55 for (int i = 0; i < 5; i++ ){ 56 Debug.Log("for開始"); 57 58 //ランダムな数値を生成 59 Debug.Log("ランダムな数値を作成"); 60 value = Random.Range(0, 3); 61 Debug.Log(value); 62 63 64 //ワールド座標の中心点を決める 65 if(value == 0) 66 { 67 _center.z = 0.0f; 68 } 69 else if (value == 1) 70 { 71 _center.z = 25.0f; 72 } 73 else if (value == 2) 74 { 75 _center.z = -25.0f; 76 } 77 78 Debug.Log("マグ移動開始"); 79 80 counting = true; 81 while (seconds <= _period) 82 { 83 //端のマグが動く 84 if (value == 0) 85 { 86 // 中心点centerの周りを、軸axisで、period周期で円運動 87 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 88 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 89 yield return null; 90 } 91 else if (value == 1)//右側のマグが動く 92 { 93 // 中心点centerの周りを、軸axisで、period周期で円運動 94 Mug1.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 95 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 96 yield return null; 97 } 98 else//左側のマグが動く 99 { 100 // 中心点centerの周りを、軸axisで、period周期で円運動 101 Mug2.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 102 Mug3.transform.RotateAround(_center, _axis, 180 / _period * Time.deltaTime); 103 yield return null; 104 } 105 } 106 counting = false; 107 Debug.Log("マグ移動終了"); 108 109 Debug.Log("初期位置に移動"); 110 //初期位置に移動 111 Transform Mug1t = Mug1.transform; 112 Transform Mug2t = Mug2.transform; 113 Transform Mug3t = Mug3.transform; 114 115 Vector3 pos1 = Mug1.transform.position; 116 pos1.z = 50f; 117 Vector3 pos2 = Mug2.transform.position; 118 pos2.z = 0f; 119 Vector3 pos3 = Mug3.transform.position; 120 pos3.z = -50f; 121 122 Mug1.transform.position = pos1; 123 Mug2.transform.position = pos2; 124 Mug3.transform.position = pos3; 125 126 yield return new WaitForSeconds(WFS); 127 Debug.Log("一秒待った"); 128 Debug.Log("for一巡終了"); 129 } 130 131 Debug.Log("コルーチン終了"); 132 yield break; 133 } 134}

コルーチン内でforを使うことで問題が解決できました。
コルーチンはUpdateと並行して処理することができるので、Update内で時間測定をしながら、コルーチン内のforを使って処理を繰り返しました。

投稿2021/01/09 09:39

actionstudio

総合スコア39

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問