3D Infinite Runner Game – Unity3D (C#)
We have 2 choice to move character in an infinite runner game: move character or move ground. First one, you can move ground continuously in a negative direction to character and move right or left your character. I will explain the second one in this tutorial that a stable ground and a moving character.
For a brief description, we will create a plane as road, we will create some spheres to create coins and to make character move(it will follow the stable spheres and we will get a moving action) with Lerp method.
At first, create a Directional Light and a A plane with size (0.5, 1, 10). Create a sphere named P1 at the begining of plane( 0, 2, -5). This sphere is our start point. Now duplicate it, rename it as P2 and replace it to (0, 2, -4.5). Character will move from P1 to P2, from P2 to P3, from P3 to P4 etc. So, create and place 20 spheres with same Z distance (0.5). Create an empty game object named Points and regroup these spheres.
There is no sphere at the end of plane because we will clone this plane and the first sphere of the clone plane will be there. In additional, create a sphere named RoadSphere and place it 0.5Z far from the first sphere as seen on picture. This sphere keeps location of the clone plane. All of these plane and spheres will be its children and and it will be located on the last sphere of current plane. That provides a continuously road for us. Edit hierarchy as RoadSphere>Plane>Points>P1, P2, P3, P4,….. Make it prefab.
For character, create a sphere named CharacterSphere. Create a Capsule for character as child of CharacterSphere. Rotate it 90X for a horizontal capsule. Attach camera to Character sphere to make camera follow character. You can use textures for a better experience. Pick some textures from google and attach it your objects.
The small sphere belongs to our character and the big one is P2 sphere of road. Now, you can hide these all spheres by clickling checkbox near the Mesh
Renderer title. You can select multiple spheres by holding CTRL. Now you get a clear view on game scene. We don’t need view of these spheres and we don’t need their Mesh Renderers too.
Let’s start coding. We will 2 scripts for game controller and for collision. Create a C# script and don’t forget to add using System.Collections.Generic;
because we will use lists.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public GameObject Road; private List Cpoints = new List(); private List CurrentRoads = new List(); private int CurrentRoadId = 0; private Transform CenterPoints; void CreateNewRoad() { if(CurrentRoadId > 0) { if(CurrentRoadId > 1) { DestroyImmediate(CurrentRoads[CurrentRoadId - 2]); CurrentRoads.RemoveAt(0); CurrentRoadId--; } CurrentRoads.Add(Instantiate (Road, Cpoints[LevelCount * 19 + LevelCount - 1].position, Quaternion.identity) as GameObject); } else CurrentRoads.Add(Instantiate (Road, Vector3.zero, Quaternion.identity) as GameObject); CenterPoints = CurrentRoads[CurrentRoadId].transform.FindChild("Plane").FindChild("Points"); for (int i = 1; i < 21; i++) { Transform childPoint = CenterPoints.transform.FindChild("P" + i); Cpoints.Add(childPoint); } } |
This code checks at start if there is a road at scene. If not, checks if there is one road or more. If there are more than one, it destroys the old one. Code keeps all spheres and roads in a list to get information about them later in update method. New road will be added “LevelCount*19+LevelCount-1″th sphere. It is 20th sphere for the first clone after the road which is created at start. Now, call CreateNewRoad method at start.
1 2 3 4 | void Start () { CreateNewRoad(); } |
I said that our character will follow spheres with Lerp method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | private int CurrentPoint = 1; private float time = 0; private float distance = 0, nextDistance = 0; private float speed = 1.5f; private int LevelCount = 0; void Update () { Vector3 startPoint = new Vector3 (Cpoints [CurrentPoint].position.x + distance, Cpoints [CurrentPoint].position.y - 0.5f, Cpoints [CurrentPoint].position.z); Vector3 endPoint = new Vector3 (Cpoints [CurrentPoint + 1].position.x + distance, Cpoints [CurrentPoint + 1].position.y - 0.5f, Cpoints [CurrentPoint + 1].position.z); transform.position = Vector3.Lerp (startPoint, endPoint, time); transform.LookAt(Vector3.Lerp(Cpoints[CurrentPoint + 3].transform.position, Cpoints[CurrentPoint + 4].transform.position,time)); time += Time.deltaTime * speed; if(time > 1) { time = 0; CurrentPoint++; if(Cpoints [CurrentPoint].name == "P10") { CurrentRoadId++; LevelCount++; CreateNewRoad(); } } } |
We assigned starPoint and endPoint for movement. Also, we use LookAt to check if there is a sphere after a few spheres or not. When our character reaches to 10th sphere, we create a new road. You can change these values but be careful, if you create new road at last sphere, you get an error because code checks 3-4 far spheres and it will be empty. Now, we can add keyboard controllers in Update method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | public GameObject Coin; public List materials = new List(); private List CurrentCoins = new List(); void CreateNewRoad() { for (int i = CurrentCoins.Count - 1; i >= 0; i--) { if(CurrentCoins[i].transform.position.z < this.transform.position.z) { DestroyImmediate(CurrentCoins[i]); CurrentCoins.RemoveAt(i); } } if(CurrentRoadId > 0) { if(CurrentRoadId > 1) { DestroyImmediate(CurrentRoads[CurrentRoadId - 2]); CurrentRoads.RemoveAt(0); CurrentRoadId--; } CurrentRoads.Add(Instantiate (Road, Cpoints[LevelCount * 19 + LevelCount - 1].position, Quaternion.identity) as GameObject); } else CurrentRoads.Add(Instantiate (Road, Vector3.zero, Quaternion.identity) as GameObject); CenterPoints = CurrentRoads[CurrentRoadId].transform.FindChild("Plane").FindChild("Points"); for (int i = 1; i < 21; i++) { Transform childPoint = CenterPoints.transform.FindChild("P" + i); Cpoints.Add(childPoint); int typeNum = Random.Range(0, materials.Count); Vector3 cPOS = Vector3.zero; if(LevelCount > 0) cPOS = new Vector3(childPoint.transform.position.x + Random.Range(-1, 2) * 1.0f, childPoint.transform.position.y - 0.5f, childPoint.transform.position.z); else cPOS = new Vector3(Cpoints[i - 1].position.x + Random.Range(-1,2) * 1.0f,Cpoints[i - 1].position.y - 0.5f, Cpoints[i - 1].position.z); GameObject newCoin = (Instantiate(Coin,cPOS,Quaternion.identity) as GameObject); CurrentCoins.Add(newCoin); newCoin.transform.Rotate(90,0,90); newCoin.transform.renderer.material = materials[typeNum]; if(typeNum == 0) newCoin.name = "Yellow"; else if(typeNum == 1) newCoin.name = "Red"; else if(typeNum == 2) newCoin.name = "Blue"; else if(typeNum == 3) newCoin.name = "Black"; } } |
Create a folder named materials and create four materials for yellow, red, blue and black material. These materials give coins different colors. Add your materials as public objects to your script. Create a cube as an game object for coins.
Now, you may add collider to collect coins or a timer for a better gameplay experience.
You can download script file here.
©Coffee Break Codes – 3D Infinite Runner Game Tutorial – Unity3D (C#)
Nice stuff..Good for beginner..Thanks
how can we make a complete patch to repeat and desstrqoy in our game ?
i like it but there is problem with my project. help me