OneHot功能完善,更改TaySensor探测到Tag的index表示。与之前不通用! 修正PlayMode中的scenePrefabSet未定位错误 修正Raysensor中TagToInt不包含rayTagResult中的-1
183 lines
7.2 KiB
C#
183 lines
7.2 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
/*该scrip用于创建复数条ray于视角内,并探测被ray射到的物体*/
|
||
|
||
public class RaySensors : MonoBehaviour
|
||
{
|
||
[SerializeField] private Camera agentCam;
|
||
[SerializeField] private Camera TPSCam;
|
||
[SerializeField] private Material lineMeterial;
|
||
[SerializeField] private GameObject rayInfoPrefab;
|
||
[SerializeField] private 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 = 7; // >=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[] rayTagResultOneHot;
|
||
public float[] rayDisResult;
|
||
|
||
[System.NonSerialized] public int totalRayNum;
|
||
private string myTag = "";
|
||
private GameObject[] linesOBJ;
|
||
private GameObject[] rayInfoOBJ;
|
||
private LineRenderer[] lineRenderers;
|
||
private RayInfoUI[] rayInfoUIs;
|
||
public List<GameObject> inViewEnemies = new List<GameObject>();
|
||
private List<string> tags = new List<string> { "Wall", "Enemy" };
|
||
private Onehot oneHotTags = new Onehot();
|
||
|
||
private void Start()
|
||
{
|
||
myTag = gameObject.tag;
|
||
totalRayNum = halfOuterRayNum * 2 + focusRayNum;
|
||
rayTagResult = new float[totalRayNum];
|
||
rayDisResult = new float[totalRayNum];
|
||
rayTagResultOneHot = new float[totalRayNum*ObjectTags.Tags.Count];
|
||
linesOBJ = new GameObject[totalRayNum];
|
||
lineRenderers = new LineRenderer[totalRayNum];
|
||
rayInfoOBJ = new GameObject[totalRayNum];
|
||
rayInfoUIs = new RayInfoUI[totalRayNum];
|
||
oneHotTags.Initialize(tags);
|
||
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<LineRenderer>();
|
||
lineRenderers[i] = linesOBJ[i].GetComponent<LineRenderer>();
|
||
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<RayInfoUI>();
|
||
}
|
||
}
|
||
|
||
private void SingleRaycastUpdate(Ray ray,int rayIndex)
|
||
{
|
||
// get Raycast hit infomation and return Tag and distance
|
||
RaycastHit nowHit;
|
||
Color rayColor = Color.gray;
|
||
float lineLength = viewDistance;
|
||
string rayInfoText = "";
|
||
Vector3 rayInfoPosition;
|
||
if (Physics.Raycast(ray, out nowHit, viewDistance)) // 若在viewDistance范围内有碰撞
|
||
{
|
||
// Tag
|
||
string thisTag = nowHit.collider.tag;
|
||
// result update
|
||
rayTagResult[rayIndex] = ObjectTags.TagToInt(thisTag);
|
||
rayDisResult[rayIndex] = nowHit.distance;
|
||
int oneHotIndex = rayIndex * ObjectTags.Tags.Count + ObjectTags.TagToInt(thisTag);
|
||
rayTagResultOneHot[oneHotIndex] = 1f;
|
||
if (rayTagResult[rayIndex] == ObjectTags.TagToInt("Enemy"))
|
||
{
|
||
inViewEnemies.Add(nowHit.transform.gameObject);
|
||
}
|
||
// ingame info update
|
||
lineLength = nowHit.distance;
|
||
rayInfoText = thisTag + "\n" + Convert.ToString(nowHit.distance);
|
||
rayColor = ObjectTags.TagToCololr(thisTag);
|
||
|
||
}
|
||
else // 若在viewDistance范围无碰撞
|
||
{
|
||
// Result update
|
||
// rayTagResultOneHot keep zero
|
||
rayTagResult[rayIndex] = -1;
|
||
rayDisResult[rayIndex] = -1;
|
||
// Info
|
||
rayInfoText = "Empty";
|
||
}
|
||
|
||
// draw Info In Game
|
||
rayInfoPosition = ray.origin + (ray.direction * lineLength);
|
||
if (showInGameRay)
|
||
{
|
||
DrawLine(ray, lineLength, lineRenderers[rayIndex], rayColor);
|
||
}
|
||
else
|
||
{
|
||
TurnOffLine(lineRenderers[rayIndex], rayColor);
|
||
}
|
||
// drawRay in game
|
||
if (showInGameRayInfo) rayInfoUIs[rayIndex].UpdateInfo(rayInfoText, rayInfoPosition, rayColor, TPSCam);
|
||
// Show log
|
||
if (showDebugRay) Debug.DrawRay(ray.origin, ray.direction * viewDistance, rayColor); // drawRay in debug
|
||
// Debug.Log(ray.origin + ray.direction);
|
||
// Debug.Log(thisRayTagResult);
|
||
// Debug.Log(tagToInt(nowHit.collider.thisTag));
|
||
}
|
||
|
||
private void DrawLine(Ray ray, float lineLength, LineRenderer lineRenderer, Color lineColor)
|
||
{
|
||
lineRenderer.startColor = lineColor;
|
||
lineRenderer.endColor = lineColor;
|
||
lineRenderer.startWidth = lineWidth;
|
||
lineRenderer.endWidth = lineWidth;
|
||
lineRenderer.SetPosition(0, ray.origin);
|
||
lineRenderer.SetPosition(1, ray.origin + (ray.direction * lineLength));
|
||
}
|
||
|
||
private void TurnOffLine(LineRenderer lineRenderer, Color lineColor)
|
||
{
|
||
lineRenderer.startColor = lineColor;
|
||
lineRenderer.endColor = lineColor;
|
||
lineRenderer.startWidth = 0f;
|
||
lineRenderer.endWidth = 0f;
|
||
lineRenderer.SetPosition(0, new Vector3(0, 0, 0));
|
||
lineRenderer.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 camPixelHeight = agentCam.pixelHeight;
|
||
inViewEnemies.Clear();
|
||
ClearResult();
|
||
for (int i = 0; i < halfOuterRayNum; i++) // create left outside rays; 0 ~ focusLeftEdge
|
||
{
|
||
Vector3 point = new Vector3(i * focusLEdge / (halfOuterRayNum - 1), camPixelHeight / 2, 0);
|
||
Ray nowRay = agentCam.ScreenPointToRay(point);
|
||
SingleRaycastUpdate(nowRay,i);
|
||
}
|
||
for (int i = 0; i < halfOuterRayNum; i++) // create right outside rays; focusRightEdge ~ MaxPixelHeight
|
||
{
|
||
Vector3 point = new Vector3(focusREdge + (i * focusLEdge / (halfOuterRayNum - 1)), camPixelHeight / 2, 0);
|
||
Ray nowRay = agentCam.ScreenPointToRay(point);
|
||
SingleRaycastUpdate(nowRay, 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)), camPixelHeight / 2, 0);
|
||
Ray nowRay = agentCam.ScreenPointToRay(point);
|
||
SingleRaycastUpdate(nowRay, halfOuterRayNum * 2 + i);
|
||
}
|
||
}
|
||
|
||
private void ClearResult()
|
||
{
|
||
rayTagResult = new float[totalRayNum];
|
||
rayDisResult = new float[totalRayNum];
|
||
rayTagResultOneHot = new float[totalRayNum * ObjectTags.Tags.Count];
|
||
}
|
||
} |