KeTa16
KeTa16

Reputation: 435

Endless Runner Infinite track generation - Unity3D C#

I am new to unity and I am creating my first ever endless runner game. I currently have a cube as a player and another cube (prefab) as the track. I have created a script which aims at instantiating the prefab at runtime and moving the track towards the player (instead of moving the player). For some reason, the tracks instantiated at runtime are being generated at the same position and don't seem to move towards the player. Could anyone tell me if I am doing it right please? How do I generate an infinite/endless track? Thanks in advance

public GameObject[] trackPieces;
public float trackLength;
public float trackSpeed;

private GameObject trackObject;

// Update is called once per frame
void Update ()
{
    GenerateInfiniteTrack();
}

private void GenerateInfiniteTrack()
{
        trackObject = InstantiatePrefab();
        trackObject.transform.Translate(-Vector3.forward * Time.deltaTime * trackSpeed);
}

private GameObject InstantiatePrefab()
{
    return Instantiate(trackPieces[Random.Range(0, trackPieces.Length)]) as GameObject;
}

Upvotes: 2

Views: 1700

Answers (1)

Tyler S. Loeper
Tyler S. Loeper

Reputation: 836

trackObject is overwritten every frame

Your track is not moving because the call to move it occurs only once at instantiation and never again. The value of which track to move is overwritten every update(). Here is what happens:

Every update you make a call to:

private void GenerateInfiniteTrack()

When this method is called you instantiate a new prefab (new instance of your object) and tell the object to move via

trackObject.transform.Translate(-Vector3.forward * Time.deltaTime * trackSpeed);

When you call the method the next time you lose the reference to the original object because you are creating another one that replaces the value held in trackObject. So the previously generated object will never move again. Your new object moves once and then is lost, again, and repeat.

Below I have suggested some code that may work. You will still have to decide how you will dispose of the track objects since you are creating them at a very fast rate. If you can think of a way to use InvokeRepeating() to address this problem, then that would be the cleanest. Invoke repeating has some limitations, like not being able to pass parameters to your repeating function so I did not use it here, but it is conceivably an alternative.

Here is my example.

var TrackObjects = new List<GameObject>();

private void MoveInfiniteTrack() 
{
    foreach(GameObject gO in TrackObjects )
    {
         gO.transform.Translate(-Vector3.forward * Time.deltaTime * trackSpeed); 
    }
}

private void GenerateInfiniteTrack()
{
        TrackObject = InstantiatePrefab();
        TrackObjects.Add(TrackObject);
}

void Update ()
{
    GenerateInfiniteTrack();
    MoveInfiniteTrack() 
}

void Foo()
{
    // Delete your track on some kind schedule or you will quickly get infinite objects and massive lag.
}

As a general observation, creating track this much (60x a second) is very inefficient. I would suggest that you either:

A. Create much larger segments of track, for example once every 1 or 10 seconds and move it along. I don't remember exactly how to do this, but it went something like this:

var lastchecked= datetime.now 

Update()
{
    if((datetime.now - lastchecked).seconds > 1)
    {
        // put here what you will do every 1 second.
        lastchecked= datetime.now 
    }
}

B. Create a large cylinder and rotate it to use as a track.

Upvotes: 1

Related Questions