870 lines
32 KiB
C#
870 lines
32 KiB
C#
|
/********************************************************************************
|
|||
|
* 文件名: AutoSearchAgent.cs
|
|||
|
* 全路径: \Script\Player\AutoSearch\AutoSearchAgent.cs
|
|||
|
* 创建人: 李嘉
|
|||
|
* 创建时间:2014-01-02
|
|||
|
*
|
|||
|
* 功能说明:自动寻路代理,只要建立一个路径,就会自动控制主角进行自动寻路
|
|||
|
* 寻路的具体路径保存在AutoSearchPath中
|
|||
|
* 修改记录:
|
|||
|
*********************************************************************************/
|
|||
|
|
|||
|
using Games.Events;
|
|||
|
using Games.GlobeDefine;
|
|||
|
using Games.LogicObj;
|
|||
|
using Games.Scene;
|
|||
|
using GCGame.Table;
|
|||
|
using Module.Log;
|
|||
|
using System.Collections.Generic;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
public struct MapConnectPath
|
|||
|
{
|
|||
|
//起始点
|
|||
|
public int SrcSceneId { get; set; }
|
|||
|
|
|||
|
//结束点
|
|||
|
public int DstSceneId { get; set; }
|
|||
|
|
|||
|
//传送点坐标X
|
|||
|
public float TelePosX { get; set; }
|
|||
|
|
|||
|
//传送点坐标Y
|
|||
|
public float TelePosZ { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
public class AutoSearchAgent : MonoBehaviour
|
|||
|
{
|
|||
|
//寻路最短距离的最大值
|
|||
|
private const int m_nMinDistanceMaxValue = 65535;
|
|||
|
|
|||
|
// 切换场景时,寻路器锁定时间
|
|||
|
private const float _sceneChangeLockTime = 2f;
|
|||
|
|
|||
|
//更新时间间隔
|
|||
|
private readonly float m_fChangeSceneInterval = 5f; //跳场景更新时间间隔,单位为秒
|
|||
|
|
|||
|
private readonly float m_fUpdateInterval = 0.50f; //更新时间间隔,单位为秒
|
|||
|
|
|||
|
//是否自动寻路中标记位
|
|||
|
private bool _isAutoSearching;
|
|||
|
|
|||
|
// 切换场景时,锁定寻路器一段时间
|
|||
|
public static float unlockTime;
|
|||
|
private int m_AutoSearchTargetID = -1;
|
|||
|
|
|||
|
private string m_AutoSearchTargetName;
|
|||
|
private int m_bNotEnamyNpcFlag; // 非敌对NPC标记 避免NPC多余遍历
|
|||
|
|
|||
|
//场景通路图,可以在游戏开始后初始化
|
|||
|
private List<MapConnectPath> m_ConnectPath;
|
|||
|
|
|||
|
private AutoSearchPoint m_EndPointCache;
|
|||
|
public AutoSearchPoint EndPointCache
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return m_EndPointCache;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private float m_fLastChangeGuildSceneUpdateTime; //上一次切换帮会场景时间
|
|||
|
private float m_fLastChangeSceneInstUpdateTime; //上一次更新时间
|
|||
|
private float m_fLastUpdateTime; //上一次更新时间
|
|||
|
|
|||
|
private bool _MissionFlyChangeSceneFlag = false;
|
|||
|
|
|||
|
public AutoSearchAgent()
|
|||
|
{
|
|||
|
FLastChangeSceneUpdateTime = 0;
|
|||
|
}
|
|||
|
|
|||
|
// 自动寻路路径
|
|||
|
|
|||
|
public AutoSearchPath Path { get; set; }
|
|||
|
|
|||
|
public bool _IsNetAsk = false;
|
|||
|
|
|||
|
public bool IsAutoSearching
|
|||
|
{
|
|||
|
get { return _isAutoSearching; }
|
|||
|
set
|
|||
|
{
|
|||
|
_isAutoSearching = value;
|
|||
|
if (!_isAutoSearching && CenterTipsLogic.Instance()!=null)
|
|||
|
{
|
|||
|
CenterTipsLogic.Instance().OnAutoMoveStateChange();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//场景显示路标的
|
|||
|
private RoadSignManager m_RoadSignManager = null;
|
|||
|
public RoadSignManager RoadSignManager
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (m_RoadSignManager == null)
|
|||
|
m_RoadSignManager = new RoadSignManager();
|
|||
|
return m_RoadSignManager;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//多场景寻路
|
|||
|
private AutoSearchTelePort m_AutoSearchTelePort = null;
|
|||
|
public AutoSearchTelePort AutoSearchTelePort
|
|||
|
{
|
|||
|
get {
|
|||
|
if (m_AutoSearchTelePort == null)
|
|||
|
m_AutoSearchTelePort = new AutoSearchTelePort();
|
|||
|
return m_AutoSearchTelePort;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public float FLastChangeSceneUpdateTime { set; get; }
|
|||
|
|
|||
|
//初始化场景通路图
|
|||
|
public void InitMapConnectPath()
|
|||
|
{
|
|||
|
if (GameManager.gameManager.RunningScene == (int) GameDefine_Globe.SCENE_DEFINE.SCENE_LOGIN)
|
|||
|
return;
|
|||
|
|
|||
|
//说明已经初始化过,无需再次调用Init函数,整个游戏过程中初始化一次即可
|
|||
|
if (null != m_ConnectPath)
|
|||
|
return;
|
|||
|
//生成完整通路图
|
|||
|
m_ConnectPath = new List<MapConnectPath>();
|
|||
|
|
|||
|
foreach (var key in TableManager.GetMapConnection().Keys)
|
|||
|
{
|
|||
|
var tableList = TableManager.GetMapConnectionByID(key);
|
|||
|
if (null != tableList)
|
|||
|
foreach (var conect in tableList)
|
|||
|
{
|
|||
|
var path = new MapConnectPath
|
|||
|
{
|
|||
|
SrcSceneId = conect.SourceSceneID,
|
|||
|
DstSceneId = conect.DestSceneID,
|
|||
|
TelePosX = conect.TelePosX,
|
|||
|
TelePosZ = conect.TelePosZ
|
|||
|
};
|
|||
|
m_ConnectPath.Add(path);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//初始化
|
|||
|
private void Awake()
|
|||
|
{
|
|||
|
Path = new AutoSearchPath();
|
|||
|
Path.ResetPath();
|
|||
|
|
|||
|
IsAutoSearching = false;
|
|||
|
|
|||
|
m_EndPointCache = new AutoSearchPoint();
|
|||
|
//InitMapConnectPath();
|
|||
|
}
|
|||
|
|
|||
|
private void OnDestroy()
|
|||
|
{
|
|||
|
if (m_RoadSignManager != null)
|
|||
|
m_RoadSignManager.OnDestroy();
|
|||
|
}
|
|||
|
|
|||
|
public void LockAutoSearch(float time = _sceneChangeLockTime)
|
|||
|
{
|
|||
|
unlockTime = Time.realtimeSinceStartup + time;
|
|||
|
}
|
|||
|
|
|||
|
private void LateUpdate()
|
|||
|
{
|
|||
|
RoadSignManager.UpdateSign();
|
|||
|
}
|
|||
|
private void Update()
|
|||
|
{
|
|||
|
//未寻路,不更新
|
|||
|
if (!IsAutoSearching || Time.realtimeSinceStartup < unlockTime)
|
|||
|
return;
|
|||
|
//判断是否到了更新间隔
|
|||
|
if (Time.time - m_fLastUpdateTime < m_fUpdateInterval) return;
|
|||
|
|
|||
|
m_fLastUpdateTime = Time.time;
|
|||
|
var mainPlayer = ObjManager.Instance.MainPlayer;
|
|||
|
if (null == mainPlayer)
|
|||
|
return;
|
|||
|
if (GameManager.gameManager.RunningScene != m_EndPointCache.SceneID)
|
|||
|
{
|
|||
|
// 注:传送是一个技能,因此需要满足技能使用条件
|
|||
|
if (mainPlayer.CheckCanCastSkill() != SkillCastableCheckResult.Success
|
|||
|
|| !mainPlayer.SkillAllowSkill
|
|||
|
|| Time.time - FLastChangeSceneUpdateTime < m_fChangeSceneInterval)
|
|||
|
return;
|
|||
|
if (m_EndPointCache.GuildGuid != SceneData.sceneGuildGuid)
|
|||
|
if (m_EndPointCache.GuildGuid != GlobeVar.INVALID_GUID)
|
|||
|
{
|
|||
|
FLastChangeSceneUpdateTime = Time.time;
|
|||
|
mainPlayer.BackGuildMap(m_EndPointCache.GuildGuid);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
FLastChangeSceneUpdateTime = Time.time;
|
|||
|
var sceneInfo = TableManager.GetSceneClassByID(m_EndPointCache.SceneID, 0);
|
|||
|
if (sceneInfo != null)
|
|||
|
{
|
|||
|
if (m_EndPointCache.ChangeMapType == AutoSearchPoint.ChangeMap_Type.WORLDMAP)
|
|||
|
{
|
|||
|
SceneData.RequestChangeScene((int)m_EndPointCache.ChangeMapType, 0, m_EndPointCache.SceneID,
|
|||
|
m_EndPointCache.SceneInstID, (int)sceneInfo.SafeX, (int)sceneInfo.SafeZ);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SceneData.RequestChangeScene((int)m_EndPointCache.ChangeMapType, 0, m_EndPointCache.SceneID,
|
|||
|
m_EndPointCache.SceneInstID, (int)m_EndPointCache.PosX * 100, (int)m_EndPointCache.PosZ * 100);
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (m_EndPointCache.SceneInstID != -1 && SceneData.SceneInst != m_EndPointCache.SceneInstID)
|
|||
|
{
|
|||
|
if (Time.time - FLastChangeSceneUpdateTime < m_fChangeSceneInterval)
|
|||
|
return;
|
|||
|
FLastChangeSceneUpdateTime = Time.time;
|
|||
|
var packet =
|
|||
|
(CG_SCENE_CHANGEINST) PacketDistributed.CreatePacket(MessageID.PACKET_CG_SCENE_CHANGEINST);
|
|||
|
packet.SetSceneInst(m_EndPointCache.SceneInstID);
|
|||
|
packet.SendPacket();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (m_EndPointCache.ChangeMapType == AutoSearchPoint.ChangeMap_Type.MISSIONFLY)
|
|||
|
{
|
|||
|
if (!_MissionFlyChangeSceneFlag)
|
|||
|
{
|
|||
|
UnityEngine.AI.NavMeshPath navMeshPath = new UnityEngine.AI.NavMeshPath();
|
|||
|
bool needFly = false;
|
|||
|
if (UnityEngine.AI.NavMesh.CalculatePath(mainPlayer.Position, new Vector3(m_EndPointCache.PosX, mainPlayer.Position.y, m_EndPointCache.PosZ), 1, navMeshPath))
|
|||
|
{
|
|||
|
if (navMeshPath.GetTotalDistance() < 10)
|
|||
|
{
|
|||
|
needFly = false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
needFly = true;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
needFly = true;
|
|||
|
}
|
|||
|
|
|||
|
if (needFly)
|
|||
|
{
|
|||
|
SceneData.RequestChangeScene((int)m_EndPointCache.ChangeMapType, 0, m_EndPointCache.SceneID,
|
|||
|
m_EndPointCache.SceneInstID, (int)m_EndPointCache.PosX * 100, (int)m_EndPointCache.PosZ * 100);
|
|||
|
_MissionFlyChangeSceneFlag = true;
|
|||
|
#if UNITY_EDITOR
|
|||
|
GUIData.AddNotifyData("飞鞋传送场景:" + m_EndPointCache.SceneID + "," + m_EndPointCache.PosX + "," + m_EndPointCache.PosZ);
|
|||
|
Debug.Log("飞鞋传送场景:" + m_EndPointCache.SceneID + "," + m_EndPointCache.PosX + "," + m_EndPointCache.PosZ);
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("#{86104}"));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (m_EndPointCache.GuildGuid != SceneData.sceneGuildGuid)
|
|||
|
if (m_EndPointCache.GuildGuid != GlobeVar.INVALID_GUID)
|
|||
|
{
|
|||
|
if (Time.time - m_fLastChangeGuildSceneUpdateTime < m_fChangeSceneInterval)
|
|||
|
return;
|
|||
|
m_fLastChangeGuildSceneUpdateTime = Time.time;
|
|||
|
mainPlayer.BackGuildMap(m_EndPointCache.GuildGuid);
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
FLastChangeSceneUpdateTime = 0;
|
|||
|
m_fLastChangeSceneInstUpdateTime = 0;
|
|||
|
m_fLastChangeGuildSceneUpdateTime = 0;
|
|||
|
//寻路中首先判断是否结束
|
|||
|
if (Path.IsFinish(mainPlayer.transform.position))
|
|||
|
Finish();
|
|||
|
// 如果角色停止移动或者到达位置,则重新开始移动
|
|||
|
else if (Path.IsReachPoint(mainPlayer.transform.position) || mainPlayer.MovementState == MoveState.Static)
|
|||
|
BeginMove();
|
|||
|
//else if (Path.IsReachPoint(mainPlayer.transform.position))
|
|||
|
// GotoNextPoint();
|
|||
|
////如果此时未移动,则前往下一个点
|
|||
|
//else if (mainPlayer.MovementState == MoveState.Static)
|
|||
|
// BeginMove();
|
|||
|
}
|
|||
|
|
|||
|
// 寻路找怪处理
|
|||
|
// private void FindEnamyTick()
|
|||
|
// {
|
|||
|
// if (m_bNotEnamyNpcFlag != 0) return;
|
|||
|
//
|
|||
|
// //如果有目标名字则寻找该目标,进行交互
|
|||
|
// if (Path.AutoSearchTargetName != "")
|
|||
|
// {
|
|||
|
// var obj = Singleton<ObjManager>.GetInstance()
|
|||
|
// .FindObjCharacterInSceneByName(Path.AutoSearchTargetName);
|
|||
|
// if (obj && obj.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_NPC)
|
|||
|
// {
|
|||
|
// var objNpc = obj as Obj_NPC;
|
|||
|
// //根据目标NPC的势力确认是对话还是攻击
|
|||
|
// if (Reputation.IsEnemy(objNpc) || Reputation.IsNeutral(objNpc))
|
|||
|
// {
|
|||
|
// Singleton<ObjManager>.GetInstance().MainPlayer.StopMove();
|
|||
|
// Path.AutoSearchPosCache.Clear();
|
|||
|
// Path.ResetPath();
|
|||
|
// IsAutoSearching = false;
|
|||
|
// m_EndPointCache.Clean();
|
|||
|
//
|
|||
|
// //如果是地方NPC,则开始攻击
|
|||
|
// Singleton<ObjManager>.GetInstance().MainPlayer.OnEnterCombat(objNpc);
|
|||
|
// Singleton<ObjManager>.GetInstance().MainPlayer.EnterAutoCombat();
|
|||
|
// m_bNotEnamyNpcFlag = 1;
|
|||
|
// }
|
|||
|
// else
|
|||
|
// {
|
|||
|
// m_bNotEnamyNpcFlag = 2;
|
|||
|
// }
|
|||
|
// }
|
|||
|
// }
|
|||
|
// }
|
|||
|
|
|||
|
//创建一条路径,并且在Update中判断是否抵达
|
|||
|
public void BuildPath(AutoSearchPoint endPoint, bool isNetAsk = false, string searchName = null, float dialogRadius = -1)
|
|||
|
{
|
|||
|
if(GameManager.gameManager.PlayerDataPool.IsInWeddingCar)
|
|||
|
{
|
|||
|
GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("#{26013}"));
|
|||
|
return;
|
|||
|
}
|
|||
|
//正在播放剧情
|
|||
|
if (SceneMovieManager.Instance._PlayingMovie)
|
|||
|
return;
|
|||
|
if (Singleton<ObjManager>.Instance.MainPlayer.IsInPaoShang() && RoadSignManager.ShowSign)
|
|||
|
{
|
|||
|
GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#34013}"));
|
|||
|
return;
|
|||
|
}
|
|||
|
//组队跟随,不响应
|
|||
|
if (GameManager.gameManager.PlayerDataPool.IsFollowTeam)
|
|||
|
{
|
|||
|
GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("#{5128}"));
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var _mainPlayer = Singleton<ObjManager>.GetInstance().MainPlayer;
|
|||
|
if (null == _mainPlayer) return;
|
|||
|
|
|||
|
if (GameManager.gameManager.ActiveScene.IsCopyScene() == false)
|
|||
|
_mainPlayer.LeveAutoCombat();
|
|||
|
|
|||
|
// 同一个点,直接跳过
|
|||
|
if (m_EndPointCache.SceneID == endPoint.SceneID
|
|||
|
&& m_EndPointCache.PosX == endPoint.PosX
|
|||
|
&& m_EndPointCache.PosZ == endPoint.PosZ
|
|||
|
&& m_EndPointCache.ChangeMapType == endPoint.ChangeMapType)
|
|||
|
return;
|
|||
|
|
|||
|
_MissionFlyChangeSceneFlag = false;
|
|||
|
|
|||
|
//停止正在进行的移动
|
|||
|
if (_mainPlayer.MovementState > MoveState.Static)
|
|||
|
_mainPlayer.StopMove();
|
|||
|
if (OneDragonAuto.One_DragonAuto != null && isNetAsk)
|
|||
|
OneDragonAuto.One_DragonAuto.NeedCheckOneDragonEnterCopy = false;
|
|||
|
|
|||
|
m_EndPointCache = endPoint;
|
|||
|
Path.ResetPath();
|
|||
|
m_bNotEnamyNpcFlag = 0;
|
|||
|
Path.AddPathPoint(endPoint);
|
|||
|
|
|||
|
_IsNetAsk = isNetAsk;
|
|||
|
if (searchName != null)
|
|||
|
Path.AutoSearchTargetName = searchName;
|
|||
|
|
|||
|
if (dialogRadius != -1)
|
|||
|
Path.autoSearchRadius = dialogRadius;
|
|||
|
|
|||
|
//设置开始自动寻路
|
|||
|
IsAutoSearching = true;
|
|||
|
// 如果是队长,让队员进入组队跟随
|
|||
|
if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain())
|
|||
|
_mainPlayer.TeamLeaderEndCombat();
|
|||
|
|
|||
|
//如果是当前场景,则直接生成单点路径,进行移动
|
|||
|
// if (GameManager.gameManager.RunningScene == endPoint.SceneID)
|
|||
|
// {
|
|||
|
// m_Path.AddPathPoint(endPoint);
|
|||
|
// //设置开始自动寻路
|
|||
|
// m_bIsAutoSearching = true;
|
|||
|
// return;
|
|||
|
// }
|
|||
|
|
|||
|
//根据当前点和目的地点来确定路径
|
|||
|
// AutoSearchPoint startPoint = AutoSearchPoint.MakePoint(_mainPlayer.gameObject);
|
|||
|
// if (true == FindPath(startPoint, endPoint))
|
|||
|
// {
|
|||
|
// m_bIsAutoSearching = true;
|
|||
|
// return;
|
|||
|
// }
|
|||
|
}
|
|||
|
|
|||
|
//获得两个场景的通路长度
|
|||
|
private int GetDisBySceneID(int srcId, int dstId)
|
|||
|
{
|
|||
|
foreach (var path in m_ConnectPath)
|
|||
|
if (path.SrcSceneId == srcId && path.DstSceneId == dstId)
|
|||
|
return 1;
|
|||
|
|
|||
|
return m_nMinDistanceMaxValue;
|
|||
|
}
|
|||
|
|
|||
|
//搜索路径算法,根据DJ算法生成最短路径
|
|||
|
private bool FindPath(AutoSearchPoint startPoint, AutoSearchPoint endPoint)
|
|||
|
{
|
|||
|
var path = new List<int>(); //最后生成的最短路径图
|
|||
|
|
|||
|
//统计所有节点,计算srcid的逆临街表,放在nodeMap中
|
|||
|
var nodeMap = new Dictionary<int, PathNodeInfo>();
|
|||
|
foreach (var connectPath in m_ConnectPath)
|
|||
|
{
|
|||
|
if (false == nodeMap.ContainsKey(connectPath.SrcSceneId))
|
|||
|
{
|
|||
|
var info = new PathNodeInfo();
|
|||
|
info.sceneId = connectPath.SrcSceneId;
|
|||
|
info.dis = GetDisBySceneID(startPoint.SceneID, info.sceneId);
|
|||
|
info.prevNode = startPoint.SceneID;
|
|||
|
nodeMap.Add(info.sceneId, info);
|
|||
|
}
|
|||
|
|
|||
|
if (false == nodeMap.ContainsKey(connectPath.DstSceneId))
|
|||
|
{
|
|||
|
var info = new PathNodeInfo();
|
|||
|
info.sceneId = connectPath.DstSceneId;
|
|||
|
info.dis = GetDisBySceneID(startPoint.SceneID, info.sceneId);
|
|||
|
info.prevNode = startPoint.SceneID;
|
|||
|
nodeMap.Add(info.sceneId, info);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var openList = new List<int>();
|
|||
|
var closeList = new List<int>();
|
|||
|
|
|||
|
//放入开始点
|
|||
|
openList.Add(startPoint.SceneID);
|
|||
|
|
|||
|
while (openList.Count > 0)
|
|||
|
{
|
|||
|
var minPt = openList[0];
|
|||
|
var minDis = m_nMinDistanceMaxValue;
|
|||
|
|
|||
|
foreach (var openPoint in openList)
|
|||
|
{
|
|||
|
if (!nodeMap.ContainsKey(openPoint)) continue;
|
|||
|
|
|||
|
if (nodeMap[openPoint].dis < minDis)
|
|||
|
{
|
|||
|
minPt = openPoint;
|
|||
|
minDis = nodeMap[openPoint].dis;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var minDisNode = minPt;
|
|||
|
openList.Remove(minDisNode);
|
|||
|
closeList.Add(minDisNode);
|
|||
|
|
|||
|
//展开该节点,更新所有邻接表的距离,并把下一个(或几个)最短路径上的点放入openList。
|
|||
|
foreach (var connectPath in m_ConnectPath)
|
|||
|
if (connectPath.SrcSceneId == minDisNode)
|
|||
|
{
|
|||
|
var newDis = nodeMap[minDisNode].dis + GetDisBySceneID(minDisNode, connectPath.DstSceneId);
|
|||
|
if (newDis < nodeMap[connectPath.DstSceneId].dis)
|
|||
|
{
|
|||
|
nodeMap[connectPath.DstSceneId].dis = newDis;
|
|||
|
nodeMap[connectPath.DstSceneId].prevNode = minDisNode;
|
|||
|
}
|
|||
|
|
|||
|
if (!openList.Contains(connectPath.DstSceneId) && !closeList.Contains(connectPath.DstSceneId))
|
|||
|
openList.Add(connectPath.DstSceneId);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (!nodeMap.ContainsKey(endPoint.SceneID)) return false;
|
|||
|
|
|||
|
//这里生成最短路径和下一个场景号,这里的邻接表已经记录了最短路径信息
|
|||
|
if (nodeMap[endPoint.SceneID].dis < m_nMinDistanceMaxValue)
|
|||
|
{
|
|||
|
path.Insert(0, endPoint.SceneID);
|
|||
|
var backId = nodeMap[endPoint.SceneID].prevNode;
|
|||
|
while (backId != -1)
|
|||
|
{
|
|||
|
if (backId == startPoint.SceneID)
|
|||
|
{
|
|||
|
//int nextScn = path[0];
|
|||
|
path.Insert(0, backId);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
path.Insert(0, backId);
|
|||
|
backId = nodeMap[backId].prevNode;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (path.Count > 1)
|
|||
|
{
|
|||
|
//生成路径
|
|||
|
var beginScene = path[0];
|
|||
|
var endScene = -1;
|
|||
|
for (var i = 1; i < path.Count; ++i)
|
|||
|
{
|
|||
|
endScene = path[i];
|
|||
|
foreach (var connectPath in m_ConnectPath)
|
|||
|
if (connectPath.SrcSceneId == beginScene && connectPath.DstSceneId == endScene)
|
|||
|
{
|
|||
|
var point = new AutoSearchPoint(connectPath.SrcSceneId, connectPath.TelePosX,
|
|||
|
connectPath.TelePosZ);
|
|||
|
Path.AutoSearchPosCache.Add(point);
|
|||
|
|
|||
|
beginScene = endScene;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//最后加入目标点
|
|||
|
Path.AutoSearchPosCache.Add(endPoint);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//切换场景的时候判断一下是否是自动寻路,如果不是自动寻路的就清除一下自动寻路的数据
|
|||
|
public void OnChangeScene(int sceneId)
|
|||
|
{
|
|||
|
if(sceneId == -1)
|
|||
|
{
|
|||
|
StopAutoSerach();
|
|||
|
return;
|
|||
|
}
|
|||
|
if (Path == null)
|
|||
|
return;
|
|||
|
|
|||
|
if (Path.GetPathPosition(sceneId) == null) StopAutoSerach();
|
|||
|
}
|
|||
|
|
|||
|
//寻路到帮会场景
|
|||
|
public void BackGuild(ulong guildId, int roleId, float x, float z)
|
|||
|
{
|
|||
|
if (roleId == -1)
|
|||
|
{
|
|||
|
var guid = GameManager.gameManager.PlayerDataPool.GuildInfo.GuildGuid;
|
|||
|
var mainPlayer = ObjManager.Instance.MainPlayer;
|
|||
|
if (mainPlayer != null)
|
|||
|
mainPlayer.BackGuildMap(guid);
|
|||
|
else
|
|||
|
{
|
|||
|
// 保持之前玩家未创建也可以发送协议的逻辑
|
|||
|
var send =
|
|||
|
(CG_REQ_ENTER_GUILDMAP) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_ENTER_GUILDMAP);
|
|||
|
send.SetGuildGuid(guid);
|
|||
|
send.SendPacket();
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var guildOther = TableManager.GetGuildOtherByID(0, 0);
|
|||
|
if (guildOther != null)
|
|||
|
{
|
|||
|
var GuildSceneId = guildOther.SceneId;
|
|||
|
var point = new AutoSearchPoint(GuildSceneId, x, z, -1, AutoSearchPoint.ChangeMap_Type.WORLDMAP,
|
|||
|
guildId);
|
|||
|
var RoleBase = TableManager.GetRoleBaseAttrByID(roleId, 0);
|
|||
|
if (null != RoleBase && null != Path)
|
|||
|
{
|
|||
|
BuildPath(point);
|
|||
|
Path.AutoSearchTargetName = RoleBase.Name;
|
|||
|
Path.autoSearchRadius = RoleBase.DialogRadius;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void StopAutoSerach()
|
|||
|
{
|
|||
|
FLastChangeSceneUpdateTime = 0;
|
|||
|
m_fLastChangeGuildSceneUpdateTime = 0;
|
|||
|
m_fLastChangeSceneInstUpdateTime = 0;
|
|||
|
Path.ResetPath();
|
|||
|
IsAutoSearching = false;
|
|||
|
m_EndPointCache.Clean();
|
|||
|
m_AutoSearchTargetName = "";
|
|||
|
m_AutoSearchTargetID = -1;
|
|||
|
if(Singleton<ObjManager>.Instance.MainPlayer!=null)
|
|||
|
Singleton<ObjManager>.Instance.MainPlayer.StopMove();
|
|||
|
}
|
|||
|
|
|||
|
//停止自动寻路
|
|||
|
public void Stop()
|
|||
|
{
|
|||
|
StopAutoSerach();
|
|||
|
AutoSearchTelePort.Stop();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public static UnityEngine.AI.NavMeshPath tempPath
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_tempPath == null)
|
|||
|
_tempPath = new UnityEngine.AI.NavMeshPath();
|
|||
|
return _tempPath;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static UnityEngine.AI.NavMeshPath _tempPath;
|
|||
|
|
|||
|
//向最新点移动
|
|||
|
private void BeginMove()
|
|||
|
{
|
|||
|
var mainPlayer = ObjManager.Instance.MainPlayer;
|
|||
|
if (null == mainPlayer)
|
|||
|
return;
|
|||
|
|
|||
|
if (Path.AutoSearchPosCache.Count > 0)
|
|||
|
{
|
|||
|
//首先检测场景是否对应,如果不对则直接返回
|
|||
|
if (GameManager.gameManager.RunningScene != m_EndPointCache.SceneID)
|
|||
|
{
|
|||
|
if (m_EndPointCache.GuildGuid != SceneData.sceneGuildGuid)
|
|||
|
if (m_EndPointCache.GuildGuid != GlobeVar.INVALID_GUID)
|
|||
|
{
|
|||
|
FLastChangeSceneUpdateTime = Time.time;
|
|||
|
Singleton<ObjManager>.Instance.MainPlayer.BackGuildMap(m_EndPointCache.GuildGuid);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var sceneInfo = TableManager.GetSceneClassByID(m_EndPointCache.SceneID, 0);
|
|||
|
if (sceneInfo != null)
|
|||
|
{
|
|||
|
if (m_EndPointCache.ChangeMapType == AutoSearchPoint.ChangeMap_Type.WORLDMAP)
|
|||
|
{
|
|||
|
SceneData.RequestChangeScene((int)m_EndPointCache.ChangeMapType, 0, m_EndPointCache.SceneID,
|
|||
|
m_EndPointCache.SceneInstID, (int)sceneInfo.SafeX, (int)sceneInfo.SafeZ);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SceneData.RequestChangeScene((int)m_EndPointCache.ChangeMapType, 0, m_EndPointCache.SceneID,
|
|||
|
m_EndPointCache.SceneInstID, (int)m_EndPointCache.PosX * 100, (int)m_EndPointCache.PosZ * 100);
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (m_EndPointCache.SceneInstID != -1 && SceneData.SceneInst != m_EndPointCache.SceneInstID)
|
|||
|
{
|
|||
|
var packet =
|
|||
|
(CG_SCENE_CHANGEINST)PacketDistributed.CreatePacket(MessageID.PACKET_CG_SCENE_CHANGEINST);
|
|||
|
packet.SetSceneInst(m_EndPointCache.SceneInstID);
|
|||
|
packet.SendPacket();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (m_EndPointCache.ChangeMapType == AutoSearchPoint.ChangeMap_Type.MISSIONFLY)
|
|||
|
{
|
|||
|
if (!_MissionFlyChangeSceneFlag)
|
|||
|
{
|
|||
|
UnityEngine.AI.NavMeshPath navMeshPath = new UnityEngine.AI.NavMeshPath();
|
|||
|
bool needFly = false;
|
|||
|
if (UnityEngine.AI.NavMesh.CalculatePath(mainPlayer.Position, new Vector3(m_EndPointCache.PosX, mainPlayer.Position.y, m_EndPointCache.PosZ), 1, navMeshPath))
|
|||
|
{
|
|||
|
if (navMeshPath.GetTotalDistance() < 10)
|
|||
|
{
|
|||
|
needFly = false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
needFly = true;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
needFly = true;
|
|||
|
}
|
|||
|
|
|||
|
if (needFly)
|
|||
|
{
|
|||
|
SceneData.RequestChangeScene((int)m_EndPointCache.ChangeMapType, 0, m_EndPointCache.SceneID,
|
|||
|
m_EndPointCache.SceneInstID, (int)m_EndPointCache.PosX * 100, (int)m_EndPointCache.PosZ * 100);
|
|||
|
_MissionFlyChangeSceneFlag = true;
|
|||
|
#if UNITY_EDITOR
|
|||
|
GUIData.AddNotifyData("飞鞋传送场景:" + m_EndPointCache.SceneID + "," + m_EndPointCache.PosX + "," + m_EndPointCache.PosZ);
|
|||
|
Debug.Log("飞鞋传送场景:" + m_EndPointCache.SceneID + "," + m_EndPointCache.PosX + "," + m_EndPointCache.PosZ);
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (m_EndPointCache.GuildGuid != SceneData.sceneGuildGuid)
|
|||
|
if (m_EndPointCache.GuildGuid != GlobeVar.INVALID_GUID)
|
|||
|
{
|
|||
|
Singleton<ObjManager>.Instance.MainPlayer.BackGuildMap(m_EndPointCache.GuildGuid);
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//todo 武场特殊处理一下,后续一定要完善高度图误差
|
|||
|
// if (GameManager.gameManager.RunningScene == (int)GameDefine_Globe.SCENE_DEFINE.SCENE_WUCHANG)
|
|||
|
// {
|
|||
|
// pos.y = 18.5f;
|
|||
|
// }
|
|||
|
if (mainPlayer.IsCanAcceptMoveOrder(true))
|
|||
|
{
|
|||
|
var pos = new Vector3(m_EndPointCache.PosX, 0, m_EndPointCache.PosZ);
|
|||
|
pos = ActiveScene.GetTerrainPosition(pos);
|
|||
|
|
|||
|
if (CenterTipsLogic.Instance() != null)
|
|||
|
{
|
|||
|
CenterTipsLogic.Instance().OnAutoMoveStateChange();
|
|||
|
}
|
|||
|
var stopRange = Mathf.Max(0f, Path.autoSearchRadius);
|
|||
|
mainPlayer.MainPlayMoveToPos(pos, stopRange, bIsAutoSearch: true);
|
|||
|
if (IsAutoSearching &&
|
|||
|
null != GameManager.gameManager.AutoSearch &&
|
|||
|
GameManager.gameManager.AutoSearch.IsAutoSearching
|
|||
|
&& GameManager.gameManager.PlayerDataPool.m_objMountParam.AdvanceMountId < 1 //当前有坐骑但是你没有骑乘
|
|||
|
&& GameManager.gameManager.PlayerDataPool.m_objMountParam.AutoFlagMountID > 0)
|
|||
|
{
|
|||
|
if (mainPlayer.NavAgent != null && mainPlayer.NavAgent.isActiveAndEnabled &&
|
|||
|
mainPlayer.NavAgent.hasPath)
|
|||
|
{
|
|||
|
var distance = mainPlayer.NavAgent.path.GetTotalDistance();
|
|||
|
if ( /*distance > 50f &&*/ distance >= 10f)
|
|||
|
mainPlayer.AskRideMount(false);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//自动寻路结束
|
|||
|
private void Finish()
|
|||
|
{
|
|||
|
//如果有结束后的回调事件则回调
|
|||
|
if (null != Path.FinishCallBackEvent &&
|
|||
|
GameDefine_Globe.EVENT_DEFINE.EVENT_INVALID != Path.FinishCallBackEvent.EventID)
|
|||
|
Singleton<EventSystem>.GetInstance().PushEvent(Path.FinishCallBackEvent);
|
|||
|
|
|||
|
if (Path.finishCallBack != null) Path.finishCallBack(Path.callBackParam);
|
|||
|
|
|||
|
m_AutoSearchTargetName = Path.AutoSearchTargetName;
|
|||
|
m_AutoSearchTargetID = Path.AutoSearchTargetID;
|
|||
|
AgentToNPC();
|
|||
|
|
|||
|
m_EndPointCache.Clean();
|
|||
|
Path.ResetPath();
|
|||
|
IsAutoSearching = false;
|
|||
|
m_fLastUpdateTime = 0;
|
|||
|
}
|
|||
|
|
|||
|
public void AgentToNPC(Obj_NPC npc = null)
|
|||
|
{
|
|||
|
if (npc != null && IsAutoSearching && Path.AutoSearchTargetRoleID != -1 && Path.AutoSearchTargetRoleID == npc.BaseAttr.RoleBaseID)
|
|||
|
{
|
|||
|
Stop();
|
|||
|
Path.AutoSearchTargetRoleID = -1;
|
|||
|
AutoSearchPoint point = new AutoSearchPoint(GameManager.gameManager.RunningScene, npc.Position.x, npc.Position.z, SceneData.SceneInst, AutoSearchPoint.ChangeMap_Type.WORLDMAP, SceneData.sceneGuildGuid);
|
|||
|
if (GameManager.gameManager && GameManager.gameManager.AutoSearch)
|
|||
|
{
|
|||
|
GameManager.gameManager.AutoSearch.BuildPath(point);
|
|||
|
GameManager.gameManager.AutoSearch.Path.AutoSearchTargetID = npc.ServerID;
|
|||
|
GameManager.gameManager.AutoSearch.Path.autoSearchRadius = 1.5f;
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//如果有目标名字则寻找该目标,进行交互
|
|||
|
if (m_AutoSearchTargetName != "" || m_AutoSearchTargetID != -1)
|
|||
|
{
|
|||
|
var obj = ObjManager.Instance.FindObjCharacterInScene(m_AutoSearchTargetID);
|
|||
|
if (obj == null)
|
|||
|
obj = ObjManager.Instance.FindObjCharacterInSceneByName(m_AutoSearchTargetName);
|
|||
|
var mainPlayer = ObjManager.Instance.MainPlayer;
|
|||
|
if (mainPlayer && obj && obj.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_NPC)
|
|||
|
{
|
|||
|
m_AutoSearchTargetName = "";
|
|||
|
m_AutoSearchTargetID = -1;
|
|||
|
var objNpc = (Obj_NPC)obj;
|
|||
|
//根据目标NPC的势力确认是对话还是攻击
|
|||
|
if (Reputation.CanAttack(objNpc))
|
|||
|
{
|
|||
|
//如果是地方NPC,则开始攻击
|
|||
|
if (!mainPlayer.isAutoCombat)
|
|||
|
mainPlayer.OnEnterCombat(objNpc);
|
|||
|
mainPlayer.EnterAutoCombat();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
mainPlayer.SetClientTargetByClick(objNpc);
|
|||
|
}
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//当自动寻路过程中遇到传送点
|
|||
|
public void ProcessTelepoint(Obj_TeleportPoint telePoint)
|
|||
|
{
|
|||
|
//传送点数据异常,返回
|
|||
|
if (null == telePoint || null == telePoint.gameObject) return;
|
|||
|
|
|||
|
//非自动寻路状态,返回
|
|||
|
if (!IsAutoSearching) return;
|
|||
|
|
|||
|
//自动寻路状态,并且路径中有数值
|
|||
|
if (Path.AutoSearchPosCache.Count > 0)
|
|||
|
{
|
|||
|
//判断是不是本次跨场景寻路所需传送点
|
|||
|
var autoSearchPoint = new Vector2(Path.AutoSearchPosCache[0].PosX, Path.AutoSearchPosCache[0].PosZ);
|
|||
|
var telePortPoint = new Vector2(telePoint.gameObject.transform.position.x,
|
|||
|
telePoint.gameObject.transform.position.z);
|
|||
|
//距离校验,因为自动寻路点为2D,所以转化为2D坐标验证
|
|||
|
if (Vector2.Distance(autoSearchPoint, telePortPoint) <= 3.0f)
|
|||
|
{
|
|||
|
Path.AutoSearchPosCache.RemoveAt(0);
|
|||
|
|
|||
|
//如果此时路径点中无数据,则结束自动寻路
|
|||
|
if (Path.AutoSearchPosCache.Count == 0) Finish();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private class PathNodeInfo
|
|||
|
{
|
|||
|
public int dis;
|
|||
|
public int prevNode;
|
|||
|
|
|||
|
public int sceneId;
|
|||
|
|
|||
|
public PathNodeInfo()
|
|||
|
{
|
|||
|
sceneId = -1;
|
|||
|
dis = m_nMinDistanceMaxValue;
|
|||
|
prevNode = -1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|