Search Unity

Question How to spawn coins in a given place?

Discussion in 'Scripting' started by kobrata_6, Jun 7, 2020.

  1. kobrata_6

    kobrata_6

    Joined:
    Jun 2, 2020
    Posts:
    4
    Basically I am making a copy of Flappy bird, so I can get better at Unity. I am beginner and now I have a problem. I want to spawn a coin between the pipes. Here is my parallaxer.cs where I spawn the pipes. I want to spawn a coin on every forth pipe. How can I do it?

    Code (CSharp):
    1. public class Parallaxer : MonoBehaviour {
    2.  
    3.     class PoolObject {
    4.         public Transform transform;
    5.         public bool inUse;
    6.         public PoolObject(Transform t) { transform = t; }
    7.         public void Use() { inUse = true; }
    8.         public void Dispose() { inUse = false; }
    9.     }
    10.  
    11.     [System.Serializable]
    12.     public struct YSpawnRange {
    13.         public float min;
    14.         public float max;
    15.     }
    16.  
    17.     public GameObject Prefab;
    18.     public int poolSize;
    19.     public float shiftSpeed;
    20.     public float spawnRate;
    21.  
    22.     public YSpawnRange ySpawnRange;
    23.     public Vector3 defaultSpawnPos;
    24.     public bool spawnImmediate;
    25.     public Vector3 immediateSpawnPos;
    26.     public Vector2 targetAspectRatio;
    27.  
    28.     float spawnTimer;
    29.     PoolObject[] poolObjects;
    30.     float targetAspect;
    31.     GameManager game;
    32.  
    33.     void Awake() {
    34.         Configure();
    35.     }
    36.  
    37.     void Start() {
    38.         game = GameManager.Instance;
    39.     }
    40.  
    41.     void OnEnable() {
    42.         GameManager.OnGameOverConfirmed += OnGameOverConfirmed;
    43.     }
    44.  
    45.     void OnDisable() {
    46.         GameManager.OnGameOverConfirmed -= OnGameOverConfirmed;
    47.     }
    48.  
    49.     void OnGameOverConfirmed() {
    50.         for (int i = 0; i < poolObjects.Length; i++) {
    51.             poolObjects[i].Dispose();
    52.             poolObjects[i].transform.position = Vector3.one * 1000;
    53.         }
    54.         // Configure();
    55.         if (spawnImmediate) {
    56.             SpawnImmediate();
    57.         }
    58.     }
    59.  
    60.     void Update() {
    61.         if (game.GameOver) return;
    62.  
    63.         Shift();
    64.         spawnTimer += Time.deltaTime;
    65.         if (spawnTimer > spawnRate) {
    66.             Spawn();
    67.             spawnTimer = 0;
    68.         }
    69.     }
    70.  
    71.     void Configure() {
    72.         //spawning pool objects
    73.         targetAspect = targetAspectRatio.x / targetAspectRatio.y;
    74.         poolObjects = new PoolObject[poolSize];
    75.         for (int i = 0; i < poolObjects.Length; i++) {
    76.             GameObject go = Instantiate(Prefab) as GameObject;
    77.             Transform t = go.transform;
    78.             t.SetParent(transform);
    79.             t.position = Vector3.one * 1000;
    80.             poolObjects[i] = new PoolObject(t);
    81.         }
    82.  
    83.         if (spawnImmediate) {
    84.             SpawnImmediate();
    85.         }
    86.     }
    87.  
    88.     void Spawn() {
    89.         //moving pool objects into place
    90.         Transform t = GetPoolObject();
    91.         if (t == null) return;
    92.         Vector3 pos = Vector3.zero;
    93.         pos.y = Random.Range(ySpawnRange.min, ySpawnRange.max);
    94.         pos.x = (defaultSpawnPos.x * Camera.main.aspect) / targetAspect;
    95.         t.position = pos;
    96.     }
    97.  
    98.     void SpawnImmediate() {
    99.         Transform t = GetPoolObject();
    100.         // if (t==null) return;
    101.         // Vector3 pos = Vector3.zero;
    102.         // pos.y = Random.Range(ySpawnRange.min, ySpawnRange.max);
    103.         // t.position = pos;
    104.         if (t == null) return;
    105.         Vector3 pos = Vector3.zero;
    106.         pos.y = Random.Range(ySpawnRange.min, ySpawnRange.max);
    107.         pos.x = (immediateSpawnPos.x * Camera.main.aspect) / targetAspect;
    108.         t.position = pos;
    109.         Spawn();
    110.     }
    111.  
    112.     void Shift() {
    113.         //loop through pool objects
    114.         //moving them
    115.         //discarding them as they go off screen
    116.         for (int i = 0; i < poolObjects.Length; i++) {
    117.             poolObjects[i].transform.position += -Vector3.right * shiftSpeed * Time.deltaTime;
    118.             CheckDisposeObject(poolObjects[i]);
    119.         }
    120.     }
    121.  
    122.     void CheckDisposeObject(PoolObject poolObject) {
    123.         //place objects off screen
    124.         if (poolObject.transform.position.x < (-defaultSpawnPos.x * Camera.main.aspect) / targetAspect) {
    125.             poolObject.Dispose();
    126.             poolObject.transform.position = Vector3.one * 1000;
    127.         }
    128.     }
    129.  
    130.     Transform GetPoolObject() {
    131.         //retrieving first available pool object
    132.         for (int i = 0; i < poolObjects.Length; i++) {
    133.             if (!poolObjects[i].inUse) {
    134.                 poolObjects[i].Use();
    135.                 return poolObjects[i].transform;
    136.             }
    137.         }
    138.         return null;
    139.     }
    140.  
    141. }
    Here is my method where I check whether it is "Score zone", where actually I want the coins to be spawned. Should I set it somewhere in that method? It is actually in "TapController .cs"

    Code (CSharp):
    1. void OnTriggerEnter2D(Collider2D col) {
    2.         if (col.gameObject.tag == "ScoreZone") {
    3.             OnPlayerScored();
    4.             scoreSound.Play();
    5.         }
    6.         if (col.gameObject.tag == "DeadZone") {
    7.             rigidBody.simulated = false;
    8.             OnPlayerDied();
    9.             dieSound.Play();
    10.         }
    11.     }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    Without looking at your code, one approach will be to find where the pipes are Instantiated, and every fourth set of pipes also instantiate a coin in the gap.

    If you're using physics, make the coins a trigger collider and use that to collect them.

    If you're not using physics, just check distance to coin and award it if you get close enough.
     
    kobrata_6 likes this.
  3. kobrata_6

    kobrata_6

    Joined:
    Jun 2, 2020
    Posts:
    4
    But how to find that gap? I used the two pipes as one prefab?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    Excellent! Put a blank GameObject in there where you want the coin to possibly spawn, and then you can use that GameObject to know where to spawn it.

    If you want it to appear in a range of positions, put TWO GameObjects and then pick a position randomly between them using
    Random.value
    (returns 0.0 to 1.0) and then use
    Vector3.Lerp()
    to generate a position between those two GameObjects'
    transform.position
     
    kobrata_6 likes this.
  5. kobrata_6

    kobrata_6

    Joined:
    Jun 2, 2020
    Posts:
    4
    Thanks! I made this code running in my Spawn method but the coins do not parallax and don't follow the pipes. Any suggestions?
    Code (CSharp):
    1. void Spawn() {
    2.         //moving pool objects into place
    3.         Transform t = GetPoolObject();
    4.         if (t == null) return;
    5.         Vector3 pos = Vector3.zero;
    6.         pos.y = Random.Range(ySpawnRange.min, ySpawnRange.max);
    7.         pos.x = (defaultSpawnPos.x * Camera.main.aspect) / targetAspect;
    8.         if (coinCounter == 4){
    9.  
    10.             GameObject coin = Instantiate(Coin) as GameObject;
    11.             Transform coinPos = coin.transform;
    12.             Vector3 pos2 = Vector3.zero;
    13.             pos2 = Vector3.Lerp(pos, pos, Random.value);
    14.             coinPos.position = pos2;
    15.             coinCounter = 0;
    16.         }
    17.         if (coinCounter < 4){
    18.             coinCounter++;
    19.         }
    20.         t.position = pos;
    21.     }
     
    Last edited: Jun 8, 2020
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    Can you parent them to the pipes?

    You can change this line 10 above:

    Code (csharp):
    1. GameObject coin = Instantiate<GameObject>(Coin, transformThatPipesAreOnOrParentedTo);
     
    kobrata_6 likes this.
  7. kobrata_6

    kobrata_6

    Joined:
    Jun 2, 2020
    Posts:
    4
    Thanks man, you are my hero!
     
    Kurt-Dekker likes this.