1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
| using UnityEngine;
public class AIPerception : MonoBehaviour { [Header("感知设置")] [Tooltip("视野角度(度)")] [Range(0, 360)] public float viewAngle = 90f;
[Tooltip("视野距离")] public float viewDistance = 10f;
[Tooltip("听觉范围")] public float hearDistance = 5f;
[Header("检测层级")] public LayerMask targetMask;
[Header("可视化颜色")] public Color viewColor = new Color(1, 0.5f, 0, 0.2f); public Color hearColor = new Color(0, 1, 0, 0.1f);
private Vector3[] viewPoints; private int viewPointCount = 20;
private void OnDrawGizmos() { Gizmos.color = hearColor; Gizmos.DrawWireSphere(transform.position, hearDistance);
Gizmos.color = Color.yellow; Gizmos.DrawRay(transform.position, transform.forward * 2); }
private void OnDrawGizmosSelected() {
DrawViewField();
Gizmos.color = hearColor; Gizmos.DrawSphere(transform.position, hearDistance);
UnityEditor.Handles.Label( transform.position + transform.forward * viewDistance, $"<color=yellow>视野: {viewDistance}m</color>" ); }
private void DrawViewField() { Vector3 leftDir = DirFromAngle(-viewAngle / 2, false); Vector3 rightDir = DirFromAngle(viewAngle / 2, false);
Gizmos.color = Color.red; Gizmos.DrawRay(transform.position, leftDir * viewDistance); Gizmos.DrawRay(transform.position, rightDir * viewDistance);
DrawViewSector(); }
private void DrawViewSector() { Gizmos.color = viewColor;
if (viewPoints == null || viewPoints.Length != viewPointCount + 2) { viewPoints = new Vector3[viewPointCount + 2]; }
viewPoints[0] = transform.position;
float stepAngle = viewAngle / viewPointCount; for (int i = 0; i <= viewPointCount; i++) { float angle = -viewAngle / 2 + stepAngle * i; Vector3 dir = DirFromAngle(angle, false); viewPoints[i + 1] = transform.position + dir * viewDistance; }
for (int i = 0; i < viewPoints.Length - 1; i++) { Gizmos.DrawLine(viewPoints[i], viewPoints[i + 1]); } }
private Vector3 DirFromAngle(float angleInDegrees, bool angleIsGlobal) { if (!angleIsGlobal) { angleInDegrees += transform.eulerAngles.y; } return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad), 0, Mathf.Cos(angleInDegrees * Mathf.Deg2Rad)); }
public Transform[] GetVisibleTargets() { Collider[] targetsInViewRadius = Physics.OverlapSphere(transform.position, viewDistance, targetMask); List<Transform> visibleTargets = new List<Transform>();
foreach (Collider target in targetsInViewRadius) { Transform targetTransform = target.transform; Vector3 dirToTarget = (targetTransform.position - transform.position).normalized;
if (Vector3.Angle(transform.forward, dirToTarget) < viewAngle / 2) { float distanceToTarget = Vector3.Distance(transform.position, targetTransform.position);
if (!Physics.Linecast(transform.position, targetTransform.position, ~targetMask)) { visibleTargets.Add(targetTransform); } } }
return visibleTargets.ToArray(); } }
|