Aimbot-PPO/Aimbot-PPO-MultiScene/Assets/Script/InGame/RaySensors.cs
Koha9 885dbb92e9 Add Enemy Change Button
Add Enemy Change Button. Tidy up Unity Script folder.
2022-09-06 23:01:55 +09:00

322 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 ->
//此时RHorizontalLHorizontal的长度巨几把长需要下面操作标准化为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]);
}
*/
}
}