移除ECM2

This commit is contained in:
2025-05-11 21:42:51 +08:00
parent aadd564c38
commit a7bf033ca9
726 changed files with 0 additions and 138648 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 8a5e05c5b0509214d911dd005a610d9a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,401 +0,0 @@
using UnityEngine;
using UnityEngine.AI;
namespace ECM2
{
/// <summary>
/// This component extends a Character (through composition) adding navigation capabilities using a NavMeshAgent.
/// This replaces the previous AgentCharacter class.
/// </summary>
[RequireComponent(typeof(Character)), RequireComponent(typeof(NavMeshAgent))]
public class NavMeshCharacter : MonoBehaviour
{
#region EDITOR EXPOSED FIELDS
[Space(15f)]
[Tooltip("Should the agent brake automatically to avoid overshooting the destination point? \n" +
"If true, the agent will brake automatically as it nears the destination.")]
[SerializeField]
private bool _autoBraking;
[Tooltip("Distance from target position to start braking.")]
[SerializeField]
private float _brakingDistance;
[Tooltip("Stop within this distance from the target position.")]
[SerializeField]
private float _stoppingDistance;
#endregion
#region FIELDS
private NavMeshAgent _agent;
private Character _character;
#endregion
#region PROPERTIES
/// <summary>
/// Cached NavMeshAgent component.
/// </summary>
public NavMeshAgent agent => _agent;
/// <summary>
/// Cached Character component.
/// </summary>
public Character character => _character;
/// <summary>
/// Should the agent brake automatically to avoid overshooting the destination point?
/// If this property is set to true, the agent will brake automatically as it nears the destination.
/// </summary>
public bool autoBraking
{
get => _autoBraking;
set
{
_autoBraking = value;
agent.autoBraking = _autoBraking;
}
}
/// <summary>
/// Distance from target position to start braking.
/// </summary>
public float brakingDistance
{
get => _brakingDistance;
set => _brakingDistance = Mathf.Max(0.0001f, value);
}
/// <summary>
/// The ratio (0 - 1 range) of the agent's remaining distance and the braking distance.
/// 1 If no auto braking or if agent's remaining distance is greater than brakingDistance.
/// less than 1, if agent's remaining distance is less than brakingDistance.
/// </summary>
public float brakingRatio
{
get
{
if (!autoBraking)
return 1f;
return agent.hasPath ? Mathf.InverseLerp(0.0f, brakingDistance, agent.remainingDistance) : 1.0f;
}
}
/// <summary>
/// Stop within this distance from the target position.
/// </summary>
public float stoppingDistance
{
get => _stoppingDistance;
set
{
_stoppingDistance = Mathf.Max(0.0f, value);
agent.stoppingDistance = _stoppingDistance;
}
}
#endregion
#region EVENTS
public delegate void DestinationReachedEventHandler();
/// <summary>
/// Event triggered when agent reaches its destination.
/// </summary>
public event DestinationReachedEventHandler DestinationReached;
/// <summary>
/// Trigger DestinationReached event.
/// Called when agent reaches its destination.
/// </summary>
public virtual void OnDestinationReached()
{
DestinationReached?.Invoke();
}
#endregion
#region METHODS
/// <summary>
/// Cache used components.
/// </summary>
protected virtual void CacheComponents()
{
_agent = GetComponent<NavMeshAgent>();
_character = GetComponent<Character>();
}
/// <summary>
/// Does the Agent currently has a path?
/// </summary>
public virtual bool HasPath()
{
return agent.hasPath;
}
/// <summary>
/// True if Agent is following a path, false otherwise.
/// </summary>
public virtual bool IsPathFollowing()
{
return agent.hasPath && !agent.isStopped;
}
/// <summary>
/// Returns the destination set for this agent.
/// If a destination is set but the path is not yet processed,
/// the returned position will be valid navmesh position that's closest to the previously set position.
/// If the agent has no path or requested path - returns the agents position on the navmesh.
/// If the agent is not mapped to the navmesh (e.g. Scene has no navmesh) - returns a position at infinity.
/// </summary>
public virtual Vector3 GetDestination()
{
return agent.destination;
}
/// <summary>
/// Requests the character to move to the valid navmesh position that's closest to the requested destination.
/// </summary>
public virtual void MoveToDestination(Vector3 destination)
{
Vector3 worldUp = -character.GetGravityDirection();
Vector3 toDestination2D = Vector3.ProjectOnPlane(destination - character.position, worldUp);
if (toDestination2D.sqrMagnitude >= MathLib.Square(stoppingDistance))
agent.SetDestination(destination);
}
/// <summary>
/// Pause / Resume Character path following movement.
/// If set to True, the character's movement will be stopped along its current path.
/// If set to False after the character has stopped, it will resume moving along its current path.
/// </summary>
public virtual void PauseMovement(bool pause)
{
agent.isStopped = pause;
character.SetMovementDirection(Vector3.zero);
}
/// <summary>
/// Halts Character's current path following movement.
/// This will clear agent's current path.
/// </summary>
public virtual void StopMovement()
{
agent.ResetPath();
character.SetMovementDirection(Vector3.zero);
}
/// <summary>
/// Computes the analog input modifier (0.0f to 1.0f) based on Character's max speed and given desired velocity.
/// </summary>
protected virtual float ComputeAnalogInputModifier(Vector3 desiredVelocity)
{
float maxSpeed = _character.GetMaxSpeed();
if (desiredVelocity.sqrMagnitude > 0.0f && maxSpeed > 0.00000001f)
return Mathf.Clamp01(desiredVelocity.magnitude / maxSpeed);
return 0.0f;
}
/// <summary>
/// Calculates Character movement direction from a given desired velocity factoring (if enabled) auto braking.
/// </summary>
protected virtual Vector3 CalcMovementDirection(Vector3 desiredVelocity)
{
Vector3 worldUp = -character.GetGravityDirection();
Vector3 desiredVelocity2D = Vector3.ProjectOnPlane(desiredVelocity, worldUp);
Vector3 scaledDesiredVelocity2D = desiredVelocity2D * brakingRatio;
float minAnalogSpeed = _character.GetMinAnalogSpeed();
if (scaledDesiredVelocity2D.sqrMagnitude < MathLib.Square(minAnalogSpeed))
scaledDesiredVelocity2D = scaledDesiredVelocity2D.normalized * minAnalogSpeed;
return Vector3.ClampMagnitude(scaledDesiredVelocity2D, ComputeAnalogInputModifier(scaledDesiredVelocity2D));
}
/// <summary>
/// Makes the character's follow Agent's path (if any).
/// Eg: Keep updating Character's movement direction vector to steer towards Agent's destination until reached.
/// </summary>
protected virtual void DoPathFollowing()
{
if (!IsPathFollowing())
return;
// Is destination reached ?
if (agent.remainingDistance <= stoppingDistance)
{
// Destination is reached, stop movement
StopMovement();
// Trigger event
OnDestinationReached();
}
else
{
// If destination not reached, request a Character to move towards agent's desired velocity direction
Vector3 movementDirection = CalcMovementDirection(agent.desiredVelocity);
character.SetMovementDirection(movementDirection);
}
}
/// <summary>
/// Synchronize the NavMeshAgent with Character (eg: speed, acceleration, velocity, etc) as we moves the Agent.
/// </summary>
protected virtual void SyncNavMeshAgent()
{
agent.angularSpeed = _character.rotationRate;
agent.speed = _character.GetMaxSpeed();
agent.acceleration = _character.GetMaxAcceleration();
agent.velocity = _character.GetVelocity();
agent.nextPosition = _character.GetPosition();
agent.radius = _character.radius;
agent.height = _character.height;
}
/// <summary>
/// On MovementMode change, stop agent movement if character is not walking or falling.
/// </summary>
protected virtual void OnMovementModeChanged(Character.MovementMode prevMovementMode, int prevCustomMovementMode)
{
if (!character.IsWalking() || !character.IsFalling())
{
StopMovement();
}
}
/// <summary>
/// While Character has a valid path, do path following.
/// </summary>
protected virtual void OnBeforeSimulationUpdated(float deltaTime)
{
DoPathFollowing();
}
#endregion
#region MONOBEHAVIOUR
/// <summary>
/// If overriden, base method MUST be called.
/// </summary>
private void Reset()
{
_autoBraking = true;
_brakingDistance = 2.0f;
_stoppingDistance = 1.0f;
}
/// <summary>
/// If overriden, base method MUST be called.
/// </summary>
private void OnValidate()
{
if (_agent == null)
_agent = GetComponent<NavMeshAgent>();
brakingDistance = _brakingDistance;
stoppingDistance = _stoppingDistance;
}
/// <summary>
/// If overriden, base method MUST be called.
/// </summary>
protected virtual void Awake()
{
// Cache used components
CacheComponents();
// Initialize NavMeshAgent
agent.autoBraking = autoBraking;
agent.stoppingDistance = stoppingDistance;
// Turn-off NavMeshAgent auto-control,
// we control it (see SyncNavMeshAgent method)
agent.updatePosition = false;
agent.updateRotation = false;
agent.updateUpAxis = false;
}
/// <summary>
/// If overriden, base method MUST be called.
/// </summary>
protected virtual void OnEnable()
{
// Subscribe to Character events
character.MovementModeChanged += OnMovementModeChanged;
character.BeforeSimulationUpdated += OnBeforeSimulationUpdated;
}
/// <summary>
/// If overriden, base method MUST be called.
/// </summary>
protected virtual void OnDisable()
{
// Un-Subscribe to Character events
character.MovementModeChanged -= OnMovementModeChanged;
character.BeforeSimulationUpdated -= OnBeforeSimulationUpdated;
}
/// <summary>
/// If overriden, base method MUST be called.
/// </summary>
protected virtual void LateUpdate()
{
SyncNavMeshAgent();
}
#endregion
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 0b8353732406ae7418b47f5928e333c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,142 +0,0 @@
using UnityEngine;
namespace ECM2
{
/// <summary>
/// Helper component used to define physics volumes like water, air, oil, etc.
/// Characters will react according to this settings when inside this volume.
/// </summary>
[RequireComponent(typeof(BoxCollider))]
public class PhysicsVolume : MonoBehaviour
{
#region EDITOR EXPOSED FIELDS
[Tooltip("Determines which PhysicsVolume takes precedence if they overlap (higher value == higher priority).")]
[SerializeField]
private int _priority;
[Tooltip("Determines the amount of friction applied by the volume as Character using CharacterMovement moves through it.\n" +
"The higher this value, the harder it will feel to move through the volume.")]
[SerializeField]
private float _friction;
[Tooltip("Determines the terminal velocity of Characters using CharacterMovement when falling.")]
[SerializeField]
private float _maxFallSpeed;
[Tooltip("Determines if the volume contains a fluid, like water.")]
[SerializeField]
private bool _waterVolume;
#endregion
#region FIELDS
private BoxCollider _collider;
#endregion
#region PROPERTIES
/// <summary>
/// This volume collider (trigger).
/// </summary>
public BoxCollider boxCollider
{
get
{
if (_collider == null)
_collider = GetComponent<BoxCollider>();
return _collider;
}
}
/// <summary>
/// Determines which PhysicsVolume takes precedence if they overlap (higher value == higher priority).
/// </summary>
public int priority
{
get => _priority;
set => _priority = value;
}
/// <summary>
/// Determines the amount of friction applied by the volume as Character's using CharacterMovement move through it.
/// The higher this value, the harder it will feel to move through the volume.
/// </summary>
public float friction
{
get => _friction;
set => _friction = Mathf.Max(0.0f, value);
}
/// <summary>
/// Determines the terminal velocity of Character's using CharacterMovement when falling.
/// </summary>
public float maxFallSpeed
{
get => _maxFallSpeed;
set => _maxFallSpeed = Mathf.Max(0.0f, value);
}
/// <summary>
/// Determines if the volume contains a fluid, like water.
/// </summary>
public bool waterVolume
{
get => _waterVolume;
set => _waterVolume = value;
}
#endregion
#region METHODS
protected virtual void OnReset()
{
priority = 0;
friction = 0.5f;
maxFallSpeed = 40.0f;
waterVolume = true;
}
protected virtual void OnOnValidate()
{
friction = _friction;
maxFallSpeed = _maxFallSpeed;
}
protected virtual void OnAwake()
{
boxCollider.isTrigger = true;
}
#endregion
#region MONOBEHAVIOUR
private void Reset()
{
OnReset();
}
private void OnValidate()
{
OnOnValidate();
}
private void Awake()
{
OnAwake();
}
#endregion
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4a7a95050e56c7e4f976c906ecd1a941
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,113 +0,0 @@
using UnityEngine;
namespace ECM2
{
/// <summary>
/// The slope behaviour for attached collider.
/// </summary>
public enum SlopeBehaviour
{
Default,
/// <summary>
/// Sets the collider as walkable.
/// </summary>
Walkable,
/// <summary>
/// Sets the collider as not walkable.
/// </summary>
NotWalkable,
/// <summary>
/// Let you specify a custom slope limit value for collider.
/// </summary>
Override
}
/// <summary>
/// Overrides a CharacterMovement SlopeLimit property allowing to define per-object behaviour instead of per face.
/// This enable you to tweak what surfaces Characters can walk up. Perhaps a stair case is too steep or
/// maybe you want to enforce the "no walking on the grass" signs, these settings will enable you to do so.
/// </summary>
public sealed class SlopeLimitBehaviour : MonoBehaviour
{
#region EDITOR EXPOSED FIELDS
[Tooltip("The desired behaviour.")]
[SerializeField]
private SlopeBehaviour _slopeBehaviour = SlopeBehaviour.Default;
[SerializeField]
private float _slopeLimit;
#endregion
#region FIELDS
[SerializeField, HideInInspector]
private float _slopeLimitCos;
#endregion
#region PROPERTIES
/// <summary>
/// The current behaviour.
/// </summary>
public SlopeBehaviour walkableSlopeBehaviour
{
get => _slopeBehaviour;
set => _slopeBehaviour = value;
}
/// <summary>
/// The slope limit angle in degrees.
/// </summary>
public float slopeLimit
{
get => _slopeLimit;
set
{
_slopeLimit = Mathf.Clamp(value, 0.0f, 89.0f);
_slopeLimitCos = Mathf.Cos(_slopeLimit * Mathf.Deg2Rad);
}
}
/// <summary>
/// The cosine of slope angle (in radians), this is used to faster angle tests (e.g. dotProduct > slopeLimitCos)
/// </summary>
public float slopeLimitCos
{
get => _slopeLimitCos;
set
{
_slopeLimitCos = Mathf.Clamp01(value);
_slopeLimit = Mathf.Clamp(Mathf.Acos(_slopeLimitCos) * Mathf.Rad2Deg, 0.0f, 89.0f);
}
}
#endregion
#region MONOBEHAVIOUR
private void OnValidate()
{
slopeLimit = _slopeLimit;
}
#endregion
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2843c82a9ca85424b925fc897391f62d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: