Unity2D视野脚本射线原点未更新问题求助
Unity2D视野射线原点不更新问题排查与修复
我参考YouTube上CodeMonkey的视野(FOV)脚本教程编写了Unity2D项目代码,但射线检测原点无法随玩家位置更新——射线方向正常,但位置始终停留在(0,0)。即使将FieldOfView脚本挂载到玩家控制器上,视野网格可随玩家移动,但射线原点问题仍存在。通过调试打印origin的值,显示它确实随玩家坐标变化,但射线碰撞计算依旧异常:玩家移动后,射线检测的碰撞结果未更新,仿佛碰撞物体仍在原地。
相关脚本
FieldOfView脚本
public class FieldOfView : MonoBehaviour { [SerializeField] private LayerMask layerMask; private Mesh mesh; //create mesh private float fov; private Vector3 origin; private float startingAngle; private void Start() { mesh = new Mesh(); GetComponent<MeshFilter>().mesh = mesh; fov = 90f; origin = Vector3.zero; } private void LateUpdate() { Vector3 origin = Vector3.zero; int rayCount = 100; float angle = startingAngle; 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; for (int i = 0; i <= rayCount; i++) { Vector3 vertex = origin + GetVectorFromAngle(angle) * viewDistance; RaycastHit2D raycastHit2D = Physics2D.Raycast(origin, GetVectorFromAngle(angle), viewDistance, layerMask); if (raycastHit2D.collider == null) { // did not hit vertex = origin + GetVectorFromAngle(angle) * viewDistance; } else { // object hit vertex = raycastHit2D.point; } vertices[vertexIndex] = vertex; if (i > 0) { triangles[triangleIndex + 0] = 0; triangles[triangleIndex + 1] = vertexIndex - 1; triangles[triangleIndex + 2] = vertexIndex; triangleIndex += 3; } vertexIndex++; angle -= angleIncrease; } mesh.vertices = vertices; mesh.uv = uv; mesh.triangles = triangles; } public void SetOrigin(Vector3 origin) { this.origin = origin; } public void SetAimDirection(Vector3 aimDirection) { startingAngle = GetAngleFromVectorFloat(aimDirection) + fov / 2f; } public static Vector3 GetVectorFromAngle(float angle) { float angleRad = angle * (Mathf.PI / 180f); return new Vector3(Mathf.Cos(angleRad), Mathf.Sin(angleRad)); } public static float GetAngleFromVectorFloat(Vector3 dir) { dir = dir.normalized; float n = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg; if (n < 0) n += 360; return n; } }
PlayerAim脚本
public class PlayerAim : MonoBehaviour { [SerializeField] private FieldOfView fieldOfView; void Update() { Vector3 targetPosition = GetMouseWorldPosition(); Vector3 aimDir = (targetPosition - transform.position).normalized; fieldOfView.SetAimDirection(aimDir); fieldOfView.SetOrigin(transform.position); } public static Vector3 GetMouseWorldPosition() { Vector3 vec = GetMouseWorldPositionWithZ(Input.mousePosition, Camera.main); vec.z = 0f; return vec; } public static Vector3 GetMouseWorldPositionWithZ() { return GetMouseWorldPositionWithZ(Input.mousePosition, Camera.main); } public static Vector3 GetMouseWorldPositionWithZ(Camera worldCamera) { return GetMouseWorldPositionWithZ(Input.mousePosition, worldCamera); } public static Vector3 GetMouseWorldPositionWithZ(Vector3 screenPosition, Camera worldCamera) { Vector3 worldPosition = worldCamera.ScreenToWorldPoint(screenPosition); return worldPosition; } public static Vector3 GetDirToMouse(Vector3 fromPosition) { Vector3 mouseWorldPosition = GetMouseWorldPosition(); return (mouseWorldPosition - fromPosition).normalized; } }
问题原因与修复方案
问题核心
FieldOfView的LateUpdate方法中,你重新定义了一个局部变量Vector3 origin = Vector3.zero;,这会覆盖类的成员变量origin。尽管SetOrigin方法正确更新了类的成员变量,但LateUpdate里的射线检测、顶点计算全用的是这个固定为(0,0)的局部变量,导致射线始终从原点发射,碰撞结果自然不会随玩家位置更新。
修复步骤
删除LateUpdate开头的Vector3 origin = Vector3.zero;这一行,直接使用类的成员变量origin即可。
修改后的LateUpdate方法:
private void LateUpdate() { int rayCount = 100; float angle = startingAngle; 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; for (int i = 0; i <= rayCount; i++) { Vector3 vertex = origin + GetVectorFromAngle(angle) * viewDistance; RaycastHit2D raycastHit2D = Physics2D.Raycast(origin, GetVectorFromAngle(angle), viewDistance, layerMask); if (raycastHit2D.collider == null) { vertex = origin + GetVectorFromAngle(angle) * viewDistance; } else { vertex = raycastHit2D.point; } vertices[vertexIndex] = vertex; if (i > 0) { triangles[triangleIndex + 0] = 0; triangles[triangleIndex + 1] = vertexIndex - 1; triangles[triangleIndex + 2] = vertexIndex; triangleIndex += 3; } vertexIndex++; angle -= angleIncrease; } mesh.vertices = vertices; mesh.uv = uv; mesh.triangles = triangles; }
额外说明
调试时打印的origin是类的成员变量,所以显示的是正确的玩家位置,但实际计算用了局部变量,这就是出现“打印值正确但逻辑异常”矛盾现象的原因。
内容的提问来源于stack exchange,提问作者Avery Gonzaga
相关产品推荐
相关产品推荐

