0
votes

I have this game that I've been working on. Last night I've built it and uploaded it up on Google Play. I then took my android phone, went on the Play store to download my game and as it starts, it runs horribly. The game moves incredibly fast and laggy, almost as if I set the camera speed to an insanely high number. It is completely unplayable. This would be the main menu of the game, without the UI elements on it: https://youtu.be/Hxih--U8q9g

A little background on the scene:

All these buildings and props are instantiated on runtime in the Update function as the player progresses through the level, but they're also destroyed once the player passes them. All of them are prefabs and all of them use their own individual materials with individual textures. The actual game level the player would play is exactly the same as the main menu, only it has the player in it. My questions is, could this be only because of bad optimization for mobile?

I've already set the quality settings to the lowest inside Unity, and also downsize all textures from the 4K resolution that they were to 128x128 - 512x512 (depending on the asset). Even with those optimizations the game runs as poorly as before.

I'm going to change the way I'm instantiating the objects and I'll use object pooling instead. I'll also use a texture atlas instead of all these different textures and materials.

This is the way I'm instantiating the prefabs at the moment:

    void Update()
    {
        if (player.transform.position.z >= spawn.transform.position.z)
        {
            center = transform.position;
            for (int i = 0; i < Random.Range(obstacleDifficulty.x, obstacleDifficulty.y); i++)
            {
                StartCoroutine(Delay());
            }
            Vector3 newPos = transform.position;
            newPos.z += moveSpawner;
            transform.position = newPos;
        }
    }

    public void SpawnObstacles()
    {
        Vector3 pos = center + new Vector3(Random.Range(-size.x / 2, size.x / 2), 0, Random.Range(-size.z / 2, size.z / 2));
        int n = Random.Range(0, obstacles.Length);
        GameObject theObstacle = obstacles[n];
        Instantiate(theObstacle, pos, rotation);
    }

    IEnumerator Delay()
    {
        yield return new WaitForSeconds(0.05f);
        SpawnObstacles();
    }

I want to fix this problem so the game runs perfectly smooth. I wonder if doing the things I described above, using pooling and atlases, will be enough to fix this.

EDIT: This is my camera controller script:

using UnityEngine;
using System.Collections;

public class CameraController : MonoBehaviour
{

    public GameObject player;
    public float cameraHeight;

    private Vector3 offset;

    void Start ()
    {
        offset = transform.position - player.transform.position;
    }

    void LateUpdate ()
    {
        transform.position = player.transform.position + offset;
        transform.position = new Vector3(0, cameraHeight, transform.position.z);
    }
}

I've seen something about using Time.deltaTime on Unity's official tutorials, but I thought I should use that on my player's movement, and multiplying my player's speed value with Time.deltaTime didn't give me the result I wanted. This is my player's movement:

rb.velocity = new Vector3(xVelocity * Input.acceleration.x * 1.75f, 0, speed);

Last night I also disabled all image effects on my camera and that removed around 25 batches from my scene, I had no idea those would be so expensive. I got my scene to around 15 batches as it was around 55-70 before, and I'm yet to test it on my mobile to see how it moves.

2
1) have you tried profiling in unity 3d? it may be very helpful. 2) why do you want to Instantiate objects in Update? why not instantiate all of them in the beginning (Start) and leave Update empty since it's invoked once per frame?Alex Sikilinda
@AlexSikilinda The reason I want to instantiate them at running is because I use this to instantiate the prefabs that together form the level my player is playing on, and I don't know how far he'll get in that round. I used the profiler inside Unity, but nothing looked odd to me, other than some things that I understand only happen inside the editor, so I shouldn't worry about those.Radu Mitroi
have you tried to instantiate the whole level completely? it may be faster than checking it each time in Update? Or you can instantiate a big part of the level instead of instantiating separate obstacles.Alex Sikilinda
you can also profile on device (see the Unity documentation) and you will see what takes most timeAlex Sikilinda
Avoid instantiating at runtime as much as you possibly can. Object pooling will likely increase your performance by a lot, especially in 3D on a mobile device.TheBatman

2 Answers

1
votes

I've just made a test scene. It's the same as the actual game level, but in this one I disabled everything that was instantiating, instead I just made a small part of the level by manually placing the prefabs. I also put the exact same material on all of my objects, a standard blue material. So there's no objects spawning at runtime and no textures, and my build still runs laggy on my android device. It's not as laggy as before, it is playable ever since I disabled the post process effects (except for fog), but the game still doesn't run smoothly.

What else can I possibly do to make it run smooth?

This is my profiler while I play the game on the same android device, but in the Editor using Unity Remote. Profiler screenshot

0
votes

You need to check your profiler, then you will see if there is a need to optimize the game or not and check for batches. And using Time.deltatime is just like if you want to make you game independent of device type, so even on a slow device you will get a speed of 10(lets assume you set the speed as 10) and on a faster high end device you will still get the speed of 10. If you won't use Time.deltatime you will be getting a higher number of frames in a high end devices and the speed will go so high because you will be moving your player really quick due to a high frame rate, and slow movement in a low end device.