How to Create the Iconic Asteroids Arcade Gameplay! Unity 2019 Intermediate Tutorial
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
🚀 Play 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
😷👕 Need a face mask / developer T-shirt? Drop by our shop and get a 20% DISCOUNT on your first purchase by using the discount code OXMONDSALE. Click here:
https://shop.oxmond.com/discount/OXMONDSALE
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); } }
Great tutorial. Unfortunately the scripts made available in the page are not quite up to date compared to those in the video and they fail to compile. I’ve made a number of changes to get them compiling but some aspects don’t work as expected and as a Unity beginner I’m struggling a bit. Would be great if you could post the final scripts used.
My family members all the time say that I am killing
my time here at net, except I know I am getting know-how every day
by reading thes nice content.
I every time used to read piece of writing in news papers but
now as I am a user of web thus from now I am using net for content,
thanks to web
I’m amazed, I must say. Rarely do I encounter a blog that’s equally educative and
amusing, and let me tell you, you’ve hit the nail on the head.
The issue is an issue that not enough people are speaking intelligently about.
I am very happy I found this in my search for something regarding this.
I am a big supporter of this blog. Thank you for creating it.