Learn how to setup and code the iconic Asteroids shooter arcade gameplay originally designed by Lyle Rains & Ed Logg and released by Atari in 1979.

····················································································

Subscribe to Oxmond Tutorials
https://bit.ly/SubscribeOxmondTutorials

Try the game here:
https://oxmond.com/games/asteroids/

● Download the free star skybox here (Real Stars Skybox):
https://assetstore.unity.com/packages/3d/environments/sci-fi/real-stars-skybox-116333?aid=1100l4p9k

● Download Yughues Free Rocks here: https://assetstore.unity.com/packages/3d/environments/yughues-free-rocks-13568?aid=1100l4p9k

● Download the Rocket mesh here: https://assetstore.unity.com/packages/3d/vehicles/space/atom-rocket-model-140021?aid=1100l4p9k

● Other free Asset Packages at the Unity Assets Store:
https://assetstore.unity.com/lists/top-free-packages-13201?aid=1100l4p9k

Asteroid.cs

/*

   .-------.                             .--.    .-------.     .--.            .--.     .--.        
   |       |--.--.--------.-----.-----.--|  |    |_     _|--.--|  |_.-----.----|__|---.-|  |-----.
   |   -   |_   _|        |  _  |     |  _  |      |   | |  |  |   _|  _  |   _|  |  _  |  |__ --|
   |_______|__.__|__|__|__|_____|__|__|_____|      |___| |_____|____|_____|__| |__|___._|__|_____|
   © OXMOND / www.oxmond.com 

*/

using UnityEngine;

public class Asteroid : MonoBehaviour
{

    public GameObject rock;
    public Gameplay gameplay;
    private float maxRotation;
    private float rotationX;
    private float rotationY;
    private float rotationZ;
    private Rigidbody rb;
    private Camera mainCam;
    private float maxSpeed;
    private int _generation;

    void Start()
    {

        mainCam = Camera.main;

        maxRotation = 25f;
        rotationX = Random.Range(-maxRotation, maxRotation);
        rotationY = Random.Range(-maxRotation, maxRotation);
        rotationZ = Random.Range(-maxRotation, maxRotation);

        rb = rock.GetComponent();

        float speedX = Random.Range(200f, 800f);
        int selectorX = Random.Range(0, 2);
        float dirX = 0;
        if (selectorX == 1) { dirX = -1; }
        else { dirX = 1; }
        float finalSpeedX = speedX * dirX;
        rb.AddForce(transform.right * finalSpeedX);

        float speedY = Random.Range(200f, 800f);
        int selectorY = Random.Range(0, 2);
        float dirY = 0;
        if (selectorY == 1) { dirY = -1; }
        else { dirY = 1; }
        float finalSpeedY = speedY * dirY;
        rb.AddForce(transform.up * finalSpeedY);

    }

    public void SetGeneration(int generation)
    {
        _generation = generation;
    }

    void Update()
    {
        rock.transform.Rotate(new Vector3(rotationX, rotationY, 0) * Time.deltaTime);
        CheckPosition();
        float dynamicMaxSpeed = 3f;
        rb.velocity = new Vector2(Mathf.Clamp(rb.velocity.x, -dynamicMaxSpeed, dynamicMaxSpeed), Mathf.Clamp(rb.velocity.y, -dynamicMaxSpeed, dynamicMaxSpeed));
    }

    void OnCollisionEnter(Collision collisionInfo)
    {
        if (collisionInfo.collider.name == "Bullet(Clone)")
        {
            if (_generation < 3)
            {
                CreateSmallAsteriods(2);
            }
            Destroy();
        }

        if (collisionInfo.collider.name == "Rocket")
        {
            gameplay.RocketFail();
        }
    }

    void CreateSmallAsteriods(int asteroidsNum)
    {
        int newGeneration = _generation + 1;
        for (int i = 1; i <= asteroidsNum; i++)
        {
            float scaleSize = 0.5f;
            GameObject AsteroidClone = Instantiate(rock, new Vector3(transform.position.x, transform.position.y, 0f), transform.rotation);
            AsteroidClone.transform.localScale = new Vector3(AsteroidClone.transform.localScale.x * scaleSize, AsteroidClone.transform.localScale.y * scaleSize, AsteroidClone.transform.localScale.z * scaleSize);
            AsteroidClone.GetComponent().SetGeneration(newGeneration);
            AsteroidClone.SetActive(true);
        }
    }

