Menu
CoddyTech

Прицеливание

Урок 10 из 25 курса Игра на Unity: Tower Defense на Coddy.

Башня поворачивается к своей цели: не вся башня, которая стоит на своей площадке, а её верхняя часть — дочерний объект, на котором находится ствол. Поворот дочернего объекта поворачивает всё, что находится под ним, а родительский объект остаётся на месте.

Враги идут ниже верхних частей башен, поэтому направление от верхней части к врагу немного наклонено вниз, и если верхняя часть будет смотреть строго вдоль него, она наклонится вперёд. Если установить y направления в 0, оно останется горизонтальным, поэтому верхняя часть будет поворачиваться только вокруг вертикальной оси. Например, лампа маяка, следующая за кораблём:

Vector3 toShip = ship.position - lamp.position;
toShip.y = 0f;
lamp.rotation = Quaternion.LookRotation(toShip);
Quaternion.LookRotation(direction) — это поворот, направляющий объект в указанную сторону, поэтому лампа сразу поворачивается к кораблю. Верхняя часть башни должна поворачиваться с заданной скоростью: Quaternion.RotateTowards(from, to, maxDegrees) из главы о вращении поворачивает объект не более чем на maxDegrees, а скорость поворота в градусах в секунду, умноженная на Time.deltaTime, задаёт величину поворота за каждый кадр.

challenge icon

Задание

Средне

Поворачивай головку каждой башни к цели.

  1. В Tower добавь [SerializeField] private Transform head; и [SerializeField] private float turnSpeed = 270f;.
  2. Если есть цель, поворачивай head к ней только вокруг оси y, не более чем на turnSpeed * Time.deltaTime градусов, с помощью Quaternion.RotateTowards.
  3. Стреляй из ствола: head.position + head.forward * 0.6f.

Нажми «Играть»: головки следят за врагами и стреляют из ствола. Затем нажми «Проверить».

Попробуйте сами

using UnityEngine;

public class Tower : MonoBehaviour
{
    public float range = 4f;
    public int damage = 2;
    [SerializeField] private Projectile projectilePrefab;

    private Enemy target;
    private float nextShot;

    void Update()
    {
        Enemy found = FindTarget();
        if (found != null && found != target)
        {
            Debug.Log("Target: " + found.name);
        }
        target = found;
        if (target == null)
        {
            return;
        }

        if (Time.time >= nextShot)
        {
            Fire();
            nextShot = Time.time + 1f;
        }
    }

    Enemy FindTarget()
    {
        Enemy nearest = null;
        float nearestDistance = range;
        foreach (Enemy enemy in Enemy.All)
        {
            float distance = Vector3.Distance(transform.position, enemy.transform.position);
            if (distance <= nearestDistance)
            {
                nearest = enemy;
                nearestDistance = distance;
            }
        }
        return nearest;
    }

    void Fire()
    {
        Projectile shot = Instantiate(projectilePrefab, transform.position + Vector3.up, Quaternion.identity);
        shot.Launch(target.transform, damage);
    }
}

Все уроки раздела Игра на Unity: Tower Defense

Потренируйтесь самостоятельно: Песочница Unity