teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

コメントを受けて追記

2017/12/21 11:47

投稿

sakura_hana
sakura_hana

スコア11429

answer CHANGED
@@ -57,4 +57,82 @@
57
57
  - 全てのループでrandomIndexがjと同値になった場合(同じ場所のものを入れ替えるので並び替えされない)
58
58
  - シャッフル後に元に戻った場合(「j=0の時randomIndex=1、j=1の時randomIndex=0」などが続いた時) など
59
59
 
60
- 「絶対シャッフルされたい」「なるべくバラバラにシャッフルされたい」という場合は別の方法を調べてみてください。
60
+ 「絶対シャッフルされたい」「なるべくバラバラにシャッフルされたい」という場合は別の方法を調べてみてください。
61
+
62
+ ---
63
+ 2017/12/21 20:50 コメントを受けて追記
64
+
65
+ 「layerの配列をシャッフルしたい」という質問だったのでそう答えましたが、
66
+ そもそもの話をすると、質問文のコードはlayer配列を使用していません。
67
+
68
+ void Word() の中で
69
+ `string layer = "word" + 1.ToString();`
70
+ と記載しているので、layer変数には常に"word1"が入っています。
71
+ 更に言うとこのlayerはレイヤーマスクを指定しているだけであり、テクスチャの変更はしていないです。
72
+
73
+ 順番に表示されているのは「マテリアルの配列(material変数)」です。
74
+ これで表示が切り替わるということは、material配列にテクスチャ違いのマテリアルが複数入っているということですね。
75
+
76
+ もう面倒臭いので「恐らくこういうことがしたいのだろう」という全コード書きますね。
77
+
78
+ ```C#
79
+ //配列をシャッフルしてから順番に使用するパターン
80
+ using UnityEngine;
81
+ using System.Collections;
82
+
83
+ public class Stage : MonoBehaviour {
84
+
85
+ public Material[] material;
86
+ private string[] layer =
87
+ { "word1","word2","word3","word4","word5","word6","word7","word8","word9", "word10"}; //定義していますが使っていません
88
+ private int i;
89
+
90
+ void Start() {
91
+ Shuffle (); //最初に配列シャッフルする
92
+ }
93
+
94
+ //配列をシャッフルするコード
95
+ void Shuffle () {
96
+ for (int j = 0; j < material.Length; j++)
97
+ {
98
+ Material temp = material[j];
99
+ int randomIndex = Random.Range(0, material.Length);
100
+ material[j] = material[randomIndex];
101
+ material[randomIndex] = temp;
102
+ }
103
+ }
104
+
105
+ //シャッフルされた配列を使う
106
+ void Word()
107
+ {
108
+ GameObject wd = Instantiate(WordPrefab, new Vector3(0, 1, 1), Quaternion.identity) as GameObject;
109
+ string layer = "word1";
110
+ wd.gameObject.layer = LayerMask.NameToLayer(layer);
111
+ Renderer rend = wd.GetComponentInChildren<Renderer>();
112
+ rend.material = material[i];
113
+ i += 1;
114
+
115
+ //materialの数以上になるとエラーになるので、その場合0に戻す
116
+ if (i >= material.Length) {
117
+ i = 0;
118
+ }
119
+ }
120
+ ```
121
+
122
+ ```C#
123
+ //別解:毎回ランダムで取得するパターン(かつ要らない変数をごっそり削除)
124
+ using UnityEngine;
125
+ using System.Collections;
126
+
127
+ public class Stage : MonoBehaviour {
128
+
129
+ public Material[] material;
130
+
131
+ void Word()
132
+ {
133
+ GameObject wd = Instantiate(WordPrefab, new Vector3(0, 1, 1), Quaternion.identity) as GameObject;
134
+ wd.gameObject.layer = LayerMask.NameToLayer("word1");
135
+ Renderer rend = wd.GetComponentInChildren<Renderer>();
136
+ rend.material = material[Random.Range(0, material.Length)];
137
+ }
138
+ ```

1

コメントを受けて追記

2017/12/21 11:47

投稿

sakura_hana
sakura_hana

スコア11429

answer CHANGED
@@ -1,3 +1,60 @@
1
1
  以下のページが参考になるので、一度読んでみてください。
2
2
  [参考ページ1](https://teratail.com/help/question-tips)
3
- [参考ページ2](https://docs.unity3d.com/ja/current/Manual/RandomNumbers.html)
3
+ [参考ページ2](https://docs.unity3d.com/ja/current/Manual/RandomNumbers.html)
4
+
5
+ ---
6
+ 2017/12/18 20:50 コメントを受けて追記
7
+
8
+ ソースコードはほぼ合っています。
9
+ 一部 } の数などがおかしいので、動くように直すとこう。
10
+
11
+ ```C#
12
+ private string[] layer = {"word1","word2","word3","word4","word5","word6","word7","word8","word9", "word10"};
13
+
14
+ for (int j = 0; j < layer.Length; j++)
15
+ {
16
+ string temp = layer[j]; //stringで問題無いです。
17
+ int randomIndex = Random.Range(0, layer.Length);
18
+ layer[j] = layer[randomIndex];
19
+ layer[randomIndex] = temp;
20
+ }
21
+ ```
22
+ 「かと言ってintをstringにかえても??」
23
+ 何故疑問に思ったか分かりませんが、まさにそれが答えです。
24
+
25
+ `Random.Range`は検索すると分かりますが「第一引数から'第二引数-1'の内、ランダムな数1つを返す」というメソッドです。
26
+ layer.Lengthは10なので、`Random.Range(0, layer.Length)`は「0から9までのランダムな数字1つ」と同じ意味です。
27
+ これ自体はただのintを返すだけで、「Random.Rangeが配列の要素そのものを指すわけではない」ことに注意です。
28
+
29
+ これを踏まえてfor文の挙動を見てみましょう。
30
+
31
+ ```
32
+ j = 0の時
33
+ tempにlayer[0]格納(temp = "word1")
34
+ randomIndexにランダムな数字が入る(randomIndex = 3とする)
35
+ layer[0]にlayer[3]が入る(layer[0] = "word4", layer[3] = "word4")
36
+ layer[3]にtempが入る(layer[0] = "word4", layer[3] = "word1")
37
+
38
+ 現在のlayer:0番目と3番目が入れ替わった
39
+ {"word4","word2","word3","word1","word5","word6","word7","word8","word9", "word10"}
40
+
41
+ j = 1の時
42
+ tempにlayer[1]格納(temp = "word2")
43
+ randomIndexにランダムな数字が入る(randomIndex = 2とする)
44
+ layer[1]にlayer[2]が入る(layer[1] = "word3", layer[2] = "word3")
45
+ layer[2]にtempが入る(layer[1] = "word3", layer[2] = "word2")
46
+
47
+ 現在のlayer:1番目と2番目が入れ替わった
48
+ {"word4","word3","word2","word1","word5","word6","word7","word8","word9", "word10"}
49
+
50
+ (以下、j=9まで続く)
51
+ ```
52
+
53
+ というように、シャッフルが行われます。
54
+ 挙動がおかしい場合は、「エラーコードを見て問題点を探す」「初めて見るメソッドはまず検索してみる」「プログラムや実際の挙動を日本語で書いてみる」等すると自力解決しやすいです。
55
+
56
+ なお、この方法だと低確率で「シャッフルされない」「1項目だけしかシャッフルされない」などのケースが出ます。
57
+ - 全てのループでrandomIndexがjと同値になった場合(同じ場所のものを入れ替えるので並び替えされない)
58
+ - シャッフル後に元に戻った場合(「j=0の時randomIndex=1、j=1の時randomIndex=0」などが続いた時) など
59
+
60
+ 「絶対シャッフルされたい」「なるべくバラバラにシャッフルされたい」という場合は別の方法を調べてみてください。