    private void CheckPosition()
    {

        float sceneWidth = mainCam.orthographicSize * 2 * mainCam.aspect;
        float sceneHeight = mainCam.orthographicSize * 2;
        float sceneRightEdge = sceneWidth / 2;
        float sceneLeftEdge = sceneRightEdge * -1;
        float sceneTopEdge = sceneHeight / 2;
        float sceneBottomEdge = sceneTopEdge * -1;

        float rockOffset;
        if (gameplay.allAsteroidsOffScreen)
        {
            rockOffset = 1.0f;
            float reverseSpeed = 2000.1f;

            if (rock.transform.position.x > sceneRightEdge + rockOffset)
            {
                rock.transform.rotation = Quaternion.identity;
                rb.AddForce(transform.right * (reverseSpeed * (-1)));
            }

            if (rock.transform.position.x < sceneLeftEdge - rockOffset)
            {
                rock.transform.rotation = Quaternion.identity;
                rb.AddForce(transform.right * reverseSpeed);
            }

            if (rock.transform.position.y > sceneTopEdge + rockOffset)
            {
                rock.transform.rotation = Quaternion.identity;
                rb.AddForce(transform.up * (reverseSpeed * (-1)));
            }

            if (rock.transform.position.y < sceneBottomEdge - rockOffset)
            {
                rock.transform.rotation = Quaternion.identity;
                rb.AddForce(transform.up * reverseSpeed);
            }
        }
        else
        {
            rockOffset = 2.0f;
            if (rock.transform.position.x > sceneRightEdge + rockOffset)
            {
                rock.transform.position = new Vector2(sceneLeftEdge - rockOffset, rock.transform.position.y);
            }

            if (rock.transform.position.x < sceneLeftEdge - rockOffset)
            {
                rock.transform.position = new Vector2(sceneRightEdge + rockOffset, rock.transform.position.y);
            }

            if (rock.transform.position.y > sceneTopEdge + rockOffset)
            {
                rock.transform.position = new Vector2(rock.transform.position.x, sceneBottomEdge - rockOffset);
            }

            if (rock.transform.position.y < sceneBottomEdge - rockOffset)
            {
                rock.transform.position = new Vector2(rock.transform.position.x, sceneTopEdge + rockOffset);
            }
        }
    }

    public void Destroy()
    {
        gameplay.asterodDestroyed();
        Destroy(gameObject, 0.01f);
    }

    public void DestroySilent()
    {
        Destroy(gameObject, 0.00f);
    }

}

Bullet.cs

/*

   .-------.                             .--.    .-------.     .--.            .--.     .--.        
   |       |--.--.--------.-----.-----.--|  |    |_     _|--.--|  |_.-----.----|__|---.-|  |-----.
   |   -   |_   _|        |  _  |     |  _  |      |   | |  |  |   _|  _  |   _|  |  _  |  |__ --|
   |_______|__.__|__|__|__|_____|__|__|_____|      |___| |_____|____|_____|__| |__|___._|__|_____|
   © OXMOND / www.oxmond.com 

*/

using UnityEngine;

public class Bullet : MonoBehaviour
{
    void Start()
    {
        GetComponent().AddForce(transform.up * 350);
    }

    public void KillOldBullet()
    {
        Destroy(gameObject, 2.0f);
    }

    void OnCollisionEnter(Collision collisionInfo)
    {
        Destroy(gameObject, 0.0f);
    }
}

Gameplay.cs

/*

   .-------.                             .--.    .-------.     .--.            .--.     .--.        
   |       |--.--.--------.-----.-----.--|  |    |_     _|--.--|  |_.-----.----|__|---.-|  |-----.
   |   -   |_   _|        |  _  |     |  _  |      |   | |  |  |   _|  _  |   _|  |  _  |  |__ --|
   |_______|__.__|__|__|__|_____|__|__|_____|      |___| |_____|____|_____|__| |__|___._|__|_____|
   © OXMOND / www.oxmond.com 

*/

using UnityEngine;

public class Gameplay : MonoBehaviour
{

    public GameObject asteroid;
    public GameObject rocket;
    private int _startLevelAsteroidsNum;
    private bool _allAsteroidsOffScreen;
    private int levelAsteroidNum;
    private Camera mainCam;
    private int asteroidLife;

    private void Start()
    {
        asteroid.SetActive(false);
        mainCam = Camera.main;
        _startLevelAsteroidsNum = 2;
        CreateAsteroids(_startLevelAsteroidsNum);
    }

