Search Unity

C# question about OBJECT SPAWNING can someone please help?

Discussion in 'Scripting' started by amichael, Mar 4, 2015.

  1. amichael

    amichael

    Joined:
    Mar 4, 2015
    Posts:
    48
    Hello, i would like to say thanks in advance to anyone who is kind enough to help out. So here it goes, I am new to all of this and i am in the process of creating my own game. Right now my character must avoid obstacles by jumping over them and by ducking under them. Now, the thing is right now i have it set for random generator, and i do not really want a random generator. So my question to you is, how would i go about coding A certain object spawning pattern that i want? For example, right now it is just spawning randomly, BRICK, HOLE, BRICK, FENCE, FENCE, HOLE, ETC.. What i want to do is set my own organized pattern that will always spawn obstacles the same way every time i start the game. Can someone please help me with this? I have been looking for help for over a week now.
     
  2. spryx

    spryx

    Joined:
    Jul 23, 2013
    Posts:
    557
    I've never done this, so take my advice with a grain of salt...

    The way I would accomplish this is to use a "buffer" to store the pattern I want spawns to occur in.
    e.g perhaps an array of 10 items to spawn
    0 fence
    1 cube
    2 sphere
    3 fence
    ..... and so on

    There are probably 100 different ways to do this.
    you cold even write different patterns into a lookup table and switch patterns that way.
     
  3. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    The simple answer is that you probably want to store them in an array or a List--there are some Unity tutorials on working with those data structures here: Arrays - Lists and Dictionaries.
     
  4. amichael

    amichael

    Joined:
    Mar 4, 2015
    Posts:
    48
    Thanks for your response @Antistone and @spryx ... For some reason i cant seem to figure it out. I just keep randomly generating objects, if that doesnt work then it spawns the same object over and over.. Is there a sample code you might be able to give to start my pattern of objects i want to spawn? I have levels drawn out and where the objets should go, but i can not seem to get them to work without a random generator.
     
  5. Juice-Tin

    Juice-Tin

    Joined:
    Jul 22, 2012
    Posts:
    244
    @amichael
    Try something like this:
    Code (CSharp):
    1. //Set up level. 0 = Block, 1 = Bridge
    2. string objectList = "00100101101001010100";
    3. int objectNum = 0;
    4.  
    5. -------------------------------------------
    6. // This is where you would create the objects
    7.  
    8. if(objectList[objectNum] == '0'){
    9. //Spawn Block
    10. }
    11. if(objectList[objectNum] == '1'){
    12. //Spawn Bridge
    13. }
    14. objectNum++;
    15.  
    16. if(objectNum == objectList.Length){
    17. //Reached the end of the objects
    18. }
    The way it works is you first create a string. Each character in the string represents the next object. You can set the characters to ANYTHING you want, I just set it to 1 and 0.

    Later when you create the object, it checks what the current character is, and creates the proper object.
    Then it sets it to the next character. Also, you can do something once it hits the end of the object list.

    Note: The reason I set it up this way is because each object is just 1 character in a string, so you can make a huge list of objects easily in a very small space. That up there is a list of 20 objects, and the code is so tiny.
     
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Perhaps if you posted an excerpt from your current code to demonstrate how you're currently utilizing the random output, we could suggest how to modify it?
     
  7. kdubnz

    kdubnz

    Joined:
    Apr 19, 2014
    Posts:
    177
    You could have a play with something like this
    Comments explain the process

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5.  
    6. public class Starter : MonoBehaviour
    7. {
    8.     // Select the spawning objects in the inspector.
    9.     // Attach the Script to an empty Game object or the Camera.
    10.     // FIFO collection
    11.     public List<GameObject> goList;
    12.  
    13.     private int goListIndex;
    14.     private int goListLength;
    15.     private GameObject currentSpawnObject;
    16.  
    17.     // Awake is called when the script instance is being loaded (Since v1.0)
    18.     private void Awake() {
    19.         goListLength = goList.Count();
    20.         goListIndex = goListLength;
    21.     }
    22.  
    23.     // Update is called once per frame
    24.     private void Update() {
    25.         /*  Continiously iterate the GameObjectList
    26.          *  This could be done on a timer.
    27.          */
    28.         goListIndex = (++goListIndex >= goListLength) ? 0 : goListIndex;
    29.  
    30.         currentSpawnObject = goList[goListIndex];
    31.  
    32.         // perform your mojo to spawn currentSpawnObject
    33.         Debug.Log(currentSpawnObject.name);
    34.     }
    35. }
     
  8. spryx

    spryx

    Joined:
    Jul 23, 2013
    Posts:
    557
    @kdub
    Code (CSharp):
    1.         goListIndex = (++goListIndex >= goListLength) ? 0 : goListIndex;
    Heh, that line is pretty cool...learn something every day
     
  9. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    I normally do that with a modulus
    Code (CSharp):
    1. goListIndex = (goListIndex+1) % goListLength;
     
  10. kdubnz

    kdubnz

    Joined:
    Apr 19, 2014
    Posts:
    177
  11. kdubnz

    kdubnz

    Joined:
    Apr 19, 2014
    Posts:
    177
    @amichael

    Did you post that from your code editor or by copying from the previous post ??

    The post is still not a true representation of your code.

    Kerry
     
  12. amichael

    amichael

    Joined:
    Mar 4, 2015
    Posts:
    48
    @kdub i copied it from my last post and added the tag. Sorry buddy, not trying to intentionally make things difficult.
     
  13. amichael

    amichael

    Joined:
    Mar 4, 2015
    Posts:
    48
    @kdub i deleted the others and copied it directly.





    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. using System.Collections;
    4.  
    5. public class ObstacleGeneration : MonoBehaviour {
    6.  
    7.     public GameObject highBrickPrefab, lowBrickPrefab, fencePrefab;
    8.  
    9.     public float recycle;
    10.     public float minZ, maxZ;
    11.     public int numberOfObjects;
    12.     private Vector3 lowPos, highPos, fPos;
    13.     public float lowBrickProbability, highBrickProbability, fenceProbability;
    14.     private Vector3 nextPos;
    15.     private Queue<Transform> obstacleQueue;
    16.     private Transform player;
    17.     private int curObst;
    18.     private int curQue = 1;
    19.     private bool start = true;
    20.     private bool nextCreate = false;
    21.     private bool waitCreate = true;
    22.  
    23.  
    24.  
    25.  
    26.     void Start()
    27.     {
    28.  
    29.  
    30.         player = GameObject.FindGameObjectWithTag("Player").transform;
    31.         highPos = new Vector3(3.083166f, 1.491387f, player.position.z);
    32.         lowPos = new Vector3(3.083166f, 0.2214425f, player.position.z);
    33.         carPos = new Vector3(4.687229f, 0.0924263f, player.position.z);
    34.         obstacleQueue = new Queue<Transform>(numberOfObjects);
    35.         Creation();
    36.         for(int i = 0; i < numberOfObjects; i++)
    37.         {
    38.             Recycle();
    39.         }
    40.         start=false;
    41.     }
    42.  
    43.     private void Creation()
    44.     {
    45.      
    46.         for(int i = 0; i < numberOfObjects; i++)
    47.         {
    48.             curObst = Random.Range(0,100);
    49.  
    50.             if(curObst <= lowBrickProbability)
    51.             {
    52.                 obstacleQueue.Enqueue((Transform) Instantiate(highBrickPrefab.transform));
    53.                 if(i == 0 && start)
    54.                 {
    55.                     nextPos = highPos;
    56.                 }
    57.             }
    58.              
    59.             else if(curObst <= highBrickProbability && curObst > lowBrickProbability)
    60.             {
    61.                 obstacleQueue.Enqueue((Transform) Instantiate(lowBrickPrefab.transform));
    62.                 if(i == 0 && start)
    63.                 {
    64.                     nextPos = lowPos;
    65.                 }
    66.             }
    67.              
    68.             else if(curObst <= fenceProbability && curObst > highBrickProbability)
    69.             {
    70.                 obstacleQueue.Enqueue((Transform) Instantiate(fencePrefab.transform));
    71.                 if(i == 0 && start)
    72.                 {
    73.                     nextPos =fPos;
    74.                 }
    75.             }
    76.          
    77.             else if(curObst <= fenceProbability && curObst > fenceProbability)
    78.             {
    79.                 obstacleQueue.Enqueue((Transform) Instantiate(longcarPrefab.transform));
    80.                 if(i == 0 && start)
    81.                 {
    82.                     nextPos =fPos;
    83.                 }
    84.             }
    85.          
    86.             else
    87.             {
    88.                 Debug.Log ("BREAK");
    89.             }  
    90.          
    91.         }
    92.     }
    93.  
    94.     private void Recycle(float extraZ = 0f)
    95.     {
    96.         Transform o = obstacleQueue.Dequeue();
    97.         if(o.name == highBrickPrefab.name+"(Clone)")
    98.         {
    99.             nextPos = new Vector3(highPos.x,highPos.y,nextPos.z);
    100.          
    101.         }
    102.         else if(o.name == lowBrickPrefab.name+"(Clone)")
    103.         {
    104.             nextPos = new Vector3(lowPos.x,lowPos.y,nextPos.z);
    105.         }
    106.         else
    107.         {
    108.             nextPos = new Vector3(fPos.x,fPos.y,nextPos.z);
    109.         }
    110.      
    111.         nextPos += new Vector3(
    112.             0f,
    113.             0f,
    114.             Random.Range((0-minZ)+extraZ, (0-maxZ)+extraZ));
    115.      
    116.         Vector3 position = nextPos;
    117.         o.localPosition = position;
    118.         obstacleQueue.Enqueue(o);
    119.     }
    120.  
    121.     void Update()
    122.     {
    123.         if(curQue <= numberOfObjects && !nextCreate)
    124.         {
    125.             waitCreate = true;
    126.             if(obstacleQueue.Peek().localPosition.z - recycle > player.position.z)
    127.             {
    128.                 Destroy(GameObject.Find (obstacleQueue.Peek().name));
    129.                 obstacleQueue.Dequeue();
    130.                 curQue++;
    131.             }
    132.         }
    133.         else
    134.         {
    135.             nextCreate = true;
    136.             StartCoroutine(Wait(0.5f));
    137.             curQue = 1;
    138.         }
    139.     }
    140.  
    141.     private void GameStart()
    142.     {
    143.         nextPos = transform.localPosition;
    144.         for(int i = 0; i < numberOfObjects; i++)
    145.         {
    146.             Recycle();
    147.         }
    148.      
    149.     }
    150.  
    151.     IEnumerator Wait(float duration)
    152.     {
    153.         if(waitCreate)
    154.         {
    155.             waitCreate = false;
    156.             yield return new WaitForSeconds(duration);   //Wait
    157.             Creation();
    158.             for(int i = 0; i < numberOfObjects; i++)
    159.             {
    160.                 if(i == 0)
    161.                 {
    162.                     Recycle(-25f);
    163.                 }
    164.                 else { Recycle(); }
    165.             }
    166.             nextCreate = false;
    167.         }
    168.  
    169.     }
    170. }
    171.  
     
  14. kdubnz

    kdubnz

    Joined:
    Apr 19, 2014
    Posts:
    177
    @amichael
    That's a LOT better.
    You are more likely to get responders with that effort :)

    Kerry,
     
  15. amichael

    amichael

    Joined:
    Mar 4, 2015
    Posts:
    48
  16. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    OK, you probably want to take this part:
    Code (CSharp):
    1.     private void Creation()
    2.     {
    3.    
    4.         for(int i = 0; i < numberOfObjects; i++)
    5.         {
    6.             curObst = Random.Range(0,100);
    ...and change it to something like:
    Code (CSharp):
    1.     private void Creation(int[] objects)
    2.     {
    3.    
    4.         foreach(int curObst in objects)
    5.         {
    Then, whenever you call Creation(), you can pass in the objects you want to use as an argument. For example:
    Code (CSharp):
    1. int[] firstLevel = new int[]{1, 1, 2, 1, 3, 5, 7};
    2. Creation(firstLevel);
    That creates a level that has obstacles number 1, 1, 2, 1, 3, 5, and 7, in that order.
     
  17. amichael

    amichael

    Joined:
    Mar 4, 2015
    Posts:
    48
    @Antistone thx buddy, and everyone for all the help you have been giving me with this. Just another question, when you say 1,2,3,4,5, etc. are you assigning the object prefabs to a number? Of so, how do you go about that? Sorry, again still trying to learn all this on my own and with help from all of you guys. I'm really excited about the help you have been giving me with this. I have tried other forums and they were just plain "rude" about my questions, because I was "new" to this stuff.
     
  18. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    No, I'm not assigning object prefabs to the number, I'm just listing numbers. Since you were previously generating random numbers, I assume you already had some way of turning those numbers into prefabs.

    But if you want, instead of passing in an int[], you could pass in a GameObject[], which can contain prefabs instead of numbers. And if you declare a public GameObject[] field in your MonoBehavior, you can populate the array in the inspector by dragging prefabs into it.

    There are many additional flourishes you could add on top of this. Ultimately, you may want to read the levels in from a separate data file. But I suggest you take things one step at a time.
     
    amichael likes this.