summaryrefslogtreecommitdiff
path: root/Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs')
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs754
1 files changed, 754 insertions, 0 deletions
diff --git a/Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs b/Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs
new file mode 100644
index 0000000..8db3b1b
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs
@@ -0,0 +1,754 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.AI;
+
+public class Pathfinding : MonoBehaviour
+{
+ private class NavMeshTile
+ {
+ public Vector3Int m_tile;
+
+ public Vector3 m_center;
+
+ public float m_pokeTime = -1000f;
+
+ public float m_buildTime = -1000f;
+
+ public NavMeshData m_data;
+
+ public NavMeshDataInstance m_instance;
+
+ public List<KeyValuePair<Vector3, NavMeshLinkInstance>> m_links1 = new List<KeyValuePair<Vector3, NavMeshLinkInstance>>();
+
+ public List<KeyValuePair<Vector3, NavMeshLinkInstance>> m_links2 = new List<KeyValuePair<Vector3, NavMeshLinkInstance>>();
+ }
+
+ public enum AgentType
+ {
+ Humanoid = 1,
+ TrollSize,
+ HugeSize,
+ HorseSize,
+ HumanoidNoSwim,
+ HumanoidAvoidWater,
+ Fish,
+ Wolf,
+ BigFish,
+ GoblinBruteSize,
+ HumanoidBigNoSwim
+ }
+
+ public enum AreaType
+ {
+ Default,
+ NotWalkable,
+ Jump,
+ Water
+ }
+
+ private class AgentSettings
+ {
+ public AgentType m_agentType;
+
+ public NavMeshBuildSettings m_build;
+
+ public bool m_canWalk = true;
+
+ public bool m_avoidWater;
+
+ public bool m_canSwim = true;
+
+ public float m_swimDepth;
+
+ public int m_areaMask = -1;
+
+ public AgentSettings(AgentType type)
+ {
+ m_agentType = type;
+ m_build = NavMesh.CreateSettings();
+ }
+ }
+
+ private List<Vector3> tempPath = new List<Vector3>();
+
+ private List<Vector3> optPath = new List<Vector3>();
+
+ private List<Vector3> tempStitchPoints = new List<Vector3>();
+
+ private RaycastHit[] tempHitArray = new RaycastHit[255];
+
+ private static Pathfinding m_instance;
+
+ public LayerMask m_layers;
+
+ public LayerMask m_waterLayers;
+
+ private Dictionary<Vector3Int, NavMeshTile> m_tiles = new Dictionary<Vector3Int, NavMeshTile>();
+
+ public float m_tileSize = 32f;
+
+ public float m_defaultCost = 1f;
+
+ public float m_waterCost = 4f;
+
+ public float m_linkCost = 10f;
+
+ public float m_linkWidth = 1f;
+
+ public float m_updateInterval = 5f;
+
+ public float m_tileTimeout = 30f;
+
+ private const float m_tileHeight = 6000f;
+
+ private const float m_tileY = 2500f;
+
+ private float m_updatePathfindingTimer;
+
+ private Queue<Vector3Int> m_queuedAreas = new Queue<Vector3Int>();
+
+ private Queue<NavMeshLinkInstance> m_linkRemoveQueue = new Queue<NavMeshLinkInstance>();
+
+ private Queue<NavMeshDataInstance> m_tileRemoveQueue = new Queue<NavMeshDataInstance>();
+
+ private Vector3Int m_cachedTileID = new Vector3Int(-9999999, -9999999, -9999999);
+
+ private NavMeshTile m_cachedTile;
+
+ private List<AgentSettings> m_agentSettings = new List<AgentSettings>();
+
+ private AsyncOperation m_buildOperation;
+
+ private NavMeshTile m_buildTile;
+
+ private List<KeyValuePair<NavMeshTile, NavMeshTile>> m_edgeBuildQueue = new List<KeyValuePair<NavMeshTile, NavMeshTile>>();
+
+ private NavMeshPath m_path;
+
+ public static Pathfinding instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ SetupAgents();
+ m_path = new NavMeshPath();
+ }
+
+ private void ClearAgentSettings()
+ {
+ List<NavMeshBuildSettings> list = new List<NavMeshBuildSettings>();
+ for (int i = 0; i < NavMesh.GetSettingsCount(); i++)
+ {
+ list.Add(NavMesh.GetSettingsByIndex(i));
+ }
+ ZLog.Log("Build settings:" + list.Count);
+ foreach (NavMeshBuildSettings item in list)
+ {
+ if (item.agentTypeID != 0)
+ {
+ ZLog.Log("Removing " + item.agentTypeID);
+ NavMesh.RemoveSettings(item.agentTypeID);
+ }
+ }
+ }
+
+ private void OnDestroy()
+ {
+ foreach (NavMeshTile value in m_tiles.Values)
+ {
+ ClearLinks(value);
+ if ((bool)value.m_data)
+ {
+ NavMesh.RemoveNavMeshData(value.m_instance);
+ }
+ }
+ m_tiles.Clear();
+ DestroyAllLinks();
+ }
+
+ private AgentSettings AddAgent(AgentType type, AgentSettings copy = null)
+ {
+ while ((int)(type + 1) > m_agentSettings.Count)
+ {
+ m_agentSettings.Add(null);
+ }
+ AgentSettings agentSettings = new AgentSettings(type);
+ if (copy != null)
+ {
+ agentSettings.m_build.agentHeight = copy.m_build.agentHeight;
+ agentSettings.m_build.agentClimb = copy.m_build.agentClimb;
+ agentSettings.m_build.agentRadius = copy.m_build.agentRadius;
+ agentSettings.m_build.agentSlope = copy.m_build.agentSlope;
+ }
+ m_agentSettings[(int)type] = agentSettings;
+ return agentSettings;
+ }
+
+ private void SetupAgents()
+ {
+ ClearAgentSettings();
+ AgentSettings agentSettings = AddAgent(AgentType.Humanoid);
+ agentSettings.m_build.agentHeight = 1.8f;
+ agentSettings.m_build.agentClimb = 0.3f;
+ agentSettings.m_build.agentRadius = 0.4f;
+ agentSettings.m_build.agentSlope = 85f;
+ AddAgent(AgentType.Wolf, agentSettings).m_build.agentSlope = 85f;
+ AddAgent(AgentType.HumanoidNoSwim, agentSettings).m_canSwim = false;
+ AgentSettings agentSettings2 = AddAgent(AgentType.HumanoidBigNoSwim);
+ agentSettings2.m_build.agentHeight = 2.5f;
+ agentSettings2.m_build.agentClimb = 0.3f;
+ agentSettings2.m_build.agentRadius = 0.5f;
+ agentSettings2.m_build.agentSlope = 85f;
+ agentSettings2.m_canSwim = false;
+ AddAgent(AgentType.HumanoidAvoidWater, agentSettings).m_avoidWater = true;
+ AgentSettings agentSettings3 = AddAgent(AgentType.TrollSize);
+ agentSettings3.m_build.agentHeight = 7f;
+ agentSettings3.m_build.agentClimb = 0.7f;
+ agentSettings3.m_build.agentRadius = 1f;
+ agentSettings3.m_build.agentSlope = 85f;
+ AgentSettings agentSettings4 = AddAgent(AgentType.GoblinBruteSize);
+ agentSettings4.m_build.agentHeight = 3.5f;
+ agentSettings4.m_build.agentClimb = 0.3f;
+ agentSettings4.m_build.agentRadius = 0.8f;
+ agentSettings4.m_build.agentSlope = 85f;
+ AgentSettings agentSettings5 = AddAgent(AgentType.HugeSize);
+ agentSettings5.m_build.agentHeight = 10f;
+ agentSettings5.m_build.agentClimb = 1.2f;
+ agentSettings5.m_build.agentRadius = 2f;
+ agentSettings5.m_build.agentSlope = 85f;
+ AgentSettings agentSettings6 = AddAgent(AgentType.HorseSize);
+ agentSettings6.m_build.agentHeight = 2.5f;
+ agentSettings6.m_build.agentClimb = 0.3f;
+ agentSettings6.m_build.agentRadius = 0.8f;
+ agentSettings6.m_build.agentSlope = 85f;
+ AgentSettings agentSettings7 = AddAgent(AgentType.Fish);
+ agentSettings7.m_build.agentHeight = 0.5f;
+ agentSettings7.m_build.agentClimb = 1f;
+ agentSettings7.m_build.agentRadius = 0.5f;
+ agentSettings7.m_build.agentSlope = 90f;
+ agentSettings7.m_canSwim = true;
+ agentSettings7.m_canWalk = false;
+ agentSettings7.m_swimDepth = 0.4f;
+ agentSettings7.m_areaMask = 12;
+ AgentSettings agentSettings8 = AddAgent(AgentType.BigFish);
+ agentSettings8.m_build.agentHeight = 1.5f;
+ agentSettings8.m_build.agentClimb = 1f;
+ agentSettings8.m_build.agentRadius = 1f;
+ agentSettings8.m_build.agentSlope = 90f;
+ agentSettings8.m_canSwim = true;
+ agentSettings8.m_canWalk = false;
+ agentSettings8.m_swimDepth = 1.5f;
+ agentSettings8.m_areaMask = 12;
+ NavMesh.SetAreaCost(0, m_defaultCost);
+ NavMesh.SetAreaCost(3, m_waterCost);
+ }
+
+ private AgentSettings GetSettings(AgentType agentType)
+ {
+ return m_agentSettings[(int)agentType];
+ }
+
+ private int GetAgentID(AgentType agentType)
+ {
+ return GetSettings(agentType).m_build.agentTypeID;
+ }
+
+ private void Update()
+ {
+ if (!IsBuilding())
+ {
+ m_updatePathfindingTimer += Time.deltaTime;
+ if (m_updatePathfindingTimer > 0.1f)
+ {
+ m_updatePathfindingTimer = 0f;
+ UpdatePathfinding();
+ }
+ if (!IsBuilding())
+ {
+ DestroyQueuedNavmeshData();
+ }
+ }
+ }
+
+ private void DestroyAllLinks()
+ {
+ while (m_linkRemoveQueue.Count > 0 || m_tileRemoveQueue.Count > 0)
+ {
+ DestroyQueuedNavmeshData();
+ }
+ }
+
+ private void DestroyQueuedNavmeshData()
+ {
+ if (m_linkRemoveQueue.Count > 0)
+ {
+ int num = Mathf.Min(m_linkRemoveQueue.Count, 25);
+ for (int i = 0; i < num; i++)
+ {
+ NavMesh.RemoveLink(m_linkRemoveQueue.Dequeue());
+ }
+ }
+ else if (m_tileRemoveQueue.Count > 0)
+ {
+ NavMesh.RemoveNavMeshData(m_tileRemoveQueue.Dequeue());
+ }
+ }
+
+ private void UpdatePathfinding()
+ {
+ Buildtiles();
+ TimeoutTiles();
+ }
+
+ public bool HavePath(Vector3 from, Vector3 to, AgentType agentType)
+ {
+ return GetPath(from, to, null, agentType, requireFullPath: true, cleanup: false);
+ }
+
+ public bool FindValidPoint(out Vector3 point, Vector3 center, float range, AgentType agentType)
+ {
+ PokePoint(center, agentType);
+ AgentSettings settings = GetSettings(agentType);
+ NavMeshQueryFilter filter = default(NavMeshQueryFilter);
+ filter.agentTypeID = (int)settings.m_agentType;
+ filter.areaMask = settings.m_areaMask;
+ if (NavMesh.SamplePosition(center, out var hit, range, filter))
+ {
+ point = hit.position;
+ return true;
+ }
+ point = center;
+ return false;
+ }
+
+ public bool GetPath(Vector3 from, Vector3 to, List<Vector3> path, AgentType agentType, bool requireFullPath = false, bool cleanup = true)
+ {
+ path?.Clear();
+ PokeArea(from, agentType);
+ PokeArea(to, agentType);
+ AgentSettings settings = GetSettings(agentType);
+ if (!SnapToNavMesh(ref from, settings))
+ {
+ return false;
+ }
+ if (!SnapToNavMesh(ref to, settings))
+ {
+ return false;
+ }
+ NavMeshQueryFilter filter = default(NavMeshQueryFilter);
+ filter.agentTypeID = settings.m_build.agentTypeID;
+ filter.areaMask = settings.m_areaMask;
+ if (NavMesh.CalculatePath(from, to, filter, m_path))
+ {
+ if (m_path.status == NavMeshPathStatus.PathPartial && requireFullPath)
+ {
+ return false;
+ }
+ if (path != null)
+ {
+ path.AddRange(m_path.corners);
+ if (cleanup)
+ {
+ CleanPath(path, settings);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void CleanPath(List<Vector3> basePath, AgentSettings settings)
+ {
+ if (basePath.Count <= 2)
+ {
+ return;
+ }
+ NavMeshQueryFilter filter = default(NavMeshQueryFilter);
+ filter.agentTypeID = settings.m_build.agentTypeID;
+ filter.areaMask = settings.m_areaMask;
+ int num = 0;
+ optPath.Clear();
+ optPath.Add(basePath[num]);
+ do
+ {
+ num = FindNextNode(basePath, filter, num);
+ optPath.Add(basePath[num]);
+ }
+ while (num < basePath.Count - 1);
+ tempPath.Clear();
+ tempPath.Add(optPath[0]);
+ for (int i = 1; i < optPath.Count - 1; i++)
+ {
+ Vector3 vector = optPath[i - 1];
+ Vector3 vector2 = optPath[i];
+ Vector3 vector3 = optPath[i + 1];
+ Vector3 normalized = (vector3 - vector2).normalized;
+ Vector3 normalized2 = (vector2 - vector).normalized;
+ Vector3 vector4 = vector2 - (normalized + normalized2).normalized * Vector3.Distance(vector2, vector) * 0.33f;
+ vector4.y = (vector2.y + vector.y) * 0.5f;
+ Vector3 normalized3 = (vector4 - vector2).normalized;
+ if (!NavMesh.Raycast(vector2 + normalized3 * 0.1f, vector4, out var hit, filter) && !NavMesh.Raycast(vector4, vector, out hit, filter))
+ {
+ tempPath.Add(vector4);
+ }
+ tempPath.Add(vector2);
+ Vector3 vector5 = vector2 + (normalized + normalized2).normalized * Vector3.Distance(vector2, vector3) * 0.33f;
+ vector5.y = (vector2.y + vector3.y) * 0.5f;
+ Vector3 normalized4 = (vector5 - vector2).normalized;
+ if (!NavMesh.Raycast(vector2 + normalized4 * 0.1f, vector5, out hit, filter) && !NavMesh.Raycast(vector5, vector3, out hit, filter))
+ {
+ tempPath.Add(vector5);
+ }
+ }
+ tempPath.Add(optPath[optPath.Count - 1]);
+ basePath.Clear();
+ basePath.AddRange(tempPath);
+ }
+
+ private int FindNextNode(List<Vector3> path, NavMeshQueryFilter filter, int start)
+ {
+ for (int i = start + 2; i < path.Count; i++)
+ {
+ if (NavMesh.Raycast(path[start], path[i], out var _, filter))
+ {
+ return i - 1;
+ }
+ }
+ return path.Count - 1;
+ }
+
+ private bool SnapToNavMesh(ref Vector3 point, AgentSettings settings)
+ {
+ if ((bool)ZoneSystem.instance)
+ {
+ if (ZoneSystem.instance.GetGroundHeight(point, out var height) && point.y < height)
+ {
+ point.y = height;
+ }
+ if (settings.m_canSwim)
+ {
+ point.y = Mathf.Max(ZoneSystem.instance.m_waterLevel - settings.m_swimDepth, point.y);
+ }
+ }
+ NavMeshQueryFilter filter = default(NavMeshQueryFilter);
+ filter.agentTypeID = settings.m_build.agentTypeID;
+ filter.areaMask = settings.m_areaMask;
+ if (NavMesh.SamplePosition(point, out var hit, 1.5f, filter))
+ {
+ point = hit.position;
+ return true;
+ }
+ if (NavMesh.SamplePosition(point, out hit, 10f, filter))
+ {
+ point = hit.position;
+ return true;
+ }
+ if (NavMesh.SamplePosition(point, out hit, 20f, filter))
+ {
+ point = hit.position;
+ return true;
+ }
+ return false;
+ }
+
+ private void TimeoutTiles()
+ {
+ float realtimeSinceStartup = Time.realtimeSinceStartup;
+ foreach (KeyValuePair<Vector3Int, NavMeshTile> tile in m_tiles)
+ {
+ if (realtimeSinceStartup - tile.Value.m_pokeTime > m_tileTimeout)
+ {
+ ClearLinks(tile.Value);
+ if (tile.Value.m_instance.valid)
+ {
+ m_tileRemoveQueue.Enqueue(tile.Value.m_instance);
+ }
+ m_tiles.Remove(tile.Key);
+ break;
+ }
+ }
+ }
+
+ private void PokeArea(Vector3 point, AgentType agentType)
+ {
+ Vector3Int tile = GetTile(point, agentType);
+ PokeTile(tile);
+ for (int i = -1; i <= 1; i++)
+ {
+ for (int j = -1; j <= 1; j++)
+ {
+ if (j != 0 || i != 0)
+ {
+ Vector3Int tileID = new Vector3Int(tile.x + j, tile.y + i, tile.z);
+ PokeTile(tileID);
+ }
+ }
+ }
+ }
+
+ private void PokePoint(Vector3 point, AgentType agentType)
+ {
+ Vector3Int tile = GetTile(point, agentType);
+ PokeTile(tile);
+ }
+
+ private void PokeTile(Vector3Int tileID)
+ {
+ GetNavTile(tileID).m_pokeTime = Time.realtimeSinceStartup;
+ }
+
+ private void Buildtiles()
+ {
+ if (UpdateAsyncBuild())
+ {
+ return;
+ }
+ NavMeshTile navMeshTile = null;
+ float num = 0f;
+ foreach (NavMeshTile value in m_tiles.Values)
+ {
+ float num2 = value.m_pokeTime - value.m_buildTime;
+ if (num2 > m_updateInterval && (navMeshTile == null || num2 > num))
+ {
+ navMeshTile = value;
+ num = num2;
+ }
+ }
+ if (navMeshTile != null)
+ {
+ BuildTile(navMeshTile);
+ navMeshTile.m_buildTime = Time.realtimeSinceStartup;
+ }
+ }
+
+ private void BuildTile(NavMeshTile tile)
+ {
+ _ = DateTime.Now;
+ List<NavMeshBuildSource> list = new List<NavMeshBuildSource>();
+ List<NavMeshBuildMarkup> markups = new List<NavMeshBuildMarkup>();
+ AgentType z = (AgentType)tile.m_tile.z;
+ AgentSettings settings = GetSettings(z);
+ Bounds includedWorldBounds = new Bounds(tile.m_center, new Vector3(m_tileSize, 6000f, m_tileSize));
+ Bounds localBounds = new Bounds(Vector3.zero, new Vector3(m_tileSize, 6000f, m_tileSize));
+ int defaultArea = ((!settings.m_canWalk) ? 1 : 0);
+ NavMeshBuilder.CollectSources(includedWorldBounds, m_layers.value, NavMeshCollectGeometry.PhysicsColliders, defaultArea, markups, list);
+ if (settings.m_avoidWater)
+ {
+ List<NavMeshBuildSource> list2 = new List<NavMeshBuildSource>();
+ NavMeshBuilder.CollectSources(includedWorldBounds, m_waterLayers.value, NavMeshCollectGeometry.PhysicsColliders, 1, markups, list2);
+ foreach (NavMeshBuildSource item in list2)
+ {
+ NavMeshBuildSource current = item;
+ current.transform *= Matrix4x4.Translate(Vector3.down * 0.2f);
+ list.Add(current);
+ }
+ }
+ else if (settings.m_canSwim)
+ {
+ List<NavMeshBuildSource> list3 = new List<NavMeshBuildSource>();
+ NavMeshBuilder.CollectSources(includedWorldBounds, m_waterLayers.value, NavMeshCollectGeometry.PhysicsColliders, 3, markups, list3);
+ if (settings.m_swimDepth != 0f)
+ {
+ foreach (NavMeshBuildSource item2 in list3)
+ {
+ NavMeshBuildSource current2 = item2;
+ current2.transform *= Matrix4x4.Translate(Vector3.down * settings.m_swimDepth);
+ list.Add(current2);
+ }
+ }
+ else
+ {
+ list.AddRange(list3);
+ }
+ }
+ if (tile.m_data == null)
+ {
+ tile.m_data = new NavMeshData();
+ tile.m_data.position = tile.m_center;
+ }
+ m_buildOperation = NavMeshBuilder.UpdateNavMeshDataAsync(tile.m_data, settings.m_build, list, localBounds);
+ m_buildTile = tile;
+ }
+
+ private bool IsBuilding()
+ {
+ if (m_buildOperation != null)
+ {
+ return !m_buildOperation.isDone;
+ }
+ return false;
+ }
+
+ private bool UpdateAsyncBuild()
+ {
+ if (m_buildOperation == null)
+ {
+ return false;
+ }
+ if (!m_buildOperation.isDone)
+ {
+ return true;
+ }
+ if (!m_buildTile.m_instance.valid)
+ {
+ m_buildTile.m_instance = NavMesh.AddNavMeshData(m_buildTile.m_data);
+ }
+ RebuildLinks(m_buildTile);
+ m_buildOperation = null;
+ m_buildTile = null;
+ return true;
+ }
+
+ private void ClearLinks(NavMeshTile tile)
+ {
+ ClearLinks(tile.m_links1);
+ ClearLinks(tile.m_links2);
+ }
+
+ private void ClearLinks(List<KeyValuePair<Vector3, NavMeshLinkInstance>> links)
+ {
+ foreach (KeyValuePair<Vector3, NavMeshLinkInstance> link in links)
+ {
+ m_linkRemoveQueue.Enqueue(link.Value);
+ }
+ links.Clear();
+ }
+
+ private void RebuildLinks(NavMeshTile tile)
+ {
+ AgentType z = (AgentType)tile.m_tile.z;
+ AgentSettings settings = GetSettings(z);
+ float num = m_tileSize / 2f;
+ ConnectAlongEdge(tile.m_links1, tile.m_center + new Vector3(num, 0f, num), tile.m_center + new Vector3(num, 0f, 0f - num), m_linkWidth, settings);
+ ConnectAlongEdge(tile.m_links2, tile.m_center + new Vector3(0f - num, 0f, num), tile.m_center + new Vector3(num, 0f, num), m_linkWidth, settings);
+ }
+
+ private void ConnectAlongEdge(List<KeyValuePair<Vector3, NavMeshLinkInstance>> links, Vector3 p0, Vector3 p1, float step, AgentSettings settings)
+ {
+ Vector3 normalized = (p1 - p0).normalized;
+ Vector3 vector = Vector3.Cross(Vector3.up, normalized);
+ float num = Vector3.Distance(p0, p1);
+ bool canSwim = settings.m_canSwim;
+ tempStitchPoints.Clear();
+ for (float num2 = step / 2f; num2 <= num; num2 += step)
+ {
+ Vector3 p2 = p0 + normalized * num2;
+ FindGround(p2, canSwim, tempStitchPoints, settings);
+ }
+ if (CompareLinks(tempStitchPoints, links))
+ {
+ return;
+ }
+ ClearLinks(links);
+ foreach (Vector3 tempStitchPoint in tempStitchPoints)
+ {
+ NavMeshLinkData link = default(NavMeshLinkData);
+ link.startPosition = tempStitchPoint - vector * 0.1f;
+ link.endPosition = tempStitchPoint + vector * 0.1f;
+ link.width = step;
+ link.costModifier = m_linkCost;
+ link.bidirectional = true;
+ link.agentTypeID = settings.m_build.agentTypeID;
+ link.area = 2;
+ NavMeshLinkInstance value = NavMesh.AddLink(link);
+ if (value.valid)
+ {
+ links.Add(new KeyValuePair<Vector3, NavMeshLinkInstance>(tempStitchPoint, value));
+ }
+ }
+ }
+
+ private bool CompareLinks(List<Vector3> tempStitchPoints, List<KeyValuePair<Vector3, NavMeshLinkInstance>> links)
+ {
+ if (tempStitchPoints.Count != links.Count)
+ {
+ return false;
+ }
+ for (int i = 0; i < tempStitchPoints.Count; i++)
+ {
+ if (tempStitchPoints[i] != links[i].Key)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private bool SnapToNearestGround(Vector3 p, out Vector3 pos, float range)
+ {
+ if (Physics.Raycast(p + Vector3.up, Vector3.down, out var hitInfo, range + 1f, m_layers.value | m_waterLayers.value))
+ {
+ pos = hitInfo.point;
+ return true;
+ }
+ if (Physics.Raycast(p + Vector3.up * range, Vector3.down, out hitInfo, range, m_layers.value | m_waterLayers.value))
+ {
+ pos = hitInfo.point;
+ return true;
+ }
+ pos = p;
+ return false;
+ }
+
+ private void FindGround(Vector3 p, bool testWater, List<Vector3> hits, AgentSettings settings)
+ {
+ p.y = 6000f;
+ int layerMask = (testWater ? (m_layers.value | m_waterLayers.value) : m_layers.value);
+ float agentHeight = settings.m_build.agentHeight;
+ float y = p.y;
+ int num = Physics.RaycastNonAlloc(p, Vector3.down, tempHitArray, 10000f, layerMask);
+ for (int i = 0; i < num; i++)
+ {
+ Vector3 point = tempHitArray[i].point;
+ if (!(Mathf.Abs(point.y - y) < agentHeight))
+ {
+ y = point.y;
+ if (((1 << tempHitArray[i].collider.gameObject.layer) & (int)m_waterLayers) != 0)
+ {
+ point.y -= settings.m_swimDepth;
+ }
+ hits.Add(point);
+ }
+ }
+ }
+
+ private NavMeshTile GetNavTile(Vector3 point, AgentType agent)
+ {
+ Vector3Int tile = GetTile(point, agent);
+ return GetNavTile(tile);
+ }
+
+ private NavMeshTile GetNavTile(Vector3Int tile)
+ {
+ if (tile == m_cachedTileID)
+ {
+ return m_cachedTile;
+ }
+ if (m_tiles.TryGetValue(tile, out var value))
+ {
+ m_cachedTileID = tile;
+ m_cachedTile = value;
+ return value;
+ }
+ value = new NavMeshTile();
+ value.m_tile = tile;
+ value.m_center = GetTilePos(tile);
+ m_tiles.Add(tile, value);
+ m_cachedTileID = tile;
+ m_cachedTile = value;
+ return value;
+ }
+
+ private Vector3Int GetTile(Vector3 point, AgentType agent)
+ {
+ int x = Mathf.FloorToInt((point.x + m_tileSize / 2f) / m_tileSize);
+ int y = Mathf.FloorToInt((point.z + m_tileSize / 2f) / m_tileSize);
+ return new Vector3Int(x, y, (int)agent);
+ }
+
+ public Vector3 GetTilePos(Vector3Int id)
+ {
+ return new Vector3((float)id.x * m_tileSize, 2500f, (float)id.y * m_tileSize);
+ }
+}