322 lines
15 KiB
C#
322 lines
15 KiB
C#
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
/*该scrip用于创建复数条ray于视角内,并探测被ray射到的物体*/
|
|||
|
|
|||
|
|
|||
|
public class RaySensors : MonoBehaviour
|
|||
|
{
|
|||
|
|
|||
|
public Camera agentCam;
|
|||
|
public GameObject myself;
|
|||
|
public int rayNum = 6;
|
|||
|
public string EnemyTagName;
|
|||
|
public string WallTagName;
|
|||
|
public float viewDistance = 100; // how long the ray can detect
|
|||
|
public float Damage = 50; // damage to enemy
|
|||
|
public float attentionRange = 1f; //注意力范围,1为最大
|
|||
|
public float MaxDistance = 9999999999f;
|
|||
|
public float EnemyWidthRedundancy = 0.01f; //为了确保Ray可以击中Enemy,用于缩小EnemyWidth的长度
|
|||
|
//public List<string> tagNames = new List<string>();
|
|||
|
public static int allEnemyNum = 0;//All Enemy Num
|
|||
|
public static float[] focusEnemyInfo = new float[3];
|
|||
|
public static float[] rayTagResult; // Array to save Tag Result
|
|||
|
public static float[] rayDisResult; // Array to save Distance Result
|
|||
|
public static List<float> enemyLDisList = new List<float>();// All Enemy Lside Distances
|
|||
|
public static List<float> enemyRDisList = new List<float>();// All Enemy Rside Distances
|
|||
|
|
|||
|
|
|||
|
|
|||
|
public bool showEnemySensor = true;
|
|||
|
public bool showEyeSensor = true;
|
|||
|
|
|||
|
|
|||
|
static int tagToInt(string tag)
|
|||
|
{
|
|||
|
switch (tag)
|
|||
|
{
|
|||
|
case "Wall":
|
|||
|
return 1;
|
|||
|
case "Enemy":
|
|||
|
return 2;
|
|||
|
default:
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// 敌人Ray探测处理
|
|||
|
// 返回
|
|||
|
(int, List<float>, List<float>, float[]) enemySensorRay(GameObject myself, Camera agentCam, float attentionRange)
|
|||
|
{
|
|||
|
List<float> thisLDistanceList = new List<float>();
|
|||
|
List<float> thisRDistanceList = new List<float>();
|
|||
|
|
|||
|
GameObject[] EnemyGameObjs;
|
|||
|
EnemyGameObjs = GameObject.FindGameObjectsWithTag("Enemy");
|
|||
|
int EnemyIndex = 0;
|
|||
|
float MinEnemyDis = MaxDistance+1.0f;
|
|||
|
int MinEnemyIndex = 0;
|
|||
|
float[] MinEnemyInfo = new float[3];
|
|||
|
|
|||
|
//遍历所有Enemy
|
|||
|
foreach (GameObject EnemyObj in EnemyGameObjs)
|
|||
|
{
|
|||
|
Vector3 thisEnemyPosition = EnemyObj.transform.position;
|
|||
|
Vector3 thisEnemyScale = EnemyObj.transform.localScale;
|
|||
|
Vector3 MyselfPosition = myself.transform.position;
|
|||
|
float thisEnemyWidth = (float)(thisEnemyScale.x / 2) - EnemyWidthRedundancy;
|
|||
|
float thisEnemyDistance = Vector3.Distance(MyselfPosition, thisEnemyPosition);
|
|||
|
|
|||
|
//探测到Agent为自己时的处理
|
|||
|
if (thisEnemyPosition == MyselfPosition)
|
|||
|
{
|
|||
|
//Debug.Log("OH It's me");
|
|||
|
thisLDistanceList.Add(MaxDistance);
|
|||
|
thisRDistanceList.Add(MaxDistance);
|
|||
|
}
|
|||
|
//非己Agent处理
|
|||
|
else
|
|||
|
{
|
|||
|
EnemyIndex += 1;
|
|||
|
Vector3 Vertical = new Vector3(0, 100, 0);//垂直向上的向量
|
|||
|
Vector3 EnemytoMe = MyselfPosition - thisEnemyPosition;//Enemy和自机连线,指向自机的向量
|
|||
|
Vector3 LHorizontal = Vector3.Cross(Vertical, EnemytoMe);// 垂直于EnemytoMe与Vertical向量所组成的面的,且指向<-左侧的小向量<- Enemy
|
|||
|
Vector3 RHorizontal = Vector3.Cross(EnemytoMe, Vertical);// 垂直于EnemytoMe与Vertical向量所组成的面的,且指向->右侧的小向量Enemy ->
|
|||
|
//此时RHorizontal,LHorizontal的长度巨几把长,需要下面操作标准化为1/2Enemy宽度
|
|||
|
float standaedization = (float)thisEnemyWidth / Vector3.Distance(thisEnemyPosition, RHorizontal);//计算需要缩小的比例
|
|||
|
RHorizontal *= standaedization;//应用缩小比例,标准化完成
|
|||
|
LHorizontal *= standaedization;//应用缩小比例,标准化完成
|
|||
|
Vector3 LMetoEnemy = LHorizontal - EnemytoMe;//自机与左侧边界连线Me<- Enemy
|
|||
|
Vector3 RMetoEnemy = RHorizontal - EnemytoMe;//自机与右侧边界连线Enemy ->Me
|
|||
|
Vector3 L0toEnemy = LHorizontal + thisEnemyPosition;// Enemy左侧绝对坐标
|
|||
|
Vector3 R0toEnemy = RHorizontal + thisEnemyPosition;// Enemy右侧绝对坐标
|
|||
|
float LMetoEnemyDist = Vector3.Distance(MyselfPosition, L0toEnemy);
|
|||
|
float RMetoEnemyDist = Vector3.Distance(MyselfPosition, R0toEnemy);
|
|||
|
Vector3 LEnemyInView = agentCam.WorldToViewportPoint(L0toEnemy);//Enemy左侧于视角中位置
|
|||
|
Vector3 REnemyInView = agentCam.WorldToViewportPoint(R0toEnemy);//Enemy右侧于视角中位置
|
|||
|
//Debug连线,颜色遵循飞机航行灯基本使用规则,左红右绿尾翼白。
|
|||
|
//Debug.DrawRay(thisEnemyPosition, EnemytoMe, Color.white);//Enemy和自机连线,指向自机的向量
|
|||
|
//Debug.DrawRay(thisEnemyPosition, Vertical, Color.white);//垂直向上的向量
|
|||
|
//Debug.DrawRay(thisEnemyPosition, LHorizontal, Color.red);// 垂直于Vc与Vertical向量所组成的面的,且指向<-左侧的小向量<- Enemy
|
|||
|
//Debug.DrawRay(thisEnemyPosition, RHorizontal, Color.green);// 垂直于Vc与Vertical向量所组成的面的,且指向->右侧的小向量Enemy ->
|
|||
|
//Debug.DrawRay(MyselfPosition, LMetoEnemy, Color.red);//自机与左侧边界连线<- Enemy
|
|||
|
//Debug.DrawRay(MyselfPosition, RMetoEnemy, Color.green);//自机与右侧边界连线Enemy ->
|
|||
|
//Debug.Log("EnemyObj" + EnemyIndex + "Position:" + thisEnemyPosition);
|
|||
|
|
|||
|
|
|||
|
//左侧于可见范围内--<--<--<--<--<--<--<--<--<--<--<--<--<--<
|
|||
|
if (LEnemyInView.x >= (thisEnemyWidth - attentionRange / 2) && LEnemyInView.x <= (thisEnemyWidth + attentionRange / 2) && LEnemyInView.z > 0)
|
|||
|
{
|
|||
|
//射出Raycast
|
|||
|
Ray LRay = new Ray(MyselfPosition, LMetoEnemy);
|
|||
|
RaycastHit LHit;
|
|||
|
if (showEnemySensor)
|
|||
|
{
|
|||
|
Debug.DrawRay(LRay.origin, LRay.direction * LMetoEnemyDist, Color.white);//自机与左侧边界连线<- Enemy
|
|||
|
}
|
|||
|
//Ray Hit Something
|
|||
|
if (Physics.Raycast(MyselfPosition, LMetoEnemy, out LHit, LMetoEnemyDist))
|
|||
|
{
|
|||
|
//Ray Hit Enemy
|
|||
|
//并且当射线射到的Enemy的距离与当前判断Enemy的距离差小于该Enemy半径时
|
|||
|
//既该射线所射到的Enemy为当前Enemy而不是别的时
|
|||
|
if (LHit.collider.tag == EnemyTagName && System.Math.Abs(LHit.distance - thisEnemyDistance) <= thisEnemyWidth)
|
|||
|
{
|
|||
|
if (showEnemySensor)
|
|||
|
{
|
|||
|
Debug.DrawRay(LRay.origin, LRay.direction * LHit.distance, Color.red);//自机与所击中物体的连线
|
|||
|
}
|
|||
|
thisLDistanceList.Add(LHit.distance);
|
|||
|
//Debug.Log("Hit Tag = " + LHit.collider.tag);
|
|||
|
//Debug.Log(LDistance[EnemyIndex-1]);
|
|||
|
//Debug.Log("ADD_LIST_ENEMYL");
|
|||
|
}
|
|||
|
//当射线所hit的不是enemy或hit的enemy不是当前所判断的enemy
|
|||
|
else
|
|||
|
{
|
|||
|
if (showEnemySensor)
|
|||
|
{
|
|||
|
Debug.DrawRay(LRay.origin, LRay.direction * LHit.distance, Color.cyan);//自机与所击中物体的连线
|
|||
|
}
|
|||
|
thisLDistanceList.Add(MaxDistance);
|
|||
|
//Debug.LogWarning("Hit Tag = " + LHit.collider.tag);
|
|||
|
//Debug.LogWarning(LDistance[EnemyIndex-1]);
|
|||
|
//Debug.Log("ADD_LIST_ENEMYL");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
thisLDistanceList.Add(MaxDistance);
|
|||
|
Debug.LogError("LRAY HIT NOTHING, Check Code!");
|
|||
|
}
|
|||
|
}
|
|||
|
//左侧不在可见范围内时--<--<--<--<--<--<--<--<--<--<--<--<--<--<
|
|||
|
else
|
|||
|
{
|
|||
|
thisLDistanceList.Add(MaxDistance);
|
|||
|
//Debug.LogError("NoVisual");
|
|||
|
//Debug.LogError(LDistance[EnemyIndex-1]);
|
|||
|
//Debug.Log("ADD_LIST_ENEMYL_ELSE");
|
|||
|
}
|
|||
|
|
|||
|
//右侧于可见范围内-->-->-->-->-->-->-->-->-->-->-->-->-->-->
|
|||
|
if (REnemyInView.x >= (thisEnemyWidth - attentionRange / 2) && REnemyInView.x <= (thisEnemyWidth + attentionRange / 2) && REnemyInView.z > 0)
|
|||
|
{
|
|||
|
//射出Raycast
|
|||
|
Ray RRay = new Ray(MyselfPosition, RMetoEnemy);
|
|||
|
RaycastHit RHit;
|
|||
|
if (showEnemySensor)
|
|||
|
{
|
|||
|
Debug.DrawRay(RRay.origin, RRay.direction * RMetoEnemyDist, Color.white);//自机与左侧边界连线<- Enemy
|
|||
|
}
|
|||
|
//Ray Hit Something
|
|||
|
if (Physics.Raycast(MyselfPosition, RMetoEnemy, out RHit, RMetoEnemyDist))
|
|||
|
{
|
|||
|
//Ray Hit Enemy
|
|||
|
//并且当射线射到的Enemy的距离与当前判断Enemy的距离差小于该Enemy半径时
|
|||
|
//既该射线所射到的Enemy为当前Enemy而不是别的时
|
|||
|
if (RHit.collider.tag == EnemyTagName && System.Math.Abs(RHit.distance - thisEnemyDistance) <= thisEnemyWidth)
|
|||
|
{
|
|||
|
if (showEnemySensor)
|
|||
|
{
|
|||
|
Debug.DrawRay(RRay.origin, RRay.direction * RHit.distance, Color.red);//自机与所击中物体的连线
|
|||
|
}
|
|||
|
thisRDistanceList.Add(RHit.distance);
|
|||
|
//Debug.Log("Hit Tag = " + LHit.collider.tag);
|
|||
|
//Debug.Log(LDistance[EnemyIndex-1]);
|
|||
|
//Debug.Log("ADD_LIST_ENEMYR");
|
|||
|
}
|
|||
|
//当射线所hit的不是enemy或hit的enemy不是当前所判断的enemy
|
|||
|
else
|
|||
|
{
|
|||
|
if (showEnemySensor)
|
|||
|
{
|
|||
|
Debug.DrawRay(RRay.origin, RRay.direction * RHit.distance, Color.cyan);//自机与所击中物体的连线
|
|||
|
}
|
|||
|
thisRDistanceList.Add(MaxDistance);
|
|||
|
//Debug.LogWarning("Hit Tag = " + LHit.collider.tag);
|
|||
|
//Debug.LogWarning(LDistance[EnemyIndex-1]);
|
|||
|
//Debug.Log("ADD_LIST_ENEMYR");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
thisLDistanceList.Add(MaxDistance);
|
|||
|
Debug.LogError("RRAY HIT NOTHING, Check Code!");
|
|||
|
}
|
|||
|
}
|
|||
|
//右侧不在可见范围内时-->-->-->-->-->-->-->-->-->-->-->-->-->-->
|
|||
|
else
|
|||
|
{
|
|||
|
thisRDistanceList.Add(MaxDistance);
|
|||
|
//Debug.LogError("NoVisual");
|
|||
|
//Debug.LogError(LDistance[EnemyIndex-1]);
|
|||
|
//Debug.Log("ADD_LIST_ENEMYR_ELSE");
|
|||
|
}
|
|||
|
}
|
|||
|
//Debug.LogWarning("EnemyIndex" + EnemyIndex);
|
|||
|
//Debug.LogWarning(thisLDistanceList.Count);
|
|||
|
//Debug.LogWarning(MinEnemyIndex);
|
|||
|
//Debug.Log("thisLDistanceList" + thisLDistanceList.Count);
|
|||
|
//Debug.Log("thisRDistanceList" + thisRDistanceList.Count);
|
|||
|
|
|||
|
//检查最近Enemy
|
|||
|
if (System.Math.Min(thisLDistanceList[EnemyIndex], thisRDistanceList[EnemyIndex]) < MinEnemyDis)
|
|||
|
{
|
|||
|
//Debug.Log("EnemyIndex" + EnemyIndex);
|
|||
|
MinEnemyDis = System.Math.Min(thisLDistanceList[EnemyIndex], thisRDistanceList[EnemyIndex]);
|
|||
|
MinEnemyIndex = EnemyIndex;
|
|||
|
}
|
|||
|
}
|
|||
|
// 获取最近敌人的准确位置信息
|
|||
|
MinEnemyInfo[0] = (float)MinEnemyIndex;
|
|||
|
if(MinEnemyInfo[0] <= 0)
|
|||
|
{
|
|||
|
MinEnemyInfo[1] = MaxDistance;
|
|||
|
MinEnemyInfo[2] = MaxDistance;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MinEnemyInfo[1] = EnemyGameObjs[MinEnemyIndex].transform.position.x;
|
|||
|
MinEnemyInfo[2] = EnemyGameObjs[MinEnemyIndex].transform.position.z;
|
|||
|
}
|
|||
|
return (EnemyIndex, thisLDistanceList, thisRDistanceList,MinEnemyInfo);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// 全局Ray探测处理
|
|||
|
(float[], float[]) eyeSensorRay(int rayNum, Camera agentCam, float viewDistance)
|
|||
|
{
|
|||
|
//初始化result Array
|
|||
|
float[] thisRayTagResult = new float[rayNum];
|
|||
|
float[] thisRayDisResult = new float[rayNum];
|
|||
|
|
|||
|
//于视角范围内一帧射出rayNum条射线
|
|||
|
for (int a = 0; a <= rayNum - 1; a = a + 1)
|
|||
|
{
|
|||
|
//射线射出
|
|||
|
Vector3 point = new Vector3(a * agentCam.pixelWidth / (rayNum - 1), agentCam.pixelHeight / 2, 0);//发射位置
|
|||
|
Ray ray = agentCam.ScreenPointToRay(point);
|
|||
|
RaycastHit hit;
|
|||
|
if (showEyeSensor)
|
|||
|
{
|
|||
|
Debug.DrawRay(ray.origin, ray.direction * viewDistance, Color.black);
|
|||
|
}
|
|||
|
//若在viewDistance范围内有碰撞
|
|||
|
if (Physics.Raycast(ray, out hit, viewDistance))
|
|||
|
{
|
|||
|
thisRayTagResult[a] = tagToInt(hit.collider.tag);
|
|||
|
thisRayDisResult[a] = hit.distance;
|
|||
|
if (showEyeSensor)
|
|||
|
{
|
|||
|
Debug.DrawRay(ray.origin, ray.direction * hit.distance, Color.yellow);
|
|||
|
}
|
|||
|
//输出log
|
|||
|
//Debug.Log(rayTagResult[a]);
|
|||
|
//Debug.Log(tagToInt(hit.collider.tag));
|
|||
|
|
|||
|
}
|
|||
|
//若在viewDistance范围无碰撞
|
|||
|
else
|
|||
|
{
|
|||
|
thisRayTagResult[a] = -1f;
|
|||
|
thisRayDisResult[a] = -1f;
|
|||
|
//输出log
|
|||
|
//Debug.Log(0);
|
|||
|
//Debug.Log(0);
|
|||
|
}
|
|||
|
}
|
|||
|
return (thisRayTagResult, thisRayDisResult);
|
|||
|
}
|
|||
|
|
|||
|
void Start()
|
|||
|
{
|
|||
|
rayTagResult = new float[rayNum];
|
|||
|
rayDisResult = new float[rayNum];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void Update()
|
|||
|
{
|
|||
|
(rayTagResult, rayDisResult) = eyeSensorRay(rayNum, agentCam, viewDistance);
|
|||
|
(allEnemyNum, enemyLDisList, enemyRDisList, focusEnemyInfo) = enemySensorRay(myself, agentCam, attentionRange);
|
|||
|
transform.gameObject.GetComponent<UIController>().updateRemainEnemy(allEnemyNum);
|
|||
|
/*
|
|||
|
Debug.LogWarning("rayNum :" + rayNum);
|
|||
|
for (int i =0;i < rayNum; i++)
|
|||
|
{
|
|||
|
Debug.Log("rayTagResult" + rayTagResult[i] + "rayDisResult"+ rayDisResult[i]);
|
|||
|
}
|
|||
|
Debug.LogWarning("EnemyNum Include Me:" + allEnemyNum);
|
|||
|
for(int i = 0; i < allEnemyNum; i++)
|
|||
|
{
|
|||
|
Debug.Log("enemyLDisList" + enemyLDisList[i] + "enemyRDisList" + enemyRDisList[i]);
|
|||
|
}
|
|||
|
*/
|
|||
|
}
|
|||
|
}
|