質問: Enumerable.Range(0, objcts.Length).OrderBy(n => Guid.NewGuid()).Take(objcts.Length).ToArray(); } instantiateObj(objIdxAry[idx]); idx++; yield return waitTime; } } } ```
回答: 遅くなりました。すみません。 怒られちゃいましたねw ご自分でわかっていらっしゃると思うので折り合いつくとこまで進めたら少し勉強時間をはさんでみてもいいかもしれませんね。 Unityの本を買って説明を読みながら掲載されているサンプルを手打ちで打っていくとある程度わかってくると思います。Unityはどんどこ進んでいるので今は本で学ぶのが一番です。 ということでspawnNext()で呼ぶタイプに書き直しました。 相変わらず未検証です。コメントをたっぷり入れたので思ったような挙動にならなければご自身で修正してみてください。そして、どうしても分からなければその部分のコードと一緒に質問してみてください。 **使い方** 1. 下記コードをコピーしcreateRandObjsという名前でスクリプトとして保存 !createRandObjs 2. ゲームオブジェクトをヒエラルキーに作成 !ゲームオブジェクト 3. createRandObjs.csをオブジェクトにアタッチ !イメージ説明 4. ゲームオブジェクトのインスペクタに配列が入れられるようになっているのでオブジェクトを追加 !オブジェクトを追加 **5. 別スクリプトから「createRandObjs.Instance.spawnNext();」を呼ぶ** 以上です。 **外から呼ばれるということなのでシングルトンにしました。** ``` using UnityEngine; using System.Linq; using System; using System.Collections; public class createRandObjs : MonoBehaviour { //とりあえずインスペクタからオブジェクトを追加 [SerializeField] GameObject[] objcts; //外部から呼び出せるように静的なフィールドとプロパティを定義 //そうしておくと外部からcreateRandObjs.Instance.spawnNext()で呼び出せます。 static createRandObjs instance; public static createRandObjs Instance { get { //インスタンスがなければインスタンスを生成 Awakeより先にこのプロパティが呼ばれる可能性があるのでここでもチェックとnullであればインスタンス化します。 if(instance == null) instance = (createRandObjs) FindObjectOfType( typeof(createRandObjs) ); return instance; } } // オブジェクトを順番にカウントするための変数 int objIdx; // オブジェクトのランダムなインデックスを格納する配列 int[] objIdxAry; void Awake() { //インスタンスがなければインスタンス化 if(instance == null) instance = (createRandObjs) this; //すでにインスタンスが存在すれば自身を破棄 インスタンスは1つでいいので重複対策です。 else if( Instance != this ) Destroy(this); } /// /// オブジェクトを出力する /// void instantiateObj(int idx) { //とりあえずVector3.zero地点にオブジェクトを生成 Instantiate(objcts[idx], Vector3.zero, Quaternion.identity); } /// /// 外部から呼ばれる オブジェクトを出力する /// public void spawnNext() { //オブジェクトが無ければ何もせず終了 if(objcts.Length == 0) return; //objIdxが0またはobjctsの数に達したらリセット if(objIdx == 0 || objIdx == objcts.Length) { //objIdxをリセット objIdx = 0; //ランダムな配列を生成 objIdxAry = Enumerable.Range(0, objcts.Length).OrderBy(n => Guid.NewGuid()).ToArray(); } //objIdxAryのインデックスを元にオブジェクトを生成 instantiateObj( objIdxAry[objIdx] ); //objIdxを+1する objIdx++; } } ``` **呼ぶ側** ``` createRandObjs.Instance.spawnNext(); ``` ### [以降は読まなくてもいいです] とりあえずコード量を抑える為、必要最低限にしています。 どこまで完成しているか分からないのでなんとも言えないのですが今のコードでは不十分に感じます。考えられるのはこんな感じです。 * オブジェクトの移動完了などの状態を直接知ることができない * テトリスの場合、マップ的なものを用意してx軸が埋まっていれば(略)などの処理の対応 * 消える時のアニメーション などですかね?僕ならオブジェクト一つ一つにスクリプトをつけてそこで、自身の調整や管理と外部への自身の状態や消えるアニメーションのスタートやエンドなどを提供をする形にすると思います。 それをこんな感じでコントロール側で持つと思います。 ``` //これをオブジェクトひとつひとつにアタッチする public class objScript : MonoBehaviour { public bool destroyAnime(int[] targetYs) { //略 //色々して全部消えたらtrueを送る return true; } } //引数などは適当です。実際はint[]を渡す形で組まないかもしれません。 public class createRandObjs : MonoBehaviour { // 生成する時についでにこの配列に参照を渡しておく List objScripts = new List(); void destroyAnime() { //略 //1,2列目を破棄 var isDeleteObj = objScripts[0].destroyAnime(new int[]{ 1,2 }); //もしオブジェクトが完全に消えたら何かする if(isDeleteObj) objScripts.RemoveAt(0); } ```