Flappy Bird Pipe Spawning Issue

I’m following GMTK Unity for beginners Flappy Bird tutorial and I’m at the part where you get pipes to spawn at random y levels I put in all the code but there still only spawning at the same y level, any help would be appreciated, thanks

PipeSpawnScript code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PipeSpawnScript : MonoBehaviour
{
    public GameObject pipe;
    public float spawnRate = 2;
    private float timer = 0;
    public float heightOffset = 10;

    // Start is called before the first frame update
    void Start()
    {
        spawnPipe();
    }

    // Update is called once per frame
    void Update()
    {
        if (timer < spawnRate)
        {
            timer = timer + Time.deltaTime;
        }f
        else
        {
            spawnPipe();
            timer = 0;
        }
    }

    void spawnPipe()
    {
        float lowestPoint = transform.position.y - heightOffset;
        float heightestPoint = transform.position.y + heightOffset;

        Instantiate(pipe, new Vector3(transform.position.x, Random.Range(lowestPoint, heightestPoint), 0), transform.rotation);
    }
}

What is heightOffset set to in the Inspector?

Firstly, make your code be like a code, for example:

void Start()
{

}

Secondly, use coroutines to manage the spawn rate of the pipes more efficiently.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PipeSpawnScript : MonoBehaviour
{
public GameObject pipe;
public float spawnRate = 2;
public float heightOffset = 10;
// Start is called before the first frame update
void Start()
{
  StartCoroutine(managePipes());
}

void spawnPipe()
{
  float lowestPoint = transform.position.y - heightOffset;
  float heightestPoint = transform.position.y + heightOffset;

  Instantiate(pipe, new Vector3(transform.position.x,
  Random.Range(lowestPoint, heightestPoint), 0),
  transform.rotation);
}

private IEnumerator managePipes()
{
  while (true)
  {
   spawnPipe();
   yield return new WaitForSeconds(spawnRate);
  }
}

Not sure where I can find that, this is all thats under PipeSpawner in the inspector

9864270--1421301--Screenshot 2024-05-30 190416.png

I’m following a tutorial and I’m worried if I completely change the code it might break something later on

@Proudani 's suggestion is great, but for right now, just hang tight and yes, definitely follow the tutorial correctly.

Most likely you have typos.

EDIT: you have an obvious typo on line 24. Go fix it.

Read the console. Refer to the tutorial. Typing must be 100% perfect, including capitalization, punctuation, spelling, everything. If unsure, hit google. You’re NEVER the first person to commit a typo and get an error.

Once you fix it, yes, that’s where the value will be for heightOffset. Make sure it is NOT zero. NOTE: it does not matter what you put in code, and here is why:

Serialized / public fields in Unity are initialized as a cascade of possible values, each subsequent value (if present) overwriting the previous value:

  • what the class constructor makes (either default(T) or else field initializers, eg “what’s in your code”)

  • what may be saved with the prefab

  • what may be saved with the prefab override(s)/variant(s)

  • what may be saved in the scene and not applied to the prefab

  • what may be changed in the scene and not yet saved to disk

  • what may be changed in OnEnable(), Awake(), Start(), or even later

Make sure you only initialize things at ONE of the above levels, or if necessary, at levels that you specifically understand in your use case. Otherwise errors will seem very mysterious.

Here’s the official discussion: https://blog.unity.com/technology/serialization-in-unity

If you must initialize fields, then do so in the void Reset() method, which ONLY runs in the UnityEditor.

Field initializers versus using Reset() function and Unity serialization:

https://discussions.unity.com/t/829681/2

https://discussions.unity.com/t/846251/8

To avoid complexity in your prefabs / scenes, I recommend NEVER using the FormerlySerializedAsAttribute

I think I found the mistake, where is the script connected to? Is it a GameObject, an empty, or a pipe?

Because on the line 22, If the x is not on the center of your game, the pipe might be spawning, but somewhere else.