Kontroler odtwarzacza RTS i MOBA dla Unity

W grach wideo termin RTS oznacza strategię czasu rzeczywistego.

Różnica między RTS a konwencjonalnymi strzelankami z perspektywy pierwszej/trzeciej osoby polega na tym, że postaciami steruje się za pomocą wskaźnika myszy, a nie zwykłych przycisków W, A, S i D.

Gracz otrzymuje widok na pole bitwy z lotu ptaka i może wydawać rozkazy żołnierzom, bez bezpośredniego ich kontrolowania. Przykładami gier RTS są Warcraft, Starcraft, Cossacks itp.

Zrzut ekranu z gry Warcraft 3

Z kolei MOBA to skrót od Multiplayer Online Battle Arena, czyli nieco nowszy podgatunek gier RTS, w których gracz steruje tylko jedną postacią, a nie wieloma.

Przykładami takich gier są League of Legends i Dota 2.

W tym samouczku pokażę, jak utworzyć kontroler w stylu RTS/MOBA w Unity.

Krok 1: Stwórzmy niezbędne skrypty

Ten samouczek jest dość prosty, ponieważ wymaga tylko jednego skryptu.

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);
            }
        }
    }
}

Krok 2

Teraz skonfigurujmy kontroler gracza i poziom gry.

  • Utwórz nowy obiekt GameObject i wywołaj go 'RTSPlayer'
  • Dołącz do niego skrypt RTSPlayerController.cs (UWAGA: po dołączeniu automatycznie doda kolejny komponent o nazwie NavMeshAgent, ten komponent będzie potrzebny później)

  • Dodaj ciało gracza (w moim przypadku użyję prostej kapsuły z kostką, ale możesz dodać model gracza, jeśli taki posiadasz). Zmniejsz go do żądanego rozmiaru.
  • Przenieś model gracza do obiektu GameObject 'RTSPlayer' (UWAGA: przed objęciem funkcji rodzicielskich upewnij się, że 'RTSPlayer' znajduje się na dole modelu gracza)

  • Wybierz 'RTSPlayer' i w NavMeshAgent dostosuj Promień i Wysokość, aż będą zgodne z modelem odtwarzacza

  • Następnym krokiem jest utworzenie wskaźnika celu prefab. To po prostu prosty GameObject z Quadem, który wskaże, gdzie kliknęliśmy na mapie.

Możesz użyć poniższej tekstury:

wskaźnik celu strategii czasu rzeczywistego

  • Na koniec wybierz 'RTSPlayer' i przypisz wszystkie niezbędne zmienne w skrypcie RTSPlayerController:

Kamera gracza – to oczywiste, może to być dowolna kamera

Camera Offset - jak daleko kamera powinna znajdować się od gracza

Prefabrykat wskaźnika celu - prefabrykat, który właśnie stworzyliśmy

Będąc w trybie gry, zauważysz, że kliknięcie na mapę nie powoduje ruchu gracza. To dlatego, że mamy jeszcze jedną rzecz do zrobienia, czyli upiecz siatkę nawigacyjną (Navmesh):

  • Wybierz wszystkie obiekty będące częścią mapy i oznacz je jako statyczne:

  • Przejdź do Okno -> AI -> Nawigacja

  • Na karcie Pieczenie zmień wartości Promień agenta i Wysokość agenta (powinny one odpowiadać wartościom z NavMeshAgent), a następnie kliknij Piecz.

  • Po zakończeniu pieczenia zauważysz niebieskawą siatkę, która reprezentuje obszar, po którym można chodzić.

UWAGA: Aby uniemożliwić graczowi chodzenie po wzgórzach, wróć do zakładki Pieczenie i zmniejsz maksymalny kąt nachylenia, a następnie ponownie wypal siatkę nawigacyjną.

Dużo lepiej!

Na koniec wróć do trybu odtwarzania i kliknij lewym przyciskiem myszy gdzieś na mapie.

Gracz powinien teraz ruszyć w stronę celu, omijając przeszkody:

Sharp Coder Odtwarzacz wideo

Wskazówka: dostosuj prędkość, prędkość kątową i wartość przyspieszenia w NavMeshagent, aby dopasować je do swoich potrzeb.