Unity3D Endless Runner Tutorial

Infinite Runner Game mit Unity3d

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5,00 out of 5)
Loading ... Loading ...

In diesem Unity-3D Tutorial zeige ich an einem einfachen Beispiel wie man einen sogenannten endless oder infinite runner mit der Unity-Engine programmiert. Ein Spiel das recht bekannt geworden ist und das auch auf der Unity-Engine basiert ist Subway Surfers. Man steuert hierbei eine Spielfigur dich sich auf Schienen bewegt. Diese Schienen und die Landschaft werden schnell über die Z-Achse bewegt.

Es sieht dabei für den Benutzer so aus, als ob es eine riesige Landschaft wäre, technisch ist es aber wohl so, dass die Landschaft dynamisch erstellt wird. Die Teile die nach vorne hin verschwinden werden gelöscht, die Teile die erzeugt werden, werden im nicht sichtbaren Bereich der Z-Achse generiert.

Ich habe versucht dies mit Unity Prefabs nachzustellen. Ein Prefab ist dabei ein Straßenteil das folgende Abmessungen hat (Scale): X = 3, Y = 1, Z = 10. Hier ein Video das zeigt wie sich Scene- und Game-Window beim Start verhalten, man sieht dabei recht gut, dass immer nur 3 Prefabs im Speicher sind:

Warum Prefabs dynamisch erzeugen?

Klar, man könnte ja einfach in den Editor alle Prefabs platzieren, das Problem dabei liegt aber klar auf der Hand: Der Speicher wird stark belastet da alle Modelle vorhanden sind wenn die Szene dargestellt wird. Aus diesem Grund ist es ratsam für dieses Szenario die einzelnen Modellteile on the fly zu erstellen.

Wie erstellt man Prefabs über Script?

Prefabs lassen sich über den Befehl Instantiate erzeugen und sogar direkt an einer Position im 3D-Raum positionieren. Zu Beginn des C#-Skriptes für unsere Szene erstellen wir 3 Prefabs wie folgt, dies sind die Teile der Straße die immer sichtbar sind:

public Transform prefab;
	
private LinkedList<Transform> roads = new LinkedList<Transform>();
	
private float posY = 0.0f;
private int numberOfRoads = 3;
	
// Use this for initialization
void Start () {
		
	// Init the scene with some road-pieces
	for(int i=0;i < numberOfRoads;i++) {
		Transform road = Instantiate(prefab) as Transform;
		road.Translate(0, posY, i * road.localScale.z);
		roads.AddLast(road);
	}
}

Wenn man ein Objekt nicht mehr benötigt sollte man es aus dem Speicher entfernen, was über die Methode Destroy(gameObject) erreicht werden kann. In unserem Fall halten wir die Modelle die sichtbar sind in einer verketteten Liste und löschen immer nur das Objekt, dass nicht mehr angezeigt wird, wenn es sich aus dem Bereich der Camera bewegt hat:

In diesem Moment fügen wir auch wieder ein Objekt in die Liste ein und positionieren es am Ende der vorhandenen Prefabs, wo es noch nicht sichtbar ist:

private LinkedList<Transform> roads = new LinkedList<Transform>();

// Update is called once per frame
void Update () {
	
	Transform firstRoad = roads.First.Value;
	Transform lastRoad = roads.Last.Value;
	
	// Create a new road if the first one is not 
	// in sight anymore and destroy the first one
	if(firstRoad.localPosition.z < -15f) {
			roads.Remove(firstRoad);
		Destroy(firstRoad.gameObject);
		
		Transform newRoad = Instantiate(prefab, new Vector3(0, posY ,
			lastRoad.localPosition.z + lastRoad.localScale.z), 
			Quaternion.identity) as Transform;
			roads.AddLast(newRoad);
			
	}
		
	// Move the available roads along the z-axis
	foreach(Transform road in roads) {
		road.Translate(0,0, -8f * Time.deltaTime);	
	}
		
}

Natürlich muss man nicht immer dasselbe Prefab erstellen wie in diesem Beispiel sondern kann sich seine Welt wie man es wünscht über verschiedene Prefabs bunt zusammenstellen.

facebooktwittergoogle_plusredditpinterestlinkedin

Kommentiere auf Facebook

Kommentare