Menu
CoddyTech

Viser

Leçon 10 sur 25 du cours Jeu Unity : défense de tours de Coddy.

Une tour se tourne vers sa cible : pas la tour entière, qui repose sur son socle, mais sa tête, un objet enfant qui porte le canon. Tourner un enfant fait tourner tout ce qui se trouve sous lui et laisse le parent tel quel.

Les ennemis marchent plus bas que les têtes, donc la direction d’une tête vers son ennemi pointe légèrement vers le bas, et une tête qui la suivrait droit devant basculerait vers l’avant. Mettre le y de la direction à 0 la maintient à l’horizontale : la tête tourne donc uniquement autour de l’axe vertical. Une lampe de phare qui suit un navire :

Vector3 toShip = ship.position - lamp.position;
toShip.y = 0f;
lamp.rotation = Quaternion.LookRotation(toShip);
Quaternion.LookRotation(direction) est la rotation qui fait face à cette direction, donc la lampe se tourne aussitôt vers le navire. La tête d’une tour devrait plutôt tourner à une certaine vitesse : Quaternion.RotateTowards(from, to, maxDegrees), présenté dans le chapitre sur les rotations, tourne d’au plus maxDegrees, et une vitesse de rotation en degrés par seconde multipliée par Time.deltaTime donne la part de chaque image.
challenge icon

Défi

Moyen

Tournez la tête de chaque tour pour qu’elle fasse face à sa cible.

  1. Dans Tower, ajoutez [SerializeField] private Transform head; et [SerializeField] private float turnSpeed = 270f;.
  2. Lorsqu’une cible est présente, tournez head vers elle autour de l’axe y uniquement, d’au plus turnSpeed * Time.deltaTime degrés, avec Quaternion.RotateTowards.
  3. Tirez depuis le canon : head.position + head.forward * 0.6f.

Appuyez sur « Jouer » : les têtes suivent les ennemis et tirent depuis le canon. Puis appuyez sur « Vérifier ».

Essayez vous-même

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

Toutes les leçons de Jeu Unity : défense de tours

Entraînez-vous par vous-même : Playground Unity