1

First of all, since I've found much great help from other posts I found here, I considered signing up, so this is my first post I suppose!

Regardless, I am currently working on a Unity3D game in C#, where we essentially have an endless driving game where a player controllable car can be moved between three lanes while avoiding enemies and obstacles on the road.

To give the illusion of the car driving on an endless road, I made a little section of a road into a prefab, and using my script, say every x seconds one of these modules/sections is being instantiated. The sections have another script on them that moves their position forward every frame, based on the speed I set up, which move below the stationary car, which looks like the car is driving on the road. By precisely tuning the timing and speed of these road-sections, they spawn one after another outside of the screen, and essentially look like one single, infnite road. The road-sections then get deleted behind the player, where they cannot be seen anymore to save ressources.

This concept worked great initially, and as the gametime moved on, the road would move faster below the player, and the game would get more difficult.

As I implemented more game mechanics, I've noticed little gaps that sometimes occur between these instantiated road sections, as if one was instantiated a little bit to late. A Quick look at the profiler shows that overall performance drops when a section is instantiated, and sometimes these gaps would appear.

I instantiate my road sections by using "InvokeRepeating("spawnModule", 0f, spawnDelay);", and since InvokeRepeating essentially repeats said method every x seconds, it should always spawn my road sections in the way that they do not create gaps becaus one instantiated later than the other. This issue does not occur on systems with higher processing power since Instantiate() does not cause much of a performance issue there.

Anyways, I hope my concept is clear, and just for reference, if anyone can follow what I am doing, I have the scripts that move each module each frame, and that control the timing of the instantiating method (keep in mind that some variables are not declared in English, as it isn't my main language:

Module Spawner Script:

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

public class ModulSpawn : MonoBehaviour {

    public GameObject ModulPrefab;
    public GameObject ModulSpawnPoint;
    public Vector3 SpawnDrehung;
    public float BewGeschwindigkeit;
    public float spawnDelay;
    [SerializeField] float gameTime;
    float delayDifference;
    public int Stufe;
    public float[] speedListe;
    public float[] delayListe;
    public float[] timerListe;
    public bool switcherActive = true;
    public bool updateInvoke = false;


    // Use this for initialization
    void Start() {
        Stufe = 0;
        //Instantiate(ModulPrefab, ModulSpawnPoint.transform.position, Quaternion.Euler(SpawnDrehung));
        InvokeRepeating("spawnModule", 0f, spawnDelay);
        //delayDifference = spawnDelay;
    }

    // Update is called once per frame
    void FixedUpdate() {
        //gameTime = Time.time;
        /*
        if (gameTime >= delayDifference) {
            //Debug.Log(delayDifference);
            Instantiate(ModulPrefab, ModulSpawnPoint.transform.position, Quaternion.Euler(SpawnDrehung));
            if (switcherActive == true) stufenSwitcher();
            delayDifference += spawnDelay;
            Debug.Log("Now");
        } */
        //Debug.Log(gameTime);


    }

    void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("Modul")) {
            Destroy(other.gameObject);
        }
    }

    void spawnModule() {
        Instantiate(ModulPrefab, ModulSpawnPoint.transform.position, Quaternion.Euler(SpawnDrehung));
        gameTime = Time.time;

        if (Time.time >= timerListe[Stufe] && delayListe[Stufe] != 0 && switcherActive == true)
        {
            spawnDelay = delayListe[Stufe];
            CancelInvoke("spawnModule");
            InvokeRepeating("spawnModule", 0f, spawnDelay);
            BewGeschwindigkeit = speedListe[Stufe];
            Stufe++;
            //if (Stufe > timerListe.Length) switcherActive = false;
        }

        if (updateInvoke == true) {
            updateInvoke = false;
            CancelInvoke("spawnModule");
            InvokeRepeating("spawnModule", 0f, spawnDelay);
        }
    }

}

Module Mover Script:

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

public class ModulMove : MonoBehaviour {

    public bool Xpos;
    public bool Xneg;
    public bool Ypos;
    public bool Yneg;
    public bool Zpos;
    public bool Zneg = true;
    Vector3 BewRichtung = new Vector3(0f, 0f, -1f);
    public float BewGeschwindigkeit;
    public ModulSpawn modulSpawnScript;
    Rigidbody rb;


    // Use this for initialization
    void Start () {
        rb = GetComponent<Rigidbody>();
        RichtungsCheckbox();
        modulSpawnScript = GameObject.Find("ModulSpawner").GetComponent<ModulSpawn>();


    }

    void Update () {
        BewGeschwindigkeit = modulSpawnScript.BewGeschwindigkeit;
        gameObject.transform.Translate(BewRichtung * BewGeschwindigkeit * Time.deltaTime * 50);
        //Debug.Log(Time.deltaTime);
        //+= BewRichtung * (BewGeschwindigkeit * Time.deltaTime);
        //rb.velocity = new Vector3(0f, 0f, -5f);

    }

    void RichtungsCheckbox()
    {

        if (Xpos == true)
        {
            BewRichtung = new Vector3(1, 0, 0);
        }
        if (Xneg == true)
        {
            BewRichtung = new Vector3(-1, 0, 0);
        }
        if (Ypos == true)
        {
            BewRichtung = new Vector3(0, 1, 0);
        }
        if (Yneg == true)
        {
            BewRichtung = new Vector3(0, -1, 0);
        }
        if (Zpos == true)
        {
            BewRichtung = new Vector3(0, 0, 1);
        }
        if (Zneg == true)
        {
            BewRichtung = new Vector3(0, 0, -1);
        }
    }
}

I'd be really glad if I could find some suggestions for alternatives. I was thinking of perhaps instantiating between when the sections should appear to avoid lags during when one section actually has to appear precisely.

What do you think?

ZetShock
  • 11
  • 1
  • Well, for one thing you could do... `timerListe[Stufe] && delayListe[Stufe]` you should make a custom class to hold this information and use a single list. – Draco18s no longer trusts SE Jan 29 '18 at 23:19
  • have you tried using coroutines rather? https://forum.unity.com/threads/invokerepeating-vs-coroutines-performance.497208/ – Wreigh Jan 29 '18 at 23:26
  • All the above aside, you really should use object pooling, its a lot more efficient to disable and recycle unused objects rather then repeatedly spawning and despawning them -> https://unity3d.com/de/learn/tutorials/topics/scripting/object-pooling – yes Jan 30 '18 at 09:05
  • So I have looked into object pooling and I will watch the unity training video for it. Essentially it seems to make a lot of sense why this has such an impact in my game, since every new street "module" when instantiated is looking for script and object references, which takes time and performance, and sometimes this might even cause enough of a spawning delay to cause the modules to be instantiated too late, causing a gap. Ill post back when I managed to solve the issue with object pooling, thanks! – ZetShock Feb 14 '18 at 22:57

0 Answers0