上海杨浦大连路地铁站单机版电子沙盘
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

701 lines
24 KiB

using AX.InputSystem;
using AX.MessageSystem;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class AgentController : MonoBehaviour
{
private NavMeshAgent agent;
private NavMeshPath NavMeshPath;
private NavMeshQueryFilter filter;
private Vector3 pointhit;
private GameObject hitObj;
public List<Vector3> corners = new List<Vector3>();
private Vector3 lastPosition;
public bool pathFindEnable;
public bool FixedArmFlag;
private float speed;
private float angularSpeed;
public List<Vector3> TargetPoint = new List<Vector3>();
private float oriStopDis;//初始停止距离
private void Awake()
{
pathFindEnable = true;
agent = GetComponent<NavMeshAgent>();
speed = agent.speed;
angularSpeed = agent.angularSpeed;
MessageDispatcher.AddListener("ReplayEvent", ReplayAgent);
MessageDispatcher.AddListener("ReplayEvent", ReplayCautionAreaTip);
MessageDispatcher.AddListener("ReplayStatusChanged", ReplayStatusChanged);
}
void OnEnable()
{
MessageDispatcher.AddListener("PATH_FINDING_COMMAND", PathFinding);
}
void OnDisable()
{
MessageDispatcher.RemoveListener("PATH_FINDING_COMMAND", PathFinding);
}
void OnDestroy()
{
MessageDispatcher.RemoveListener("PATH_FINDING_COMMAND", PathFinding);
MessageDispatcher.RemoveListener("ReplayEvent", ReplayAgent);
MessageDispatcher.RemoveListener("ReplayEvent", ReplayCautionAreaTip);
MessageDispatcher.RemoveListener("ReplayStatusChanged", ReplayStatusChanged);
}
private void ReplayStatusChanged(IMessage obj)
{
//if (!agent.isOnNavMesh)
// return;
var Status = (ReplayStatus)obj.Data;
switch (Status)
{
case ReplayStatus.normal:
if (agent.isOnNavMesh && agent.isStopped)
{
agent.isStopped = false;
}
break;
case ReplayStatus.pause:
if (agent.isOnNavMesh && !agent.isStopped)
{
agent.isStopped = true;
}
break;
case ReplayStatus.over:
break;
default:
break;
}
}
public void Stop()
{
corners.Clear();
StopAllCoroutines();
agent.SetDestination(this.transform.position);
}
void Start()
{
oriStopDis = GetComponent<NavMeshAgent>().stoppingDistance;
NavMeshPath = new NavMeshPath();
filter = new NavMeshQueryFilter
{
agentTypeID = agent.agentTypeID,
areaMask = agent.areaMask
};
if (GetComponent<TruckMessages>())
{
NavMesh.CalculatePath(transform.position, transform.position, filter, NavMeshPath);
Vector3[] b = NavMeshPath.corners;
if (b.Length < 1)
{
agent.enabled = false;
}
else
{
agent.enabled = true;
}
}
}
//check for mouse input
void Update()
{
}
IEnumerator ReplayEventWaitPosition(Vector3 pos)
{
yield return new WaitForEndOfFrame();
agent.SetDestination(pos);
}
private void ReplayAgent(IMessage obj)
{
var eventData = (EventData)obj.Data;
if (eventData.eventType == RecordEventType.Agent)
{
var data = JsonUtility.FromJson<AgentRecordData>(eventData.json);
if (data.GameId == GetComponent<CloneGameObjInfo>().GameObjID)
{
//MessageDispatcher.AddListener("ReplayStatusChanged", ReplayStatusChanged);
ReplayManager_ChangeReplaySpeed(GlobalVariable.ReplaySpeed);
ReplayManager.ChangeReplaySpeed += ReplayManager_ChangeReplaySpeed;
if (agent && agent.isOnNavMesh)
{
agent.SetDestination(data.TargetPoint);
}
//else
//{
// StartCoroutine(ReplayEventWaitPosition(data.TargetPoint));
// }
}
}
}
private void ReplayManager_ChangeReplaySpeed(int obj)
{
if (agent)
{
agent.speed = speed * GlobalVariable.ReplaySpeed;
agent.angularSpeed = angularSpeed * GlobalVariable.ReplaySpeed;
}
}
private void PathFinding(IMessage obj)
{
if (SelectedObjs.selectedCharacters.Contains(gameObject) || SelectedObjs.selectedObj == gameObject)
{
if (pathFindEnable && !FixedArmFlag)
{
var data = (PathFindingCmdArgs)obj.Data;
pointhit = data.hitPoint;
StopAllCoroutines();
corners.Clear();
bool flag = setPathCorners(transform.position, pointhit, corners);
if (flag)
{
// pointerObj.transform.position = pointhit;
hitObj = EntitiesManager.Instance.GetEntityByID(data.gameObjID);
//setFloorMessage(hitObj.transform);
removeNoMainCorners(corners);
StartCoroutine(GoToDestination());
var objinfo = GetComponent<BaseGameObjInfo>();
//if (objinfo.gameObjType != CloneObjType.fireman && objinfo.gameObjType != CloneObjType.ObligationFireman)
//{
// MessageDispatcher.SendMessage(GetComponent<BaseGameObjInfo>().GameObjID, "SetpathIndex");
//}
if (tag == "Player")
{
//先判断:是否进入警戒区
// checkEnterCautionArea(pointhit);
FireManMessage mess = GetComponent<FireManMessage>();
//GetComponent<XiaoFangYuanDrawLine>().setLine();
if (mess.workType == FireManSkills.LayLifeSavingFlarePath ||
mess.workType == FireManSkills.LayWaterHose ||
mess.workType == FireManSkills.SprayFoam ||
mess.workType == FireManSkills.SprayWater ||
mess.workType == FireManSkills.Decontamination)
{
GetComponent<XiaoFangYuanDrawLine>().setPath(corners.ToArray());
}
}
}
else
ResourceLoadWindow.Instance.LoadTextHintWindow("不能抵达", 1f);
}
else
{
ResourceLoadWindow.Instance.LoadTextHintWindow("不能移动", 1f);
}
}
}
public static event Func<Vector3, IntData, IntData> checkCautionAreaEntering;
private void checkEnterCautionArea(Vector3 pointhit)
{
IntData data = new IntData(0);
if (checkCautionAreaEntering != null)
data = checkCautionAreaEntering(pointhit, data);
if (data.value > 0)
{
string warning = "";
//即将进入警戒区,判断是否按要求装备
Bag bag = GetComponent<Bag>();
bool detectEquiped = false; //是否携带侦测类仪器
bool breathEquiped = false; //是否装备空呼
bool clothEquiped = false; //是否装备防化服
bool phoneEquiped = false; //是否装备对讲机
foreach (Equip equip in bag.EquipList)
{
if (equip.Name == "有毒气体探测仪")
{
detectEquiped = true;
}
if (equip.Name == "正压式空气呼吸器")
{
breathEquiped = true;
}
if (equip.Name.Contains("防化服"))
{
clothEquiped = true;
}
if (equip.Name.Contains("通信"))
{
phoneEquiped = true;
}
}
if (detectEquiped && breathEquiped && clothEquiped && phoneEquiped)
{
//如果按要求装备,就不提示
return;
}
else
{
warning += "即将进入警戒区,但未按要求装备:\n";
if (!detectEquiped)
warning += "有毒气体探测仪";
if (!breathEquiped)
warning += " 空气呼吸器";
if (!clothEquiped)
warning += " 防化服";
if (!phoneEquiped)
warning += " 通信设备";
ResourceLoadWindow.Instance.LoadTipWindow(warning, () => { }, null);
AddCautionAreaTipEvent(warning);
}
}
}
public bool CheckHasPath(Vector3 pointhit)
{
StopAllCoroutines();
corners.Clear();
bool flag = setPathCorners(transform.position, pointhit, corners);
return flag;
}
private void AddCautionAreaTipEvent(string warning)
{
if (ReplaySetting.PlayStatus == PlayStatus.isEditor && RecordManager.Instance.recordStatus == RecordStatus.normal)
{
var eventData = new EventData();
eventData.time = RecordManager.Instance.RecordTimer;
eventData.cloneObjType = GetComponent<CloneGameObjInfo>().gameObjType;
eventData.eventType = RecordEventType.CautionAreaTip;
CautionAreaTipData data = new CautionAreaTipData();
data.gameObjID = GetComponent<CloneGameObjInfo>().gameObjID;
data.warning = warning;
eventData.json = JsonUtility.ToJson(data);
RecordManager.Instance.jsonData.eventDataList.Add(eventData);
}
}
private void ReplayCautionAreaTip(IMessage obj)
{
var eventData = (EventData)obj.Data;
if (eventData.eventType == RecordEventType.CautionAreaTip)
{
CautionAreaTipData data = JsonUtility.FromJson<CautionAreaTipData>(eventData.json);
if (data.gameObjID == GetComponent<CloneGameObjInfo>().gameObjID)
{
ResourceLoadWindow.Instance.LoadTextHintWindow(data.warning, Mathf.Clamp(2 / GlobalVariable.ReplaySpeed, 1, 2));
}
}
}
bool ArriveFlag(Vector3 transformpos, Vector3 pointhit)
{
// StopAllCoroutines();
// corners.Clear();
return setPathCorners(transformpos, pointhit, corners);
}
public void AutoPathFinding(List<Vector3> TargetPoint)
{
if (pathFindEnable && !FixedArmFlag)
{
StopAllCoroutines();
corners.Clear();
var templeteCorners = new List<Vector3>();
for (int i = 0; i < TargetPoint.Count; i++)
{
if (i == 0)
{
templeteCorners.Clear();
bool flag = setPathCorners(transform.position, TargetPoint[i], templeteCorners);
if (flag)
{
foreach (Vector3 point in templeteCorners)
{
corners.Add(point);
}
}
else
{
ResourceLoadWindow.Instance.LoadTextHintWindow("不能抵达", 2f);
return;
}
}
else
{
templeteCorners.Clear();
bool flag = setPathCorners(TargetPoint[i - 1], TargetPoint[i], templeteCorners);
if (flag)
{
foreach (Vector3 point in templeteCorners)
{
corners.Add(point);
}
}
else
{
ResourceLoadWindow.Instance.LoadTextHintWindow("不能抵达", 2f);
return;
}
}
}
//removeNoMainCorners(corners);
StartCoroutine(GoToDestination());
}
}
IEnumerator PathFinding(List<Vector3> TargetPoint)
{
this.TargetPoint = TargetPoint;
StopAllCoroutines();
corners.Clear();
int a = 0;
while (a < TargetPoint.Count)
{
if (a == 0)
ArriveFlag(transform.position, TargetPoint[a]);
else
ArriveFlag(TargetPoint[a - 1], TargetPoint[a]);
//if (ArriveFlag(transform.position, TargetPoint[a]))
// StartCoroutine(GoToDestination());
//// ArriveFlag(transform.position, TargetPoint[a]);
a++;
}
if (a == TargetPoint.Count)
{
removeNoMainCorners(corners);
StartCoroutine(GoToDestination());
yield return true;
}
}
public static bool InNavMesh(Vector3 tagent)
{
NavMeshHit hit;
NavMeshQueryFilter filter = new NavMeshQueryFilter();
var agent = GameObject.Find("CarAgent").GetComponent<NavMeshAgent>();
filter.agentTypeID = agent.agentTypeID;
filter.areaMask = agent.areaMask;
var hasHit = NavMesh.SamplePosition(tagent, out hit, 1, filter);
return hasHit;
}
public static List<Vector3> LiSan(Vector3 center, int count, Vector3 size)
{
List<Vector3> list = new List<Vector3>();
list.Add(center);//先加入目的地
int num = 1;
while (list.Count < count)
{
var tagent = new Vector3(center.x, center.y, center.z + size.z * num);
if (InNavMesh(tagent))
list.Add(tagent);
else
{
if (Vector3.Distance(center, tagent) >= (count + 3) * size.z)
break;
}
num++;
}
num = 1;
while (list.Count < count)
{
var tagent = new Vector3(center.x, center.y, center.z - size.z * num);
if (InNavMesh(tagent))
list.Add(tagent);
else
{
if (Vector3.Distance(center, tagent) >= (count + 3) * size.z)
break;
}
num++;
}
num = 1;
while (list.Count < count)
{
var tagent = new Vector3(center.x + size.x * num, center.y, center.z);
if (InNavMesh(tagent))
list.Add(tagent);
else
{
if (Vector3.Distance(center, tagent) >= (count + 3) * size.x)
break;
}
num++;
}
num = 1;
while (list.Count < count)
{
var tagent = new Vector3(center.x - size.x * num, center.y, center.z);
if (InNavMesh(tagent))
list.Add(tagent);
else
{
if (Vector3.Distance(center, tagent) >= (count + 3) * size.x)
break;
}
num++;
}
//找到的点不够,添加最后重复点
if (list.Count < count)
{
var point = list[list.Count - 1];
for (int i = list.Count; i < count; i++)
{
var tagent = point;
list.Add(tagent);
}
}
return list;
}
public static bool InNavMesh(Vector3 center, Vector3 tagent)
{
NavMeshHit hit;
NavMeshQueryFilter filter = new NavMeshQueryFilter();
filter.agentTypeID = 0;
filter.areaMask = 1;
NavMesh.Raycast(center, tagent, out hit, filter);
return hit.mask == filter.areaMask;
}
EventData eventData;
//loops over path positions, sets the
//current target destination of this agent
IEnumerator GoToDestination()
{
int i = 1;
while (i < corners.Count)
{
NavMeshPath NavMeshPath = new NavMeshPath();
NavMesh.CalculatePath(transform.position, corners[i], filter, NavMeshPath);
if (RecordEvent.IsRecord())
{
/* eventData = RecordEvent.CreateLinearEventData(CloneObjType.None, RecordEventType.LinearData);*///GetComponent<BaseGameObjInfo>().gameObjType
AgentRecordData AgentRecordData = new AgentRecordData
{
TargetPoint = corners[i],
GameId = GetComponent<BaseGameObjInfo>().GameObjID
};
//RecordEvent.AddLinearEventData(eventData, GetComponent<BaseGameObjInfo>().GameObjID, JsonUtility.ToJson(AgentRecordData));
eventData = RecordEvent.AddEventData(CloneObjType.None, RecordEventType.Agent, JsonUtility.ToJson(AgentRecordData));
}
agent.SetDestination(corners[i]);
while (agent.pathPending)
yield return null;
//wait until we reached this position
float remain = Vector3.Distance(transform.position, corners[i]);
while (remain == Mathf.Infinity || remain - agent.stoppingDistance > float.Epsilon)
{
remain = Vector3.Distance(transform.position, corners[i]);
if (RecordEvent.IsRecord())//正在寻路开记录节点
if (eventData == null)
{
AgentRecordData AgentRecordData = new AgentRecordData
{
TargetPoint = corners[i],
GameId = GetComponent<BaseGameObjInfo>().GameObjID
};
eventData = RecordEvent.AddEventData(CloneObjType.None, RecordEventType.Agent, JsonUtility.ToJson(AgentRecordData));
}
//if (RecordEvent.IsRecordPause())//记录暂定 停止寻路
//{
// agent.isStopped = true;
//}
//else
//{
// if (RecordEvent.IsRecord() && agent.isStopped)
// {
// agent.isStopped = false;
// eventData = null;
// }
//}
yield return null;
}
if (eventData != null)
{
eventData = null;
}
var objinfo = GetComponent<BaseGameObjInfo>();
if (objinfo.gameObjType == CloneObjType.FireMan)
{
setFloorMessage();
}
else if (objinfo.GetComponent<TruckMessages>())
{
setFloorMessage(false);
}
i++;
}
if (i == corners.Count)
{
corners.Clear();
yield return true;
}
}
private void setFloorMessage(bool isFireman = true)
{
//璁剧疆瀵昏矾瀵硅薄妤煎眰灞炴€?
Vector3 adPos2 = transform.position;
Ray ray = new Ray(adPos2 + Vector3.up, Vector3.down);
RaycastHit hit = new RaycastHit();
if (isFireman)
{
if (Physics.Raycast(ray, out hit, 1000, LayerMask.GetMask("ManRode", "CarRode")))
{
if (hit.transform.gameObject.GetComponent<CloneGameObjInfo>())
{
CloneGameObjInfo msg = GetComponent<CloneGameObjInfo>();
CloneGameObjInfo hitinfo = hit.transform.gameObject.GetComponent<CloneGameObjInfo>();
msg.buildNum = hitinfo.buildNum;
msg.floorNum = hitinfo.floorNum;
msg.interlayerNum = hitinfo.interlayerNum;
//msg.inOutType = hitinfo.inOutType;
if (!SelectedObjs.selectedCharacters.Contains(gameObject))
{
msg.UpdateFloorEnabled(GlobalVariable.CurrentFloor);
}
return;
}
}
}
else
{
if (Physics.Raycast(ray, out hit, LayerMask.NameToLayer("CarRoad")))
{
if (hit.transform.gameObject.GetComponent<CloneGameObjInfo>())
{
CloneGameObjInfo msg = GetComponent<CloneGameObjInfo>();
CloneGameObjInfo hitinfo = hit.transform.gameObject.GetComponent<CloneGameObjInfo>();
msg.buildNum = hitinfo.buildNum;
msg.floorNum = hitinfo.floorNum;
msg.interlayerNum = hitinfo.interlayerNum;
return;
}
}
}
}
bool setPathCorners(Vector3 sourcePosition, Vector3 targetPosition, List<Vector3> corners)
{
NavMeshPath NavMeshPath = new NavMeshPath();
NavMesh.CalculatePath(sourcePosition, targetPosition, filter, NavMeshPath);
Vector3[] b = NavMeshPath.corners;
if (b.Length == 1)
{
//Debug.Log("断裂");
return false;
}
if (NavMeshPath.status == NavMeshPathStatus.PathComplete)
{
//Debug.Log("PathComplete");
foreach (Vector3 corner in b)
{
if (!corners.Contains(corner))
{
corners.Add(corner);
}
}
return true;
}
else if (NavMeshPath.status == NavMeshPathStatus.PathPartial)
{
if (Vector3.Distance(b[b.Length - 1], lastPosition) == 0)
{
//Debug.Log("(" + sourcePosition.x + "," + sourcePosition.y + "," + sourcePosition.z + ")、(" + lastPosition.x + "," + lastPosition.y + "," + lastPosition.z + ")");
//Debug.Log("进入死循环");
return false;
}
foreach (Vector3 corner in b)
{
if (!corners.Contains(corner))
{
corners.Add(corner);
}
}
lastPosition = sourcePosition;
return setPathCorners(b[b.Length - 1], targetPosition, corners);
}
else if (NavMeshPath.status == NavMeshPathStatus.PathInvalid)
{
return false;
}
else
{
return false;
}
}
void removeNoMainCorners(List<Vector3> corners)
{
for (int i = 0; i < corners.Count - 1; i++)
{
for (int k = corners.Count - 2; k > i; k--)
{
float distance = Vector3.Distance(corners[i], corners[k]);//计算两点的距离
if (distance < 5)
{
for (int j = k; j > i; j--)
{
corners.RemoveAt(j);
}
break;
}
}
}
}
public void MuitiNav(List<Vector3> MuitiPoints,int dis)
{
List<Vector3> posints = new List<Vector3>();
for (int i = 0; i < MuitiPoints.Count; i++)
{
posints.Add(MuitiPoints[i]);
}
GetComponent<BoxCollider>().enabled = false;
this.StopAllCoroutines();
corners.Clear();
StartCoroutine(GoToMuitiPoints(posints));
}
IEnumerator GoToMuitiPoints(List<Vector3> posints)
{
int i = 0;
while (i < posints.Count)
{
pointhit = posints[i];
bool flag = setPathCorners(transform.position, pointhit, corners);
StartCoroutine(GoToDestination());
//MessageDispatcher.SendMessage("PATH_FINDING_COMMAND", arg);
//while循环作用:等到达第i个侦察路径点后,再寻路至i++个侦察路径点
float remain = Vector3.Distance(transform.position, posints[i]);
while (remain == Mathf.Infinity || remain - agent.stoppingDistance > float.Epsilon)
{
remain = Vector3.Distance(transform.position, posints[i]);
yield return null;//防止循环造成卡死
}
posints.Remove(posints[i]);
//i++;
}
if (i == posints.Count)
{
GetComponent<BoxCollider>().enabled = true;
}
}
}