Mesh is moving faster than the game object is attached to.

I have been following this tutorial to make a ‘field of view cone’ for NPCs. The tutorial was made for 2D games but adapting it to 3D has been fairly straightforward except for this problem I cannot seem to solve.

The problem happens whenever the game object is not centered at (0,0,0) the mesh will be much further in any direction than the physics and debug rays. I have attached some pictures showing what happens when you move the game object and the code I’m working with below.

Is there something that governs the movement of the mesh on the game object that I am not aware of?

Here is the game running when the game object is at the origin.

This happens when I move the game object in the negative X direction

6895658--806828--Screen Shot 2021-03-02 at 7.29.51 PM.png

This will happen when I move the game object in the positive Z direction

This will happen when I move the game object in the positive Y direction

The fov is made from an empty game object that is given a script, a material, a mesh filter, and a mesh renderer.

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

public class FieldOfView : MonoBehaviour {
   
    [SerializeField] private LayerMask layerMask;
    private Mesh mesh;
    private Vector3 origin;
    private float startingAngle;
    private float fov;

    private void Start()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;
        fov = 90f;

    }
    private void  LateUpdate()
    {
        int rayCount = 50;

        float angle = startingAngle;
        origin = transform.position;
        Vector3 eyeHeight = Vector3.zero; //new Vector3(0, 2.5f, 0);
        float angleIncrease = fov/rayCount;
        float viewDistance = 10f;

        Vector3[] vertices = new Vector3[rayCount + 1 + 1];
        Vector2[] uv = new Vector2[vertices.Length];
        int[] triangles = new int[rayCount * 3];

        vertices[0] = origin;

        int vertexIndex = 1;
        int triangleIndex = 0;

        RaycastHit raycastHit;
        for (int i = 0; i <= rayCount; i++)
        {
            Vector3 vertex;
            // RayCast(Origin, Direction, MaxDistance, LayerMask, QueryTriggerInteraction)
            Physics.Raycast(origin + eyeHeight, GetVectorFromAngle(angle), out raycastHit, viewDistance, layerMask);

            Debug.DrawRay(origin + eyeHeight, GetVectorFromAngle(angle)*viewDistance,Color.blue,0,true);
            if(raycastHit.collider == null)
            {
                // object was not hit
                Debug.Log("No Hit");
                vertex = origin + GetVectorFromAngle(angle)* viewDistance;
            }
            else
            {
                // object was hit
                Debug.Log("Hit");
                Debug.Log(raycastHit);

                // raycastHit.point.y = 0;
                //vertex = raycastHit.point
                vertex = Vector3.Scale(raycastHit.point, new Vector3(1,0,1));
            }
            vertices[vertexIndex] = vertex;

            if(i > 0)
            {
                triangles[triangleIndex + 0] = 0;
                triangles[triangleIndex + 1] = vertexIndex -1;
                triangles[triangleIndex + 2] = vertexIndex;

                triangleIndex += 3;
            }
           
            vertexIndex++;
            // this is not += because increasing in angle in unity goes clockwise instead of counterclockwise
            angle -= angleIncrease;
        }


        triangles[0] = 0;
        triangles[1] = 1;
        triangles[2] = 2;

        mesh.vertices = vertices;
        mesh.uv = uv;
        mesh.triangles = triangles;
    }

    Vector3 GetVectorFromAngle(float angle)
    {
        float angleRad = angle * (Mathf.PI/180f);
        return new Vector3(Mathf.Cos(angleRad), 0, Mathf.Sin(angleRad));
    }

    float GetAngleFromVectorFloat(Vector3 direction){
        direction = direction.normalized;
        float n = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        if (n < 0 ) n += 360;

        return n;
    }
    //when on a NPC object the NPC will call this function
    public void SetOrigin(Vector3 origin)
    {
       
        this.origin = origin;
    }

    //when on a NPC object the NPC will call this function
    public void SetAimDirection(Vector3 aimDirection)
    {
        startingAngle = GetAngleFromVectorFloat(aimDirection) - fov / 2f;
    }
}

Physics.Raycast and Debug.DrawRay uses world space coordinates. Mesh Vertices use object space coordinates. So when you move the object away from 0,0,0, the vertices are being offset by the object to world transformation.

1 Like

That is good information to know, thanks. Is there a way to force the use of object space or world space when desired?

No, but you can transform positions or vectors to or from world space and local object space.