Luke Stampfli
4 年前
当前提交
9ece9209
共有 8 个文件被更改,包括 324 次插入 和 0 次删除
-
8Assets/BossRoom/Scripts/Server/Navigation.meta
-
39Assets/BossRoom/Scripts/Server/Navigation/DynamicNavObstacle.cs
-
11Assets/BossRoom/Scripts/Server/Navigation/DynamicNavObstacle.cs.meta
-
195Assets/BossRoom/Scripts/Server/Navigation/DynamicNavPath.cs
-
11Assets/BossRoom/Scripts/Server/Navigation/DynamicNavPath.cs.meta
-
49Assets/BossRoom/Scripts/Server/Navigation/NavigationSystem.cs
-
11Assets/BossRoom/Scripts/Server/Navigation/NavigationSystem.cs.meta
|
|||
fileFormatVersion: 2 |
|||
guid: 651368061b0b5814f9a8b5deeb18c326 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using NUnit.Framework; |
|||
using UnityEngine; |
|||
using UnityEngine.AI; |
|||
|
|||
namespace BossRoom.Server |
|||
{ |
|||
[DefaultExecutionOrder(10000)] // The enable/disable trigger have to be called after the triggers from NavMeshObstacle which update the nav mesh.
|
|||
[RequireComponent(typeof(NavMeshObstacle))] |
|||
public sealed class DynamicNavObstacle : MonoBehaviour |
|||
{ |
|||
private NavigationSystem m_NavigationSystem; |
|||
|
|||
void Awake() |
|||
{ |
|||
m_NavigationSystem = GameObject.FindGameObjectWithTag(NavigationSystem.NavigationSytemTag).GetComponent<NavigationSystem>(); |
|||
} |
|||
|
|||
void OnValidate() |
|||
{ |
|||
if (gameObject.scene.rootCount > 1) // Hacky way for checking if this is a scene object or a prefab instance and not a prefab.
|
|||
{ |
|||
Assert.NotNull( |
|||
GameObject.FindGameObjectWithTag(NavigationSystem.NavigationSytemTag)?.GetComponent<NavigationSystem>(), |
|||
$"NavigationSystem not found. Is there a NavigationSystem Behaviour in the Scene and does its GameObject have the {NavigationSystem.NavigationSytemTag} tag?" |
|||
); |
|||
} |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
m_NavigationSystem.OnDynamicObstacleEnabled(); |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
m_NavigationSystem.OnDynamicObstacleDisabled(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b6ec113fefb19754c8dc3087500d9f1e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
using UnityEngine.AI; |
|||
|
|||
namespace BossRoom.Server |
|||
{ |
|||
public sealed class DynamicNavPath : IDisposable |
|||
{ |
|||
/// <summary>
|
|||
/// The tolerance to decide whether the path needs to be recalculated when the position of a target transform changed.
|
|||
/// </summary>
|
|||
private const float k_RepathToleranceSqr = 9f; |
|||
|
|||
private NavMeshAgent m_Agent; |
|||
|
|||
private NavigationSystem m_NavigationSystem; |
|||
|
|||
/// <summary>
|
|||
/// The target position value which was used to calculate the current path.
|
|||
/// This get stored to make sure the path gets recalculated if the target
|
|||
/// </summary>
|
|||
private Vector3 m_CurrentPathOriginalTarget; |
|||
|
|||
/// <summary>
|
|||
/// This field caches a NavMesh Path so that we don't have to allocate a new one each time.
|
|||
/// </summary>
|
|||
private NavMeshPath m_navMeshPath; |
|||
|
|||
/// <summary>
|
|||
/// The remaining path points to follow to reach the target position.
|
|||
/// </summary>
|
|||
private List<Vector3> m_Path; |
|||
|
|||
/// <summary>
|
|||
/// The target position of this path.
|
|||
/// </summary>
|
|||
private Vector3 m_PositionTarget; |
|||
|
|||
/// <summary>
|
|||
/// A moving transform target, the path will readjust when the target moves.
|
|||
/// </summary>
|
|||
private Transform m_TransformTarget; |
|||
|
|||
/// <summary>
|
|||
/// If true the path tracks a moving transform target (<see cref="m_TransformTarget"/>). If false it points to a static position target (<see cref="m_PositionTarget"/>.
|
|||
/// </summary>
|
|||
private bool m_HasTransformTarget; |
|||
|
|||
/// <summary>
|
|||
/// Creates a new instance of the <see cref="DynamicNavPath"./>
|
|||
/// </summary>
|
|||
/// <param name="agent">The NavMeshAgent of the object which uses this path.</param>
|
|||
public DynamicNavPath(NavMeshAgent agent, NavigationSystem navigationSystem) |
|||
{ |
|||
m_Agent = agent; |
|||
m_Path = new List<Vector3>(); |
|||
m_navMeshPath = new NavMeshPath(); |
|||
m_NavigationSystem = navigationSystem; |
|||
|
|||
navigationSystem.OnNavigationMeshChanged += OnNavMeshChanged; |
|||
} |
|||
|
|||
private Vector3 TargetPosition => m_HasTransformTarget ? m_TransformTarget.position : m_PositionTarget; |
|||
|
|||
/// <summary>
|
|||
/// Set the target of this path to follow a moving transform.
|
|||
/// </summary>
|
|||
/// <param name="target">The transform to follow.</param>
|
|||
public void FollowTransform(Transform target) |
|||
{ |
|||
m_TransformTarget = target; |
|||
m_HasTransformTarget = true; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Set the target of this path to a static position target.
|
|||
/// </summary>
|
|||
/// <param name="target">The target position.</param>
|
|||
public void SetTargetPosition(Vector3 target) |
|||
{ |
|||
// If there is an nav mesh area close to the target use a point inside the nav mesh instead.
|
|||
if (NavMesh.SamplePosition(target, out NavMeshHit hit, 2f, NavMesh.AllAreas)) |
|||
{ |
|||
target = hit.position; |
|||
} |
|||
|
|||
m_PositionTarget = target; |
|||
m_HasTransformTarget = false; |
|||
RecalculatePath(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Call this to recalculate the path when the navigation mesh or dynamic obstacles changed.
|
|||
/// </summary>
|
|||
public void OnNavMeshChanged() |
|||
{ |
|||
RecalculatePath(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clears the path.
|
|||
/// </summary>
|
|||
public void Clear() |
|||
{ |
|||
m_Path.Clear(); |
|||
; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the movement vector for moving this object while following the path. This function changes the state of the path and should only be called once per tick.
|
|||
/// </summary>
|
|||
/// <param name="distance">The distance to move.</param>
|
|||
/// <returns>Returns the movement vector.</returns>
|
|||
public Vector3 MoveAlongPath(float distance) |
|||
{ |
|||
if (m_HasTransformTarget) |
|||
{ |
|||
OnTargetPositionChanged(TargetPosition); |
|||
} |
|||
|
|||
if (m_Path.Count == 0) |
|||
{ |
|||
return Vector3.zero; |
|||
} |
|||
|
|||
Vector3 currentPredictedPosition = m_Agent.transform.position; |
|||
float remainingDistance = distance; |
|||
|
|||
while (remainingDistance > 0) |
|||
{ |
|||
var toNextPathPoint = m_Path[0] - currentPredictedPosition; |
|||
|
|||
// If end point is closer then distance to move
|
|||
if (toNextPathPoint.sqrMagnitude < remainingDistance * remainingDistance) |
|||
{ |
|||
currentPredictedPosition = m_Path[0]; |
|||
m_Path.RemoveAt(0); |
|||
remainingDistance -= toNextPathPoint.magnitude; |
|||
} |
|||
|
|||
// Move towards point
|
|||
currentPredictedPosition += toNextPathPoint.normalized * remainingDistance; |
|||
|
|||
// There is definitely no remaining distance to cover here.
|
|||
break; |
|||
} |
|||
|
|||
return currentPredictedPosition - m_Agent.transform.position; |
|||
} |
|||
|
|||
private void OnTargetPositionChanged(Vector3 newTarget) |
|||
{ |
|||
if (m_Path.Count == 0) |
|||
{ |
|||
RecalculatePath(); |
|||
} |
|||
|
|||
if ((newTarget - m_CurrentPathOriginalTarget).sqrMagnitude > k_RepathToleranceSqr) |
|||
{ |
|||
RecalculatePath(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Recalculates the cached navigationPath
|
|||
/// </summary>
|
|||
private void RecalculatePath() |
|||
{ |
|||
m_CurrentPathOriginalTarget = TargetPosition; |
|||
m_Agent.CalculatePath(TargetPosition, m_navMeshPath); |
|||
|
|||
m_Path.Clear(); |
|||
|
|||
var corners = m_navMeshPath.corners; |
|||
|
|||
for (int i = 1; i < corners.Length; i++) // Skip the first corner because it is the starting point.
|
|||
{ |
|||
m_Path.Add(corners[i]); |
|||
} |
|||
|
|||
// If the path is still empty here then the target position wasn't on the nav mesh.
|
|||
if (m_Path.Count == 0) |
|||
{ |
|||
// In that case we just create a linear path directly to the target.
|
|||
m_Path.Add(TargetPosition); |
|||
} |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
m_NavigationSystem.OnNavigationMeshChanged -= OnNavMeshChanged; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a2e049b0198c3064cb8f88789fc28809 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using NUnit.Framework; |
|||
using UnityEngine; |
|||
|
|||
namespace BossRoom.Server |
|||
{ |
|||
/// <summary>
|
|||
/// This system exists to coordinate path finding and navigation functionality in a scene.
|
|||
/// The Unity NavMesh is only used to calculate navigation paths. Moving along those paths is done by this system.
|
|||
/// </summary>
|
|||
public class NavigationSystem : MonoBehaviour |
|||
{ |
|||
public const string NavigationSytemTag = "NavigationSystem"; |
|||
|
|||
/// <summary>
|
|||
/// Event that gets invoked when the navigation mesh changed. This happens when dynamic obstacles move or get active
|
|||
/// </summary>
|
|||
public event System.Action OnNavigationMeshChanged; |
|||
|
|||
/// <summary>
|
|||
/// Whether all paths need to be recalculated in the next fixed update.
|
|||
/// </summary>
|
|||
private bool navMeshChanged; |
|||
|
|||
public void OnDynamicObstacleDisabled() |
|||
{ |
|||
navMeshChanged = true; |
|||
} |
|||
|
|||
public void OnDynamicObstacleEnabled() |
|||
{ |
|||
navMeshChanged = true; |
|||
} |
|||
|
|||
private void FixedUpdate() |
|||
{ |
|||
// This is done in fixed update to make sure that only one expensive global recalculation happens per fixed update.
|
|||
if (navMeshChanged) |
|||
{ |
|||
OnNavigationMeshChanged?.Invoke(); |
|||
navMeshChanged = false; |
|||
} |
|||
} |
|||
|
|||
private void OnValidate() |
|||
{ |
|||
Assert.AreEqual(NavigationSytemTag, tag, $"The GameObject of the {nameof(NavigationSystem)} component has to use the {NavigationSystem.NavigationSytemTag} tag!"); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e122c40e3a857a242915a4cece2ad208 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue