2016-05-30 17 views
0

私はUnity3Dでゲームを構築していますが、GameObjectsをインスタンス化して破棄するのではなく有効化と無効化で再利用しようとしています。配列内のオブジェクトを移動/移動して最初の要素を最後のインデックスに移動します

私はGameObject配列に10個のスプリングを持っています。私はスプリングを使うたびに配列の最初の要素から取り出し、その配列の残りの要素をすべてシフトしてから、最初のオブジェクトを配列内の最後のインデックス

+1

なぜのみ再度有効にする必要があり、以前に無効化インスタンスを取得するために無効に要素が追加されたキューを使用して、必要なときに、あなたはそれからデキューありません。なぜ配列ですか? – ray

+0

@ray - わかりません、ちょうど私がしようとしていることを正確に行うための操作をしているかもしれないと思った!前にキューを使用したことはありません。 – LooMeenin

+1

@ LooMeenin:あなたが探している操作がクラスで提供されているかどうかを確認して、そうでない場合にのみコードを書くようにしてください。以前にキューを使用したことがない人は(基本的なデータ構造です)、ゲームプログラミングを習得する前に、またはその中で学ぶ前に、いくつかの基本的なことを理解する必要があります。 – ray

答えて

2

これはオブジェクトプールと呼ばれます。これを行うには、配列を最初から最後まで削除する必要はありません。これをUnityでアーカイブする方法はたくさんあります。

方法1(推奨):これは、配列内のオブジェクトを移動させるために、それは不要かつ非効率的に動作

にもかかわらず。あなたは動き回るインデックスを持つことができます。 0から始まり、オブジェクトを要求するたびに1ずつ増加します。インデックスがArray.Length - 1の場合は、インデックスを0に戻します。

public class ArrayObjectPooling 
{ 
    int amount = 10; 
    GameObject[] objArray; 
    int currentIndex = 0; 

    public ArrayObjectPooling(GameObject objPrefab, string name, int count) 
    { 
     amount = count; 
     objArray = new GameObject[amount]; 

     for (int i = 0; i < objArray.Length; i++) 
     { 
      objArray[i] = UnityEngine.Object.Instantiate(objPrefab, Vector3.zero, Quaternion.identity); 
      objArray[i].SetActive(false); 
      objArray[i].name = name + " #" + i; 
     } 
    } 

    //Returns available GameObject 
    public GameObject getAvailabeObject() 
    { 
     //Get the first GameObject 
     GameObject firstObject = objArray[currentIndex]; 

     //Move the pointer down by 1 
     shiftDown(); 

     return firstObject; 
    } 

    //Returns How much GameObject in the Array 
    public int getAmount() 
    { 
     return amount; 
    } 

    //Moves the current currentIndex GameObject Down by 1 
    private void shiftDown() 
    { 
     if (currentIndex < objArray.Length - 1) 
     { 
      currentIndex++; 
     } 
     else 
     { 
      //Reached the end. Reset to 0 
      currentIndex = 0; 
     } 
    } 
} 

USAGE

public GameObject prefab; 

void Start() 
{ 
    ArrayObjectPooling arrayPool = new ArrayObjectPooling(prefab, "Springs", 10); 
    GameObject myObj = arrayPool.getAvailabeObject(); 
} 

方法2

Listプールが小さなある場合は、これを行うのに十分です。 takeオブジェクトプールに関するUnityの公式チュートリアルを参考にしてください。ここにコードを掲載する必要はありません。

あなたは単にを無効にして、ゲームオブジェクトListを無効にしてリサイクルしてください。次に新しいものが必要なときは、Listをループし、最初の無効なGameObjectをListに返します。有効になっている場合、それはまだ使用中であることを意味します。

無効なGameObjectがListに見つからない場合は、Instantiate新しいものをリストに追加して戻すことができます。これはこれを行う最も簡単な方法です。詳細についてはUnityチュートリアルをご覧ください。


方法3

使用キューまたはスタック。プールからオブジェクトをキューに入れ、エンキューしたりプッシュ/ポップしたりできます。あなたがこれについて簡単なreseach-searchをすれば、そこには多くの実装があります。


方法4

これは配列で、最大のオブジェクトをシフトして、配列の最後のインデックスに最初の値を入れる方法についてのあなたの元の質問だったので、これはのみ言及されています。これを使わないでください。 とすることができます。

public class ArrayObjectPooling 
{ 
    int amount = 10; 
    public GameObject[] objArray; 

    public ArrayObjectPooling(GameObject objPrefab, string name, int count) 
    { 
     amount = count; 
     objArray = new GameObject[amount]; 

     for (int i = 0; i < objArray.Length; i++) 
     { 
      objArray[i] = UnityEngine.Object.Instantiate(objPrefab, Vector3.zero, Quaternion.identity); 
      objArray[i].SetActive(false); 
      objArray[i].name = name + " #" + i; 
     } 
    } 

    //Returns available GameObject 
    public GameObject getAvailabeObject() 
    { 
     //Get the first GameObject 
     GameObject firstObject = objArray[0]; 

     //Move everything Up by one 
     shiftUp(); 

     return firstObject; 
    } 

    //Returns How much GameObject in the Array 
    public int getAmount() 
    { 
     return amount; 
    } 

    //Moves the GameObject Up by 1 and moves the first one to the last one 
    private void shiftUp() 
    { 
     //Get first GameObject 
     GameObject firstObject = objArray[0]; 

     //Shift the GameObjects Up by 1 
     Array.Copy(objArray, 1, objArray, 0, objArray.Length - 1); 

     //(First one is left out)Now Put first GameObject to the Last one 
     objArray[objArray.Length - 1] = firstObject; 
    } 
} 

USAGE

public GameObject prefab; 

void Start() 
{ 
    ArrayObjectPooling arrayPool = new ArrayObjectPooling(prefab, "Springs", 3); 
    GameObject myObj = arrayPool.getAvailabeObject(); 
} 
+0

そうだと思っていましたが、GameObjectsが有効になっているかどうか確認したくありませんでした。配列やリストの最後にGameObjectをスローする配列やリストの操作があると考えられます。そのようにすれば、毎回チェックなしで配列の最初のGameObjectを使うことができます – LooMeenin

+0

私は前にこのチュートリアルを見てきましたが、過去にオブジェクトプールを使っていましたが、このシナリオでは配列やリスト私が記述した操作を持つ何らかの種類のものです。そのような操作がない場合、私は他の何かを描くでしょう。 – LooMeenin

+0

@LooMeenin **ゲームオブジェクトをインスタンス化して破壊するのではなく、ゲームオブジェクトを有効または無効にして再利用しようとしています**現在、有効/無効をチェックしたくないと言っていますか?最初にそれらを有効/無効にするのはなぜですか?配列を使用したい場合は、10個以上のスプリングが必要な場合はどうすればよいですか?彼らはゲーム中に永久に10であることが保証されていますか? – Programmer

関連する問題