    private void Update()
    {
        RenderSettings.skybox.SetFloat("_Rotation", Time.time * 0.8f);

        if (asteroidLife <= 0)
        {
            asteroidLife = 6;
            CreateAsteroids(1);
        }
        
        float sceneWidth = mainCam.orthographicSize * 2 * mainCam.aspect;
        float sceneHeight = mainCam.orthographicSize * 2;
        float sceneRightEdge = sceneWidth / 2;
        float sceneLeftEdge = sceneRightEdge * -1;
        float sceneTopEdge = sceneHeight / 2;
        float sceneBottomEdge = sceneTopEdge * -1;

        _allAsteroidsOffScreen = true;
        
    }

    private void CreateAsteroids(float asteroidsNum)
    {
        for (int i = 1; i <= asteroidsNum; i++)
        {
            GameObject AsteroidClone = Instantiate(asteroid, new Vector2(Random.Range(-10, 10), 6f), transform.rotation);
            AsteroidClone.GetComponent().SetGeneration(1);
            AsteroidClone.SetActive(true);
        }
    }

    public void RocketFail()
    {
        Cursor.visible = true;
        print("GAME OVER");
    }

    public void asterodDestroyed()
    {
        asteroidLife--;
    }

    public int startLevelAsteroidsNum
    {
        get { return _startLevelAsteroidsNum; }
    }

    public bool allAsteroidsOffScreen
    {
        get { return _allAsteroidsOffScreen; }
    }

}

Rocket.cs

/*

   .-------.                             .--.    .-------.     .--.            .--.     .--.        
   |       |--.--.--------.-----.-----.--|  |    |_     _|--.--|  |_.-----.----|__|---.-|  |-----.
   |   -   |_   _|        |  _  |     |  _  |      |   | |  |  |   _|  _  |   _|  |  _  |  |__ --|
   |_______|__.__|__|__|__|_____|__|__|_____|      |___| |_____|____|_____|__| |__|___._|__|_____|
   © OXMOND / www.oxmond.com 

*/

using UnityEngine;

public class Rocket : MonoBehaviour
{
    public GameObject bullet;
    private float thrust = 6f;
    private float rotationSpeed = 180f;
    private float MaxSpeed = 4.5f;
    private Camera mainCam;
    private Rigidbody rb;

    private void Start()
    {
        mainCam = Camera.main;
        rb = GetComponent();
        bullet.SetActive(false);
    }

    private void FixedUpdate()
    {
        ControlRocket();
        CheckPosition();
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0) || Input.GetKeyDown("space"))
        {
            Shoot();
        }
    }

    private void ControlRocket()
    {
        transform.Rotate(0, 0, Input.GetAxis("Horizontal") * rotationSpeed * Time.deltaTime);
        rb.AddForce(transform.up * thrust * Input.GetAxis("Vertical"));
        rb.velocity = new Vector2(Mathf.Clamp(rb.velocity.x, -MaxSpeed, MaxSpeed), Mathf.Clamp(rb.velocity.y, -MaxSpeed, MaxSpeed));
    }

    private void CheckPosition()
    {

        float sceneWidth = mainCam.orthographicSize * 2 * mainCam.aspect;
        float sceneHeight = mainCam.orthographicSize * 2;

        float sceneRightEdge = sceneWidth / 2;
        float sceneLeftEdge = sceneRightEdge * -1;
        float sceneTopEdge = sceneHeight / 2;
        float sceneBottomEdge = sceneTopEdge * -1;

        if (transform.position.x > sceneRightEdge)
        {
            transform.position = new Vector2(sceneLeftEdge, transform.position.y);
        }
        if (transform.position.x < sceneLeftEdge)
        {
            transform.position = new Vector2(sceneRightEdge, transform.position.y);
        }
        if (transform.position.y > sceneTopEdge)
        {
            transform.position = new Vector2(transform.position.x, sceneBottomEdge);
        }
        if (transform.position.y < sceneBottomEdge)
        {
            transform.position = new Vector2(transform.position.x, sceneTopEdge);
        }
    }

    public void ResetRocket()
    {
        transform.position = new Vector2(0f, 0f);
        transform.eulerAngles = new Vector3(0, 180f, 0);
        rb.velocity = new Vector3(0f, 0f, 0f);
        rb.angularVelocity = new Vector3(0f, 0f, 0f);
    }

    void Shoot()
    {
            GameObject BulletClone = Instantiate(bullet, new Vector2(bullet.transform.position.x, bullet.transform.position.y), transform.rotation);
            BulletClone.SetActive(true);
            BulletClone.GetComponent().KillOldBullet();
            BulletClone.GetComponent().AddForce(transform.up * 350);
    }
}