using System; using System.Collections; using System.Collections.Generic; using UnityEngine; /*该scrip用于创建复数条ray于视角内,并探测被ray射到的物体*/ public class RaySensors : MonoBehaviour { public Camera agentCam; public Material lineMeterial; public GameObject rayInfoPrefab; public GameObject agentCanvas; [SerializeField, Range(0, 500)] public float viewDistance = 100; // how long the ray can detect //[SerializeField, Range(0, 1)] public float totalRange = 1f; // Total view range Max = 1 [SerializeField, Range(0, 1)] public float focusRange = 0.15f; // center focus range public int halfOuterRayNum = 3; // >=2 public int focusRayNum = 5; // >= 1 and must be odd num! [Header("InGameLineSetting")] public bool showInGameRay = true; public bool showDebugRay = true; public bool showInGameRayInfo = true; public float lineWidth = 0.05f; [Header("RayCastResult")] public float[] rayTagResult; public float[] rayDisResult; [System.NonSerialized] public int totalRayNum; GameObject[] linesOBJ; GameObject[] rayInfoOBJ; LineRenderer[] lineRenderers; rayInfoUI[] rayInfoUIs; private void Start() { totalRayNum = halfOuterRayNum * 2 + focusRayNum; rayTagResult = new float[totalRayNum]; rayDisResult = new float[totalRayNum]; linesOBJ = new GameObject[totalRayNum]; lineRenderers = new LineRenderer[totalRayNum]; rayInfoOBJ = new GameObject[totalRayNum]; rayInfoUIs = new rayInfoUI[totalRayNum]; for(int i = 0; i < totalRayNum; i++) { linesOBJ[i] = new GameObject(); linesOBJ[i].name = "rayCastLine-" + Convert.ToString(i); linesOBJ[i].transform.parent = agentCam.transform; linesOBJ[i].AddComponent(); lineRenderers[i] = linesOBJ[i].GetComponent(); lineRenderers[i].material = lineMeterial; rayInfoOBJ[i] = (GameObject)Instantiate(rayInfoPrefab); rayInfoOBJ[i].transform.SetParent(agentCanvas.transform,false); rayInfoOBJ[i].name = "rayInfo-" + Convert.ToString(i); rayInfoUIs[i] = rayInfoOBJ[i].GetComponent(); } } static int tagToInt(string tag) { switch (tag) { case "Wall": return 1; case "Enemy": return 2; default: return 0; } } private void singleRaycastUpdate(Ray ray,LineRenderer thisLineRenderer,rayInfoUI thisRayInfoUI, out float rayTagResult, out float rayDisResult) { // get Raycast hit infomation and return Tag and distance RaycastHit thisHit; Color rayColor = Color.cyan; float lineLength = viewDistance; string rayInfoText = ""; Vector3 rayInfoPosition; if (Physics.Raycast(ray, out thisHit, viewDistance)) // 若在viewDistance范围内有碰撞 { rayInfoText = thisHit.collider.tag; rayTagResult = tagToInt(thisHit.collider.tag); rayDisResult = thisHit.distance; lineLength = rayDisResult; rayInfoText += "\n" + Convert.ToString(rayDisResult); //输出log switch (rayTagResult) { case 1:// Wall rayColor = Color.white; break; case 2: // Enemy rayColor = Color.red; break; case -1: // Hit Nothing rayColor = Color.gray; break; default: // default,got wrong rayColor = Color.cyan; break; } } else // 若在viewDistance范围无碰撞 { rayTagResult = -1f; rayDisResult = -1f; //输出log //Debug.Log(0); //Debug.Log(0); } rayInfoPosition = ray.origin + (ray.direction * lineLength); if (showInGameRay) { drawLine(ray, lineLength, thisLineRenderer, rayColor); } else { turnOffLine(thisLineRenderer, rayColor); } // drawRay in game if (showInGameRayInfo) thisRayInfoUI.updateInfo(rayInfoText, rayInfoPosition, rayColor); // Show log if (showDebugRay) Debug.DrawRay(ray.origin, ray.direction * viewDistance, rayColor); // drawRay in debug // Debug.Log(ray.origin + ray.direction); // Debug.Log(rayTagResult); // Debug.Log(tagToInt(thisHit.collider.tag)); } private void drawLine(Ray ray,float lineLength, LineRenderer thisLineRenderer, Color lineColor) { thisLineRenderer.startColor = lineColor; thisLineRenderer.endColor = lineColor; thisLineRenderer.startWidth = lineWidth; thisLineRenderer.endWidth = lineWidth; thisLineRenderer.SetPosition(0, ray.origin); thisLineRenderer.SetPosition(1, ray.origin + (ray.direction * lineLength)); } private void turnOffLine(LineRenderer thisLineRenderer, Color lineColor) { thisLineRenderer.startColor = lineColor; thisLineRenderer.endColor = lineColor; thisLineRenderer.startWidth = 0f; thisLineRenderer.endWidth = 0f; thisLineRenderer.SetPosition(0, new Vector3(0, 0, 0)); thisLineRenderer.SetPosition(1, new Vector3(0, 0, 0)); } public void updateRayInfo() { float focusLEdge = agentCam.pixelWidth * (1 - focusRange) / 2; float focusREdge = agentCam.pixelWidth * (1 + focusRange) / 2; float thisCamPixelHeight = agentCam.pixelHeight; for (int i = 0; i < halfOuterRayNum; i++) // create left outside rays; 0 ~ focusLeftEdge { Vector3 point = new Vector3(i * focusLEdge / (halfOuterRayNum - 1), thisCamPixelHeight / 2, 0); Ray thisRay = agentCam.ScreenPointToRay(point); singleRaycastUpdate(thisRay,lineRenderers[i], rayInfoUIs[i] , out rayTagResult[i], out rayDisResult[i]); } for (int i = 0; i < halfOuterRayNum; i++) // create right outside rays; focusRightEdge ~ MaxPixelHeight { Vector3 point = new Vector3(focusREdge + (i * focusLEdge / (halfOuterRayNum - 1)), thisCamPixelHeight / 2, 0); Ray thisRay = agentCam.ScreenPointToRay(point); singleRaycastUpdate(thisRay, lineRenderers[halfOuterRayNum + i], rayInfoUIs[halfOuterRayNum + i], out rayTagResult[halfOuterRayNum + i], out rayDisResult[halfOuterRayNum + i]); } for (int i = 0; i < focusRayNum; i++) // create center focus rays; focusLeftEdge ~ focusLeftEdge { Vector3 point = new Vector3(focusLEdge + ((i + 1) * (focusREdge - focusLEdge) / (focusRayNum + 1)), thisCamPixelHeight / 2, 0); Ray thisRay = agentCam.ScreenPointToRay(point); singleRaycastUpdate(thisRay, lineRenderers[halfOuterRayNum * 2 + i], rayInfoUIs[halfOuterRayNum * 2 + i], out rayTagResult[halfOuterRayNum*2 + i], out rayDisResult[halfOuterRayNum*2 + i]); } } }