Search code examples
c#unity-game-engine2dgameobject

Unity3D async game object instantiation


I'm making my first project in Unity3D right now. This is a 2D game. This is some kind of a runner, but with possibility for player to go back on some distance. To achieve this functionality for the moment, i'm doing something like this:

  • Creating two screens with content(first to see at the start of the game, second to show it after player exceedes first screen)
  • When player goes on the next screen i'm calculating current screen position and size to create new one after it(so it's 2 from the start, and when player goes to the second one, third one is creating and so on)

When i was testing it on my PC, everything was fine, but for some reason, when next screen is creating it's causing my phone to lag for somewhat like a second, now how the code goes:

In Start() method of the script i'm initializing two scenes:

    Scene scene = new Scene ();
    scene.setSceneBounds (screenBounds);
    scene.createBackground (cameraOffsetOnStart, sceneSize);
    scene.createContent ();

    sceneNumber++;
    currentScenePosition = sceneSize * sceneNumber;
    Vector2 nextScenePosition = new Vector2 (cameraOffsetOnStart.x + currentScenePosition.x, cameraOffsetOnStart.y);

    Scene scene2 = new Scene ();
    screenBounds.min = new Vector2(min.x + currentScenePosition.x, min.y);
    screenBounds.max = new Vector2(max.x + currentScenePosition.x, max.y);
    scene2.setSceneBounds (screenBounds);
    scene2.createBackground (nextScenePosition, sceneSize);
    scene2.createContent ();

And then in Update() i'm checking if player exceedes current scene and creating new one:

void Update () {
    if (player.transform.position.x - playerOffset > sceneNumber * (max.x - min.x)) {
        Debug.Log("current scene is : " + (++sceneNumber));
        currentScenePosition = sceneSize * sceneNumber;
        Vector2 nextScenePosition = new Vector2 (cameraOffsetOnStart.x + currentScenePosition.x, cameraOffsetOnStart.y);
        Scene scene = new Scene();
        screenBounds.min = new Vector2(min.x + currentScenePosition.x, min.y);
        screenBounds.max = new Vector2(max.x + currentScenePosition.x, max.y);
        scene.setSceneBounds (screenBounds);
        scene.createBackground(nextScenePosition, sceneSize);
        scene.createWebs();
        sceneManager.Scenes.Add(scene);
    }
}

And the code for creating content:

public void createBackground(Vector2 position, Vector2 size) {
    background = new Background (position, size);
}

public void createContent() {
    Vector2[] positions = Utilities.generateRandomPositions(5, sceneBounds, 4f);

    for (int i = 0; i < positions.Length; i++) {
        Web web = ScriptableObject.CreateInstance<Web>();
        web.init(positions[i]);
    }
}

The problem of lagging comes from createContent method. Code for init :

    public void init(Vector2 position) {
        if (position != Vector2.zero) {
            obj = Instantiate (Resources.Load ("Textures/web", typeof(GameObject)), position, Quaternion.identity) as GameObject;
        }
    }

It's obvious that Instantiate method, calling 5 times in a row for 5 object is causing this behviour.

More details on "Textures/web" if needed: This is a prefab with circle collider and rigidbody, which set to be kinematic

Questions: Why it's lagging on only 5 items? Am i using Instantiate in a wrong way? How can i make it faster? Is there a way to call it async?


Solution

  • As discussed in comments.

    In line:

    obj = Instantiate (Resources.Load ("Textures/web", typeof(GameObject)), position, Quaternion.identity) as GameObject;
    

    You loading resources from devices memory each time you call this code. Just store GameObject in some variable e.g in Start() method.