using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraOcclusionDetector : MonoBehaviour { public Transform player; // 主角的Transform public LayerMask obstacleLayer; // 障碍物层,例如:Default, Environment public List objectsToCheck; // 要检测是否被遮挡的物体列表 public List OldhitObject=new List(); // 碰撞体的GameObject public Vector3 Offset; // 偏移量,用于修正碰撞体的位置 public Vector3 OffsetCamera; // 偏移量,用于修正碰撞体的位置 public float minDistance = 1.5f; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { foreach (var obj in objectsToCheck) { bool isOvvluded = IsPlayerOccluded(obj); //Debug.Log(obj.name + "是否被遮挡:" + isOvvluded); if (isOvvluded) { obj.SetActive(false); if (!OldhitObject.Contains(obj)) OldhitObject.Add(obj); } } if (OldhitObject.Count > 0) { // 恢复之前被遮挡但现在可见的物体 for (int i = OldhitObject.Count - 1; i >= 0; i--) { float distance = GetDistanceToPlayer(OldhitObject[i]); //Debug.Log("距离:" + OldhitObject[i] + "距离:" + distance); if (distance > minDistance) { OldhitObject[i].SetActive(true); //OldhitObject.RemoveAt(i); } } } } /// /// 判断是否有物体遮挡了 "摄像机 -> 主角" 的视线 /// /// 被遮挡返回 true,视野清晰返回 false public bool IsPlayerOccluded(GameObject obj) { // 计算从主角指向摄像机的方向 Vector3 _player = player.position + Offset; Vector3 _camera = transform.position + OffsetCamera; Vector3 directionToCamera = _camera - _player; float distance = directionToCamera.magnitude; // 从主角向摄像机发射射线,并渲染射线 //Debug.DrawRay(_player, directionToCamera.normalized * distance, Color.red); // 关键点:从主角向摄像机发射射线 if (Physics.Raycast(player.position, directionToCamera.normalized, out RaycastHit hit, distance, obstacleLayer)) { // 1. 如果射线击中的距离非常近(几乎在主角身上),可能是主角自身的碰撞体,视为无遮挡 // 2. 如果射线击中了非主角物体(距离正常),则是被遮挡了 // 定义一个极小的距离阈值,用于忽略主角自身的碰撞体 float minDistance = 0.1f; //Debug.Log("被遮挡了!击中物体:" + hit.collider.name + ",距离:" + hit.distance); if (hit.distance > minDistance && obj == hit.transform.gameObject) { //Debug.Log("被遮挡了!击中物体:" + hit.collider.name + ",距离:" + hit.distance); //hitObject= hit.transform.gameObject; // 记录碰撞体的GameObject return true; // 视野被遮挡 } } //Debug.Log("视野清晰"); return false; // 视野未被遮挡 } /// /// 返回指定物体到玩家的距离 /// /// 要检测距离的物体 /// 物体到玩家的距离 public float GetDistanceToPlayer(GameObject obj) { Vector3 objPosition = obj.transform.position; Vector3 playerPosition = player.position; return Vector3.Distance(objPosition, playerPosition); } }