0

Code:

        void IdleState ()
    {
    RaycastHit hit;

    for (float i = -ViewWidth; i < ViewWidth; i++)
        { 
            float Iterater = i/20;
            if (Physics.Raycast(transform.position, transform.forward + new Vector3(Iterater,0,0), out hit, ViewRange))
             {
                Debug.DrawRay(transform.position,(transform.forward + new Vector3(Iterater,0,0)).normalized * ViewRange, Color.red);
                if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Player"))
                 {
                    FoundPlayer(hit.transform);
                 }
             }
        }

}

Problem: In Unity I am trying to create a Field of view for an enemy AI by drawing multiple raycasts with for loops. For some reason the raycasts do this: GIF

I've been trying to fix this for days Please help!

Also the FoundPlayer() function in case you need it:

void FoundPlayer  (Transform DetectedObject)
    { 
        float step = TurnSpeed * Time.deltaTime;
        Vector3 Direc = DetectedObject.position - transform.position;
        Vector3 RotMath = Vector3.RotateTowards(transform.forward, Direc,step,0.0f);
        transform.rotation = Quaternion.LookRotation(RotMath);
        Vector3 CurrentRot = transform.eulerAngles;
        transform.rotation = Quaternion.Euler(0,CurrentRot.y,0);
    }

The FoundPlayer() function just rotates the enemy towards the player when one of the raycasts hit it.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
William L
  • 3
  • 2

1 Answers1

2

Regarding Raycast:

transform.Forward is in world-space coordinates, to which you add some fraction of world-space X-axis offset. What you wanted is to add some fraction of 'local-space' X-axis. transform.Right is the world-space conversion of local-space X-axis. Try:

var rayDirection = (transform.Forward + (Vector3.Scale(transform.Right, new Vector3(Iterater, 0, 0))).normalized;

Regarding Fields of View:

If all you want to do is check what objects are within a FOV, start finding everything within a sphere, then filter those objects to what's within appropriate angles from transform.forward:

float ViewRange = 10;
float hHalfFov = 45; // Horizontal Half-Field of View (Degrees)
float vHalfFov = 45; // Vertical Half-Field of View (Degrees)

void IdleState() {

    // Find all colliders within ViewRange
    var hits = Physics.OverlapSphere(transform.position, ViewRange);

    foreach (var hit in hits) {
        if ( hit.gameObject == this.gameObject ) continue; // don't hit self

        // Check FOV
        var direction = (transform.position - hit.transform.position);
        var hDirn = Vector3.ProjectOnPlane(direction, transform.up).normalized; // Project onto transform-relative XY plane to check hFov
        var vDirn = Vector3.ProjectOnPlane(direction, transform.right).normalized; // Project onto transform-relative YZ plane to check vFov

        var hOffset = Vector3.Dot(hDirn, transform.forward) * Mathf.Rad2Deg; // Calculate horizontal angular offset in Degrees
        var vOffset = Vector3.Dot(vDirn, transform.forward) * Mathf.Rad2Deg; // Calculate vertical angular offset in Degrees

        if (hOffset > hHalfFov || vOffset > vHalfFov) continue; // Outside of FOV

        Debug.DrawLine(transform.position, hit.transform.position, Color.red);

        if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Player")) {
            FoundPlayer(hit.transform);
        }
    }
}
Immersive
  • 1,684
  • 1
  • 11
  • 9
  • It seems that Transform.Scale doesnt exist, neither does transform.scale, was there something else you meant? – William L Jan 09 '19 at 03:42
  • Ahh, sorry. I meant `Vector3.Scale()` – Immersive Jan 09 '19 at 03:47
  • So for the most part that worked, only problem is it removed almost all the raycasts, only leaving the 2 on the very edge of the Enemy's Field of view and one that follows the player when detected. – William L Jan 09 '19 at 03:58
  • Try different divisors for the Iterater. Consider that you're doing vector additions for the `rayDirection`: One unit forward plus some fraction of one unit left/right. A 45degree offset would require a full unit of offset left/right. Vector addition may not be the best solution, vector rotations would probably be better. The point of this answer was to highlight that you were incorrectly using mixed coordinate systems. – Immersive Jan 09 '19 at 04:06
  • Added extra part for dealing with FOVs – Immersive Jan 09 '19 at 04:38