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.
586 lines
20 KiB
586 lines
20 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 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() |
|
{ |
|
|
|
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); |
|
} |
|
} |
|
} |
|
|
|
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) |
|
StartCoroutine(PathFinding(TargetPoint)); |
|
} |
|
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 List<Vector3> LiSan(Vector3 center, int count, Vector3 size) |
|
{ |
|
List<Vector3> list = new List<Vector3>(); |
|
int num = 1; |
|
while (list.Count < count) |
|
{ |
|
var tagent = new Vector3(center.x, center.y, center.z + size.z * num); |
|
if (InNavMesh(center, 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(center, 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(center, 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(center, tagent)) |
|
list.Add(tagent); |
|
else |
|
{ |
|
if (Vector3.Distance(center, tagent) >= (count + 3) * size.x) |
|
break; |
|
} |
|
num++; |
|
} |
|
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; |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|