Auto-Aiming in 3D Space Using Player’s FOV

In this tutorial we take a look at using a player’s field of view (FOV) to detect whether or not it can see an enemy. If the player can see the enemy then they automatically aim towards it.

This is achieved by attaching a simple script to the part of the player that needs to rotate towards the enemy and letting it know what the enemy GameObject is, where the FOV should eminate from, the speed of the rotation and the angles that limit the FOV .

Play test the demo scene online here.

Download the unity package here.

These are the scripts used in the tutorial:

 

Enemy.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LookAtEnemy : MonoBehaviour
{
    public GameObject enemy;
    // This is what the player is looking at. In this example it is the dinosaur's head.

    public GameObject fovStartPoint;
    // We will use the forward direction of whatever GameObject you give it.

    public float lookSpeed = 200;
    // How fast the rotation happens.

    public float maxAngle = 45;
    // The maximum fov to trigger looking at the enemy.

    public float maxAngleReset = 90;
    // The maximum fov to trigger returning to the base state.
    
    public bool canLean = false;
    // This turns on looking up/down depending on the enemy's height.

    public bool arms = false;

    private Quaternion lookAt;
    private Quaternion targetRotation;

    void Update()
    {

        if (EnemyInFieldOfView(fovStartPoint))
        {
            Vector3 direction = enemy.transform.position - transform.position;

            if (!canLean)
            {
                direction = new Vector3(direction.x, 0, direction.z);
            }

            // Rotate the current transform to look at the enemy
            targetRotation = Quaternion.LookRotation(direction);
            lookAt = Quaternion.RotateTowards(
            transform.rotation, targetRotation, Time.deltaTime * lookSpeed);
            transform.rotation = lookAt;
        }
        else if (EnemyInFieldOfViewNoResetPoint(fovStartPoint))
        {
            return;
        }
        else
        {
            if (arms)
            {
                // make arms point at the ground
                Quaternion targetRotation = Quaternion.Euler(90, 0, 0);
                transform.localRotation = Quaternion.RotateTowards(
                transform.localRotation, targetRotation, Time.deltaTime * lookSpeed);
            }

            else
            {
                // return to initial local angle
                Quaternion targetRotation = Quaternion.Euler(0, 0, 0);
                transform.localRotation = Quaternion.RotateTowards(
                transform.localRotation, targetRotation, Time.deltaTime * lookSpeed);
            }
        }
    }

    bool EnemyInFieldOfView(GameObject looker)
    {

        Vector3 targetDir = enemy.transform.position - looker.transform.position;
        // gets the direction to the enemy.

        float angle = Vector3.Angle(targetDir, looker.transform.forward);
        // gets the angle based on the direction.

        if (angle < maxAngle)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    bool EnemyInFieldOfViewNoResetPoint(GameObject looker)
    {
        Vector3 targetDir = enemy.transform.position - looker.transform.position;
        float angle = Vector3.Angle(targetDir, looker.transform.forward);

        if (angle < maxAngleReset)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

 

PlayerMove3D.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove3D : MonoBehaviour
{
    public Animator anim;

    void Update()
    {
        var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        var z = Input.GetAxis("Vertical") * Time.deltaTime * 5.0f;

        transform.Rotate(0, x, 0);
        transform.Translate(0, 0, z);

        if (Input.GetAxis("Vertical") == 0)
        {
            anim.SetBool("Walking", false);
        }
        else
        {
            anim.SetBool("Walking", true);
        }
    }
}

Facebook Comments

Leave a Reply

Your email address will not be published. Required fields are marked *