init
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using Unity.AI.Navigation;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
using VOID.Generic.Objects.Traversable;
|
||||
|
||||
namespace VOID.Generic.Navigation
|
||||
{
|
||||
[RequireComponent(typeof(NavMeshSurface))]
|
||||
[DefaultExecutionOrder(-1)]
|
||||
public class NavigationManager : MonoBehaviour
|
||||
{
|
||||
public static NavigationManager current { get; private set; }
|
||||
|
||||
private const float NavMeshLinkThreshold = 0.01f;
|
||||
|
||||
// NavMesh data
|
||||
private NavMeshSurface _navMeshSurface;
|
||||
private NavMeshBuildSettings _navMeshBuildSettings;
|
||||
|
||||
// Cached links
|
||||
private Dictionary<Vector2Int, Dictionary<Vector3, TraversableObject>> _linksPerTile;
|
||||
private Dictionary<Vector3, bool> _isPositionStart;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
current = this;
|
||||
_navMeshSurface = gameObject.GetComponent<NavMeshSurface>();
|
||||
_navMeshBuildSettings = _navMeshSurface.GetBuildSettings();
|
||||
_navMeshBuildSettings.preserveTilesOutsideBounds = true;
|
||||
_linksPerTile = new Dictionary<Vector2Int, Dictionary<Vector3, TraversableObject>>();
|
||||
_isPositionStart = new Dictionary<Vector3, bool>();
|
||||
}
|
||||
|
||||
public void BuildNavMesh()
|
||||
{
|
||||
_navMeshSurface.BuildNavMesh();
|
||||
}
|
||||
|
||||
[Button]
|
||||
public void UpdateNavMesh(Bounds bounds)
|
||||
{
|
||||
bounds.extents += Vector3.one * GetTileSize();
|
||||
NavMeshBuilder.UpdateNavMeshData(
|
||||
_navMeshSurface.navMeshData,
|
||||
_navMeshBuildSettings,
|
||||
GetSources(bounds),
|
||||
bounds
|
||||
);
|
||||
}
|
||||
|
||||
private static List<NavMeshBuildSource> GetSources(Bounds bounds)
|
||||
{
|
||||
var sources = new List<NavMeshBuildSource>();
|
||||
NavMeshBuilder.CollectSources(
|
||||
bounds,
|
||||
LayerManager.Static | LayerManager.NavModifier,
|
||||
NavMeshCollectGeometry.RenderMeshes,
|
||||
0,
|
||||
GetMarkups(),
|
||||
sources
|
||||
);
|
||||
AppendSourcesWithModifierVolume(ref sources);
|
||||
return sources;
|
||||
}
|
||||
|
||||
private static List<NavMeshBuildMarkup> GetMarkups()
|
||||
{
|
||||
var markups = new List<NavMeshBuildMarkup>();
|
||||
foreach (var modifier in NavMeshModifier.activeModifiers)
|
||||
{
|
||||
var markup = new NavMeshBuildMarkup();
|
||||
markup.root = modifier.transform;
|
||||
markup.overrideArea = modifier.overrideArea;
|
||||
markup.area = modifier.area;
|
||||
markup.ignoreFromBuild = modifier.ignoreFromBuild;
|
||||
markups.Add(markup);
|
||||
}
|
||||
return markups;
|
||||
}
|
||||
|
||||
private static void AppendSourcesWithModifierVolume(ref List<NavMeshBuildSource> sources)
|
||||
{
|
||||
foreach (var modifier in NavMeshModifierVolume.activeModifiers)
|
||||
{
|
||||
var mcenter = modifier.transform.TransformPoint(modifier.center);
|
||||
var scale = modifier.transform.lossyScale;
|
||||
var msize = new Vector3(modifier.size.x * Mathf.Abs(scale.x), modifier.size.y * Mathf.Abs(scale.y), modifier.size.z * Mathf.Abs(scale.z));
|
||||
|
||||
var src = new NavMeshBuildSource();
|
||||
src.shape = NavMeshBuildSourceShape.ModifierBox;
|
||||
src.transform = Matrix4x4.TRS(mcenter, modifier.transform.rotation, Vector3.one);
|
||||
src.size = msize;
|
||||
src.area = modifier.area;
|
||||
sources.Add(src);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets cached TraversableObject at given point.
|
||||
/// </summary>
|
||||
/// <param name="pos">Check point for TraversableObject</param>
|
||||
/// <param name="traversable">returns found traversable</param>
|
||||
/// <param name="isReverse">returns bool if this is point is from link's end</param>
|
||||
/// <returns>Boolean if traversable is found.</returns>
|
||||
public bool GetCachedTraversable(Vector3 pos, out TraversableObject traversable, out bool isReverse)
|
||||
{
|
||||
var index = GetTileIndex(pos);
|
||||
if (!_linksPerTile.ContainsKey(index))
|
||||
{
|
||||
traversable = null;
|
||||
isReverse = false;
|
||||
return false;
|
||||
}
|
||||
var foundPair = _linksPerTile[index].FirstOrDefault(pair =>
|
||||
{
|
||||
var position = pair.Key;
|
||||
return Vector3.Distance(position, pos) < NavMeshLinkThreshold;
|
||||
});
|
||||
traversable = foundPair.Value;
|
||||
isReverse = !_isPositionStart.GetValueOrDefault(foundPair.Key);
|
||||
return traversable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache both points of TraversableObject. Alias for:
|
||||
/// <see cref="RegisterTraversable(Vector3, TraversableObject, bool)" />
|
||||
/// </summary>
|
||||
public void RegisterTraversable(TraversableObject traversable)
|
||||
{
|
||||
var startPosition = traversable.traversableData.linkStartPosition;
|
||||
var endPosition = traversable.traversableData.linkEndPosition;
|
||||
RegisterTraversable(startPosition, traversable, true);
|
||||
RegisterTraversable(endPosition, traversable, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache given TraversableObject at given point.
|
||||
/// </summary>
|
||||
/// <param name="position">At which position, also it calculates into position index.</param>
|
||||
/// <param name="traversable">Which traversable will be cached.</param>
|
||||
/// <param name="isStart">Is given point start link? Otherwise it is end.</param>
|
||||
public void RegisterTraversable(Vector3 position, TraversableObject traversable, bool isStart)
|
||||
{
|
||||
var index = GetTileIndex(position);
|
||||
if (!_linksPerTile.ContainsKey(index))
|
||||
_linksPerTile[index] = new Dictionary<Vector3, TraversableObject>();
|
||||
_linksPerTile[index].Add(position, traversable);
|
||||
_isPositionStart.Add(position, isStart);
|
||||
}
|
||||
|
||||
private float GetTileSize()
|
||||
{
|
||||
return _navMeshBuildSettings.tileSize * _navMeshBuildSettings.voxelSize;
|
||||
}
|
||||
|
||||
private Vector2Int GetTileIndex(Vector3 pos)
|
||||
{
|
||||
return new Vector2Int()
|
||||
{
|
||||
x = Mathf.FloorToInt(pos.x / GetTileSize()),
|
||||
y = Mathf.FloorToInt(pos.z / GetTileSize()),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user