Look Them In The Eyes (in other words, using LookAt())

Any questions or discussion on this one? Where else could you use LookAt()?

I didn’t like that the enemies weren’t looking at me when I attacked them so I created a LookAt()

using RPG.Core;
using RPG.Movement;
using UnityEngine;

namespace RPG.Combat
{
    public class Fighter : MonoBehaviour, IAction
    {
        [SerializeField] float attackRange = 1.5f;
        [SerializeField] float numOfAttacks = 1f;

        Transform opponent;
        float timeSinceLastAttack = Mathf.Infinity;

        void Update()
        {
            timeSinceLastAttack += Time.deltaTime;
            
            if      (opponent == null)  { return; }
            if      (!IsInRange())
            {
                GetComponent<Mover>().MoveTo(opponent.position);
            } else  {
                        GetComponent<Mover>().CancelAction();
                        AttackBehavior();
                    }
            }

        private void AttackBehavior()
        {
            float timeBetweenAttacks = 6f/numOfAttacks;
            LookAt(opponent.position);
            if(timeSinceLastAttack < timeBetweenAttacks) { return; }
            GetComponent<Animator>().SetTrigger("medAttack");
            timeSinceLastAttack = 0f;
        }

        public void CancelAction()
        {
            opponent = null;
            GetComponent<Animator>().ResetTrigger("medAttack");
        }
        
        public void Attack(CombatTarget target)
        {
            GetComponent<ActionScheduler>().StartAction(this);
            opponent = target.transform;
        }

        public void LookAt(Vector3 position)
        {
            transform.LookAt(position);
        }
        
        private bool IsInRange()
        {
            return Vector3.Distance(transform.position, opponent.position) < attackRange;
        }

       void Hit()      // Animation Event
       {
            float damage = 1f;
            Health enemyHealth = opponent.GetComponent<Health>();
            enemyHealth.TakeDamage(damage);
            enemyHealth.GetComponent<Fighter>().LookAt(transform.position);
            if (enemyHealth.GetIsDead())
            {
                opponent.GetComponent<Animator>().SetTrigger("onDeath");
                CancelAction();
            }
        }
    }
}
1 Like

I actually implemented this before you brought this up with a different approach.
The difference is that my approach is less abrupt.

private void FaceTarget()
        {
            if (target == null)
                return;
            var targetRotation = Quaternion.LookRotation(target.position - transform.position);
            transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, rotationSpeed);
        }

And this method is called when isInRange is true.

Though I agree that we should settle with an OK approach rather than a “perfect” approach.

I put it in PlayerController…

private bool InteractWithCombat()

    {

        RaycastHit[] hits = Physics.RaycastAll(GetMouseRay());

        foreach (RaycastHit hit in hits)

        {

            CombatTarget target = hit.transform.GetComponent<CombatTarget>();

            if(target == null) continue;

            if(Input.GetMouseButtonDown(0))

            {

                //transform.LookAt(target.transform.position);

                GetComponent<Fighter>().Attack(target);

            }

            return true;

        } 

        return false;  

    }

I commented it out for now but it seemed to have the same result

At this point, it shouldn’t make much of a difference, because it’s just the player (actually, we’ll be moving that lookat to Fighter in future lectures). Once we have Enemies running around, etc, that lookat will be a lot more significant, especially if you move mid combat, then the enemy will continue to face you.

Could you fix your null reference exceptions when you see them? cuz my game freezes when I encounter null pointer. I don’t know what settings you tweaked such that your game still runs.

Initially, I put my call to LookAt() in CheckDistanceAndMove. So before the player even moves into range.
But this isn’t ideal or necessary because when moving, the player already will automatically turn to face its destination. So I do like it better per Rick’s solution in the AttackBehaviour() [speaking of unnecessary, who doesn’t like a good ol’ British ‘u’ in ‘behaviour’?]

Dont know if you have fixed this issue yet but have you had a look to see if “Error Pause” is on in the console?

It will pause play mode on encountering an error.

so I have been playing around with this a bit. I have coded in that when player gets in range the enemy chases the player at the set max speed, but when they return back to their position or patrol route, they walk back slowly. seems more natural. I was looking at the guards I have and when they return to their position they are facing the wrong way. I have tried 5 or 6 different ways to have them rotate back around but nothing I have tried seems to work. My most promising attempt was creating a game object and using transform.lookat, no dice. I then tried creating a patrol route of 1 and calling the lookat when they reach the waypoint on return but that doesn’t get called either. any suggestions? or is this discussed in greater detail later?

Privacy & Terms