RTS- und MOBA-Player-Controller für Unity
In Videospielen steht der Begriff RTS für Echtzeitstrategie.
Der Unterschied zwischen RTS und herkömmlichen Ego-/Third-Person-Shooter-Spielen besteht darin, dass die Charaktere mit dem Mauszeiger und nicht mit den üblichen W-, A-, S- und D-Tasten gesteuert werden.
Der Spieler erhält eine Adlerperspektive auf das Schlachtfeld und kann den Truppen Befehle erteilen, ohne sie direkt zu kontrollieren. Beispiele für RTS-Spiele sind Warcraft, Starcraft, Cossacks usw.
Andererseits steht MOBA für Multiplayer Online Battle Arena und ist ein etwas neueres Subgenre von RTS-Spielen, bei dem der Spieler nur einen Charakter statt vieler steuert.
Beispiele für solche Spiele sind League of Legends und Dota 2.
In diesem Tutorial zeige ich, wie man einen Controller im RTS/MOBA-Stil in Unity erstellt.
Schritt 1: Lassen Sie uns die erforderlichen Skripte erstellen.
Dieses Tutorial ist recht einfach, da es nur ein Skript erfordert.
RTSPlayerController.cs
//You are free to use this script in Free or Commercial projects
//sharpcoderblog.com @2018
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class RTSPlayerController : MonoBehaviour
{
public Camera playerCamera;
public Vector3 cameraOffset;
public GameObject targetIndicatorPrefab;
NavMeshAgent agent;
GameObject targetObject;
// Use this for initialization
void Start()
{
agent = GetComponent<NavMeshAgent>();
//Instantiate click target prefab
if (targetIndicatorPrefab)
{
targetObject = Instantiate(targetIndicatorPrefab, Vector3.zero, Quaternion.identity) as GameObject;
targetObject.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
#if (UNITY_ANDROID || UNITY_IOS || UNITY_WP8 || UNITY_WP8_1) && !UNITY_EDITOR
//Handle mobile touch input
for (var i = 0; i < Input.touchCount; ++i)
{
Touch touch = Input.GetTouch(i);
if (touch.phase == TouchPhase.Began)
{
MoveToTarget(touch.position);
}
}
#else
//Handle mouse input
if (Input.GetKeyDown(KeyCode.Mouse0))
{
MoveToTarget(Input.mousePosition);
}
#endif
//Camera follow
playerCamera.transform.position = Vector3.Lerp(playerCamera.transform.position, transform.position + cameraOffset, Time.deltaTime * 7.4f);
playerCamera.transform.LookAt(transform);
}
void MoveToTarget(Vector2 posOnScreen)
{
//print("Move To: " + new Vector2(posOnScreen.x, Screen.height - posOnScreen.y));
Ray screenRay = playerCamera.ScreenPointToRay(posOnScreen);
RaycastHit hit;
if (Physics.Raycast(screenRay, out hit, 75))
{
agent.destination = hit.point;
//Show marker where we clicked
if (targetObject)
{
targetObject.transform.position = agent.destination;
targetObject.SetActive(true);
}
}
}
}
Schritt 2
Nun richten wir einen Player-Controller und ein Spiellevel ein.
- Erstellen Sie ein neues GameObject und nennen Sie es 'RTSPlayer'
- Hängen Sie das RTSPlayerController.cs-Skript daran an (HINWEIS: Beim Anhängen wird automatisch eine weitere Komponente namens NavMeshAgent hinzugefügt, diese Komponente wird später benötigt)
- Fügen Sie einen Spielerkörper hinzu (in meinem Fall verwende ich eine einfache Kapsel mit einem Würfel, aber Sie können ein Spielermodell hinzufügen, falls Sie welche haben). Verkleinern Sie es, bis die gewünschte Größe erreicht ist.
- Verschieben Sie das Spielermodell in das GameObject 'RTSPlayer' (HINWEIS: Stellen Sie vor dem Parenting sicher, dass 'RTSPlayer' am unteren Rand des Spielermodells platziert ist.)
- Wählen Sie 'RTSPlayer' und passen Sie in NavMeshAgent den Radius und die Höhe an, bis sie dem Spielermodell entsprechen
- Als nächstes erstellen Sie einen Zielindikator prefab. Dies ist nur ein einfaches GameObject mit einem Quad, das anzeigt, wo wir auf der Karte geklickt haben.
Sie können die folgende Textur verwenden:
- Und schließlich wählen Sie 'RTSPlayer' aus und weisen alle erforderlichen Variablen im RTSPlayerController-Skript zu:
Player-Kamera – ist selbsterklärend, das kann jede beliebige Kamera sein
Kamera-Offset – wie weit die Kamera vom Player entfernt sein soll
Zielindikator Prefab – das Prefab, das wir gerade erstellt haben
Im Spielmodus werden Sie feststellen, dass sich der Spieler nicht bewegt, wenn er auf die Karte klickt. Das liegt daran, dass wir noch eine letzte Sache zu tun haben, nämlich ein Navigationsnetz (Navmesh) zu backen:
- Wählen Sie alle Objekte aus, die Teil der Karte sind, und markieren Sie sie als statisch:
- Gehen Sie zu Fenster -> KI -> Navigation
- Ändern Sie auf der Registerkarte „Backen“ die Werte für „Agent Radius“ und „Agent Height“ (diese sollten mit den Werten von NavMeshAgent übereinstimmen) und klicken Sie dann auf „Backen“.
- Nachdem das Backen beendet ist, werden Sie ein bläulich umrandetes Netz bemerken, das den begehbaren Bereich darstellt.
HINWEIS: Um zu verhindern, dass der Spieler über die Hügel läuft, gehen Sie zurück zur Registerkarte „Backen“, verringern Sie den maximalen Neigungswinkel und backen Sie dann das Navmesh erneut.
Viel besser!
Gehen Sie abschließend zurück in den Wiedergabemodus und klicken Sie mit der linken Maustaste irgendwo auf die Karte.
Der Spieler sollte sich nun auf das Ziel zubewegen und dabei den Hindernissen ausweichen:
Tipp: Passen Sie die Werte für Geschwindigkeit, Winkelgeschwindigkeit und Beschleunigung bei NavMeshagent an Ihre Bedürfnisse an.