I have these scripts I made that work absolutely perfectly as I need them to. Is there any improvements that can be done to these scripts and make them more efficient for Mobile Platforms? Or even just combine them into one script?These 4 scripts are just about identical except that each one controls a different obstacle and I have it that way so I can have more control over each individual obstacle. Does that make sense? (For instance, I want one obstacle to start spawning 10 seconds into the game and another to spawn RIGHT when the game starts).Obstacle 1:using UnityEngine;using System.Collections;[System.Serializable] // Serialize this so it looks neater in the inspector public class Obstacle1 // Hammer Obstacle {    public GameObject hammer; // The first obstacle gameobject. This is attached in the inspector.    public Vector3 spawnHPosValues; // Where the first obstacle will be spawned at on the X,Y,Z plane.     public int hCount; // This is the count of the first obstacle in a given wave. //    public float hSpawnWait; // Time in seconds between next wave of obstacle 1.    public float hStartGameWait; // Time in seconds between when the game starts and when the first obstacle start spawning.    public float hWaveSpawnWait; // Time in seconds between waves when the next wave of obstacle 1 will spawn.}public class SpawnHammers : MonoBehaviour {    public Obstacle1 obstacle1; // Reference to the Obstacle 1 class //    void Start () {        StartCoroutine (SpawnHammer ()); // at the beginning of the game, start to function SpawnHammer() //}    IEnumerator SpawnHammer () {        yield return new WaitForSeconds(obstacle1.hStartGameWait);        while (true)        {            for (int i = 0; i < obstacle1.hCount; i++) {                Vector3 spawnPosition = new Vector3 (Random.Range(-obstacle1.spawnHPosValues.x, obstacle1.spawnHPosValues.x),                                                      obstacle1.spawnHPosValues.y,                                                      obstacle1.spawnHPosValues.z); // I choose where I spawn the obstacles on the X,Y,Z planes. Only the X                                                                                   // plane will be random                Quaternion spawnRotation = Quaternion.identity; // Spawn with NO rotation                Instantiate (obstacle1.hammer, spawnPosition, spawnRotation); // Bring the object into the scene                yield return new WaitForSeconds(obstacle1.hSpawnWait); // Spawn a new obstacle            }            yield return new WaitForSeconds (obstacle1.hWaveSpawnWait); // Start the new wave of obstacles        }    }}Obstacle 2:using UnityEngine;using System.Collections;[System.Serializable] public class Obstacle2 // Road Barrier Obstacle {    public GameObject roadBarrier; // The second obstacle gameobject. This is attached in the inspector.    public Vector3 spawnRBPosValues; // Where the second obstacle will be spawned at on the X,Y,Z plane.     public int rbCount; // This is the count of the second obstacle in a given wave. //    public float rbSpawnWait; // Time in seconds between next wave of obstacle 2.    public float rbStartGameWait; // Time in seconds between when the game starts and when the second obstacle will start spawning.    public float rbWaveSpawnWait; // Time in seconds between waves when the next wave of obstacle 2 will spawn.}public class SpawnRoadBarriers : MonoBehaviour {    public Obstacle2 obstacle2;    void Start () {        StartCoroutine (SpawnRoadBarrier ());    }    IEnumerator SpawnRoadBarrier () {        yield return new WaitForSeconds(obstacle2.rbStartGameWait);        while (true)        {            for (int i = 0; i < obstacle2.rbCount; i++) {                Vector3 spawnPosition = new Vector3 (Random.Range(-obstacle2.spawnRBPosValues.x, obstacle2.spawnRBPosValues.x),                                                      obstacle2.spawnRBPosValues.y,                                                      obstacle2.spawnRBPosValues.z);                 Quaternion spawnRotation = Quaternion.identity;                 Instantiate (obstacle2.roadBarrier, spawnPosition, spawnRotation);                yield return new WaitForSeconds(obstacle2.rbSpawnWait);            }            yield return new WaitForSeconds (obstacle2.rbWaveSpawnWait);        }    }}Obstacle 3:using UnityEngine;using System.Collections;[System.Serializable]public class Obstacle3 // Cone Obstacle{    public GameObject cone; // The third obstacle gameobject. This is attached in the inspector.    public Vector3 spawnCPosValues; // Where the third obstacle will be spawned at on the X,Y,Z plane.     public int cCount; // This is the count of the third obstacle in a given wave.    public float cSpawnWait; // Time in seconds between next wave of obstacle 3.    public float cStartGameWait; // Time in seconds between when the game starts and when the third obstacle start spawning.    public float cWaveSpawnWait; // Time in seconds between waves when the next wave of obstacle 3 will spawn.}public class SpawnCones : MonoBehaviour {    public Obstacle3 obstacle3;    void Start () {        StartCoroutine (SpawnCone ());    }    IEnumerator SpawnCone () {        yield return new WaitForSeconds(obstacle3.cStartGameWait);        while (true)        {            for (int i = 0; i < obstacle3.cCount; i++) {                Vector3 spawnPosition = new Vector3 (Random.Range(-obstacle3.spawnCPosValues.x, obstacle3.spawnCPosValues.x),                                                      obstacle3.spawnCPosValues.y,                                                      obstacle3.spawnCPosValues.z);                Quaternion spawnRotation = Quaternion.Euler(0f,0f,90f); // rotate 90 degrees on the Z axis                   Instantiate (obstacle3.cone, spawnPosition, spawnRotation);                yield return new WaitForSeconds(obstacle3.cSpawnWait);            }            yield return new WaitForSeconds (obstacle3.cWaveSpawnWait);        }    } }Obstacle 4:using UnityEngine;using System.Collections;[System.Serializable]public class Obstacle4 // Barrel Obstacle{    public GameObject barrel; // The fourth obstacle gameobject. This is attached in the inspector.    public Vector3 spawnBPosValues; // Where the fourth obstacle will be spawned at on the X,Y,Z plane.     public int bCount; // This is the count of the fourth obstacle in a given wave.    public float bSpawnWait; // Time in seconds between next wave of obstacle 4.    public float bStartGameWait; // Time in seconds between when the game starts and when the fourth obstacle start spawning.    public float bWaveSpawnWait; // Time in seconds between waves when the next wave of obstacle 4 will spawn.}public class SpawnBarrels : MonoBehaviour {    public Obstacle4 obstacle4;    void Start () {        StartCoroutine (SpawnBarrel ());    }    IEnumerator SpawnBarrel () {        yield return new WaitForSeconds(obstacle4.bStartGameWait);        while (true)        {            for (int i = 0; i < obstacle4.bCount; i++) {                Vector3 spawnPosition = new Vector3 (Random.Range(-obstacle4.spawnBPosValues.x, obstacle4.spawnBPosValues.x),                                                      obstacle4.spawnBPosValues.y,                                                      obstacle4.spawnBPosValues.z);                Quaternion spawnRotation = Quaternion.Euler(0f,0f,90f); // rotate 90 degrees on the Z axis                   Instantiate (obstacle4.barrel, spawnPosition, spawnRotation);                yield return new WaitForSeconds(obstacle4.bSpawnWait);            }            yield return new WaitForSeconds (obstacle4.bWaveSpawnWait);        }    } }
Obstacle-spawning and movement scripts
c#;performance;beginner;comparative review;unity3d
Bracket alignment. For some reason, all obstacle classes and while-loops are written with vertically aligned bracket, while the MonoBehaviours are egyptians.[Coding style] create a consistent look to the code, so that readers can focus on content, not layout. - C# Coding ConventionAnd, the commonly agreed convention for this one is vertically aligned, Naming. Do not abbreviate the variable name... Go for the full name, with exception of some short lambda functions', event handlers' parameters and for-loops' variables.At first, I thought they were some kind of hungarian notation, and had trouble figuring out what kind of handles are they? It was until I saw the next obstacle class that I realize it was h for Hammer!public class Obstacle1 // Hammer Obstacle{    public GameObject hammer; // The first obstacle gameobject. This is attached in the inspector.    public Vector3 spawnHPosValues; // Where the first obstacle will be spawned at on the X,Y,Z plane.    public int hCount; // This is the count of the first obstacle in a given wave. //    public float hSpawnWait; // Time in seconds between next wave of obstacle 1.    public float hStartGameWait; // Time in seconds between when the game starts and when the first obstacle start spawning.    public float hWaveSpawnWait; // Time in seconds between waves when the next wave of obstacle 1 will spawn.}So, do use the full name, like spawnHammerPosition, hammerCount and so on... It does irk a bit, but I will refactor this with other Obstacles later.In this bit of codevar spawnRotation = Quaternion.identity; // Spawn with NO rotationInstantiate(hammer.GameObject, spawnPosition, spawnRotation); // Bring the object into the sceneInstead of spawnRotation, you could have gone with noRotation and gotten rid of the comment.var noRotation = Quaternion.identity;Instantiate(hammer.GameObject, spawnPosition, noRotation); // Bring the object into the sceneOr, if you are proficient enough, just inline it.Normally, you should use PascalCase for public menbers, and not camelCase. However, Unity3D seems favor the latter. Therefore, it is up to you to decide. (Quaternion.identity *twiches eye*)When your method name is already SpawnObstacles, you don't also have to name the local variable spawnPosition, just position should suffice.Class name should never be plurial, and never a verb or verb+complement.This distinguishes type names from methods, which are named with verb phrases. - Names of Classes, Structs, and InterfacesSpawnHammers -> HammerSpawnerI don't understand, why you have 4 different classes with the same properties and copy-pasta comments, and, most importantly, shareing the same role of obstacle.Combine them into a single class, subclass if you had to keep the class name for distinction :[Serializable]public abstract class Obstacle{    public GameObject gameObject;    public Vector3 spawnPosition;    public int spawnCount;    public float spawnWait;    public float startGameWait;    public float waveSpawnWait;}public class Hammer : Obstacle { }public class RoadBarrier : Obstacle { }public class Cone : Obstacle { }public class Barrel : Obstacle { }Try keep the line width not too long and don't align the parameters :// compare these two :Vector3 spawnPosition = new Vector3(Random.Range(-cone.spawnCPosValues.x, cone.spawnCPosValues.x),                                    cone.spawnCPosValues.y,                                    cone.spawnCPosValues.z);Vector3 spawnPosition = new Vector3(    Random.Range(-cone.spawnCPosValues.x, cone.spawnCPosValues.x),    cone.spawnCPosValues.y,    cone.spawnCPosValues.z);As you have already noticed, all 4 spawners' implementation are quite repetitive, namely the waiting part. However, each obstacle has its own spawn rotation and position. So, we will have to extract the former while isolating the latter : public abstract class ObstacleSpawnerBase : MonoBehaviour{    public Obstacle obstacle;    void Start()    {        StartCoroutine(SpawnObstacles());    }    // the repeated pattern in SpawnXXXXs has been extracted to here    IEnumerator SpawnObstacles()    {        yield return new WaitForSeconds(obstacle.startGameWait);        while (true)        {            foreach (var obstacle in SpawnObstaclesImpl())                yield return new WaitForSeconds(obstacle.spawnWait);            yield return new WaitForSeconds(obstacle.waveSpawnWait);        }    }    // with the actual implementation detail separated for customization    protected abstract IEnumerable<WaitForSeconds> SpawnObstaclesImpl();}And the concrete obstacle spawner classes : public class HammerSpawner : ObstacleSpawnerBase{    protected override IEnumerable SpawnObstaclesImpl()    {        for (int i = 0; i < obstacle.spawnCount; i++)        {            // randomize x-axis            var position = new Vector3(                Random.Range(-obstacle.spawnPosition.x, obstacle.spawnPosition.x),                obstacle.spawnPosition.y,                obstacle.spawnPosition.z);            // bring the object into the scene            yield return Instantiate(obstacle.gameObject, position, Quaternion.identity);        }    }}public class RoadBarrierSpawner : ObstacleSpawnerBase{    protected override IEnumerable SpawnObstaclesImpl()    {        for (int i = 0; i < obstacle.spawnCount; i++)        {            var position = new Vector3(                Random.Range(-obstacle.spawnPosition.x, obstacle.spawnPosition.x),                obstacle.spawnPosition.y,                obstacle.spawnPosition.z);            yield return Instantiate(obstacle.gameObject, position, Quaternion.identity);        }    }}public class ConeSpawner : ObstacleSpawnerBase{    protected override IEnumerable SpawnObstaclesImpl()    {        for (int i = 0; i < obstacle.spawnCount; i++)        {            var position = new Vector3(                Random.Range(-obstacle.spawnPosition.x, obstacle.spawnPosition.x),                obstacle.spawnPosition.y,                obstacle.spawnPosition.z);            // rotate 90 degrees on the Z axis             var rotation = Quaternion.Euler(0f, 0f, 90f);            yield return Instantiate(obstacle.gameObject, position, rotation);        }    }}public class BarrelSpawner : ObstacleSpawnerBase{    protected override IEnumerable SpawnObstaclesImpl()    {        for (int i = 0; i < obstacle.spawnCount; i++)        {            var position = new Vector3(                Random.Range(-obstacle.spawnPosition.x, obstacle.spawnPosition.x),                obstacle.spawnPosition.y,                obstacle.spawnPosition.z);            // rotate 90 degrees on the Z axis             var rotation = Quaternion.Euler(0f, 0f, 90f);            yield return Instantiate(obstacle.gameObject, position, rotation);        }    }}Normally, I would use generic here, but Unity3D seems to have some problems with generic MonoBehaviour, so I left it out. However, do give them a try : public abstract class ObstacleSpawnerBase<TObstacle> : MonoBehaviour    where TObstacle : Obstacle{    // ...}public class HammerSpawner : ObstacleSpawnerBase<Hammer> { /*...*/ }public class RoadBarrierSpawner : ObstacleSpawnerBase<RoadBarrier> { /*...*/ }public class ConeSpawner : ObstacleSpawnerBase<Cone> { /*...*/ }public class BarrelSpawner : ObstacleSpawnerBase<Barrel> { /*...*/ }