Menu
CoddyTech

Patrulhe e persiga

Parte da seção Física e Jogabilidade do Journey de Unity da Coddy. Lição 54 de 71.

Um guarda em patrulha percorre uma rota até avistar o jogador, persegui-lo e voltar à rota quando o jogador desaparecer. Os dois comportamentos seguem a mesma lógica: deslocam-se em direção a um ponto, então um único método pode fazer o movimento em ambos os casos. Este sentinela vai e volta entre dois postos e persegue o jogador dentro de chaseRange:

[SerializeField] private Transform pointA;
[SerializeField] private Transform pointB;
[SerializeField] private Transform player;
[SerializeField] private float speed = 2f;
[SerializeField] private float chaseRange = 5f;
private Rigidbody rb;
private Transform goal;

void Start()
{
    rb = GetComponent<Rigidbody>();
    goal = pointA;
}

void FixedUpdate()
{
    if (Flat(player.position - rb.position).magnitude < chaseRange)
    {
        WalkTo(player.position);
        return;
    }
    if (Flat(goal.position - rb.position).magnitude < 0.2f)
    {
        goal = goal == pointA ? pointB : pointA;
    }
    WalkTo(goal.position);
}

void WalkTo(Vector3 target)
{
    Vector3 dir = Flat(target - rb.position).normalized;
    rb.linearVelocity = new Vector3(dir.x * speed, rb.linearVelocity.y, dir.z * speed);
}

Vector3 Flat(Vector3 v)
{
    return new Vector3(v.x, 0f, v.z);
}

O teste de perseguição vem primeiro, e o return faz com que o código da patrulha seja ignorado, então a perseguição tem prioridade sempre que o jogador está por perto. goal é um campo, então o sentinela se lembra dele durante uma perseguição: quando o jogador desaparecer, ele continua até o posto para o qual estava indo.

O teste de chegada mede a distância pelo chão. Os postos são marcadores no chão e o centro do sentinela fica 1 unidade acima deles, então uma distância que inclua a altura nunca fica abaixo de 1 e o sentinela nunca daria meia-volta. O teste verifica se a distância é menor que 0.2, não se é exatamente 0: a 2 unidades por segundo, o sentinela se move 0.04 unidades por passo e quase nunca chega exatamente ao posto.

challenge icon

Desafio

Médio

Faça o robô patrulhar seus pontos de referência e perseguir o jogador que se aproximar.

  1. Escreva WalkTo(Vector3 target), definindo rb.linearVelocity em direção a ele pelo chão com speed, mantendo sua velocidade y.
  2. Em FixedUpdate(), quando o jogador estiver a uma distância menor que chaseRange, use WalkTo(player.position) e return.
  3. Caso contrário, quando estiver a menos de 0.2 de waypoints[next], defina next = (next + 1) % waypoints.Length; e, em seguida, caminhe até waypoints[next].

Pressione “Jogar” e cruze o caminho dele. Depois, pressione “Verificar”.

Experimente você mesmo

using UnityEngine;

public class Robot : MonoBehaviour
{
    [SerializeField] private Transform[] waypoints;
    [SerializeField] private Transform player;
    [SerializeField] private float speed = 4f;
    [SerializeField] private float chaseRange = 4f;
    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        // persiga o jogador quando ele estiver perto ou percorra a rota de patrulha
    }
}

Todas as lições de Física e Jogabilidade

Pratique por conta própria: Playground de Unity