Controlador de jogador RTS e MOBA para Unity

Nos videogames, o termo RTS significa estratégia em tempo real.

A diferença entre RTS e jogos convencionais de tiro em primeira/terceira pessoa é que os personagens são controlados usando o ponteiro do mouse em vez dos habituais botões W, A, S e D.

O jogador tem uma visão panorâmica do campo de batalha com a capacidade de dar ordens às tropas, sem controlá-las diretamente. Exemplos de jogos RTS são Warcraft, Starcraft, Cossacks, etc.

Captura de tela do jogo Warcraft 3

Por outro lado, MOBA significa Multiplayer Online Battle Arena, é um subgênero um pouco mais novo de jogos RTS onde o jogador controla apenas um personagem em vez de muitos.

Exemplos de tais jogos são League of Legends e Dota 2.

Neste tutorial, mostrarei como criar um controlador estilo RTS/MOBA em Unity.

Etapa 1: vamos criar os scripts necessários

Este tutorial é bastante simples, pois requer apenas um script.

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

Passo 2

Agora vamos configurar um controlador de jogador e um nível de jogo.

  • Crie um novo GameObject e chame-o 'RTSPlayer'
  • Anexe o script RTSPlayerController.cs a ele (NOTA: Ao anexar, ele adicionará automaticamente outro componente chamado NavMeshAgent, este componente será necessário mais tarde)

  • Adicione um corpo de jogador (no meu caso usarei uma cápsula simples com um cubo, mas você pode adicionar um modelo de jogador se tiver algum). Reduza até o tamanho desejado.
  • Mova o modelo do jogador dentro do GameObject 'RTSPlayer' (NOTA: Antes de criar os pais, certifique-se de que 'RTSPlayer' esteja colocado na parte inferior do modelo do jogador)

  • Selecione 'RTSPlayer' e no NavMeshAgent ajuste o Raio e a Altura até que corresponda ao modelo do jogador

  • A seguir, crie um indicador de meta pré-fabricado. Este é apenas um GameObject simples com um Quad que indicará onde clicamos no mapa.

Você pode usar a textura abaixo:

indicador de meta de estratégia em tempo real

  • E por último, selecione 'RTSPlayer' e atribua todas as variáveis ​​necessárias no script RTSPlayerController:

Câmera do jogador - é autoexplicativa, pode ser qualquer câmera

Camera Offset - a que distância a câmera deve estar do player

Target Indicator Prefab - o pré-fabricado que acabamos de criar

Enquanto estiver no modo Play, você notará que clicar no mapa não faz o jogador se mover. Isso porque temos uma última coisa a fazer, que é preparar uma Navigation Mesh (Navmesh):

  • Selecione todos os objetos que fazem parte do mapa e marque-os como estáticos:

  • Vá para Janela -> AI -> Navegação

  • Na guia Bake, altere os valores de Agent Radius e Agent Height (esses devem corresponder aos valores de NavMeshAgent) e clique em Bake.

  • Depois que o cozimento terminar, você notará uma malha com contorno azulado, que representa a área que pode ser percorrida.

NOTA: Para evitar que o jogador ande pelas colinas, volte para a aba Bake e diminua o ângulo Max Slope e então refaça a malha de navegação.

Muito melhor!

Por fim, volte ao modo Play e clique com o botão esquerdo em algum lugar do mapa.

O jogador deve agora mover-se em direção ao alvo evitando os obstáculos:

Sharp Coder Reprodutor de vídeo

Dica: Ajuste a velocidade, a velocidade angular e o valor de aceleração no NavMeshagent para atender às suas necessidades.