added ground profiles
This commit is contained in:
parent
73a23861a4
commit
fd75d7e2d2
@ -14,22 +14,22 @@ namespace Intrepid.Core.Entities
|
|||||||
[GroupInjections, SerializeField] private Entity entity;
|
[GroupInjections, SerializeField] private Entity entity;
|
||||||
[GroupConfigurations, SerializeField] private LayerMask groundMask;
|
[GroupConfigurations, SerializeField] private LayerMask groundMask;
|
||||||
|
|
||||||
|
[GroupConfigurations, SerializeField] private bool inheritGroundMotionY;
|
||||||
[GroupConfigurations, SerializeField] private float groundCheckHeight = 1.0f;
|
[GroupConfigurations, SerializeField] private float groundCheckHeight = 1.0f;
|
||||||
[GroupConfigurations, SerializeField] private float groundCheckDistance = 3.0f;
|
[GroupConfigurations, SerializeField] private float groundCheckDistance = 3.0f;
|
||||||
[GroupConfigurations, SerializeField] private float groundOffset;
|
[GroupConfigurations, SerializeField] private float groundOffset;
|
||||||
[GroupConfigurations, SerializeField] private float maxSlopeAngle = 45f;
|
[GroupConfigurations, SerializeField] private float maxSlopeAngle = 45f;
|
||||||
[GroupConfigurations, SerializeField] private float groundProbeRadiusGrounded = 0.5f;
|
[GroupConfigurations, SerializeField] private float groundProbeRadiusGrounded = 0.5f;
|
||||||
[GroupConfigurations, SerializeField] private float groundProbeRadiusFalling = 0.2f;
|
[GroupConfigurations, SerializeField] private float groundProbeRadiusFalling = 0.2f;
|
||||||
[GroupConfigurations, SerializeField] private float fallingGroundCheckDistance = 20f;
|
[GroupConfigurations, SerializeField] private float fallingGroundCheckDistance = 150f;
|
||||||
[GroupConfigurations, SerializeField] private float minFallHeight = 0.25f;
|
[GroupConfigurations, SerializeField] private float minFallHeight = 0.25f;
|
||||||
[GroupConfigurations, SerializeField] private float fallAcceleration = 35f;
|
[GroupConfigurations, SerializeField] private float fallAcceleration = 35f;
|
||||||
[GroupConfigurations, SerializeField] private float maxFallSpeed = 18f;
|
[GroupConfigurations, SerializeField] private float maxFallSpeed = 18f;
|
||||||
|
|
||||||
|
|
||||||
private Vector3 Origin { get; set; }
|
private Vector3 Origin { get; set; }
|
||||||
private Vector3 End { get; set; }
|
private Vector3 End { get; set; }
|
||||||
private bool HasHit { get; set; }
|
private bool HasHit { get; set; }
|
||||||
|
private GroundProfiles _currentGroundProfiles = GroundProfiles.None;
|
||||||
private float _fallVerticalSpeed;
|
private float _fallVerticalSpeed;
|
||||||
private RaycastHit _groundHit;
|
private RaycastHit _groundHit;
|
||||||
private float GroundProbeRadius => IsFalling || IsFallingToAbyss
|
private float GroundProbeRadius => IsFalling || IsFallingToAbyss
|
||||||
@ -48,6 +48,7 @@ namespace Intrepid.Core.Entities
|
|||||||
{
|
{
|
||||||
IsFalling = false;
|
IsFalling = false;
|
||||||
IsFallingToAbyss = false;
|
IsFallingToAbyss = false;
|
||||||
|
_currentGroundProfiles = GroundProfiles.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Move(
|
public void Move(
|
||||||
@ -60,9 +61,9 @@ namespace Intrepid.Core.Entities
|
|||||||
|
|
||||||
if (IsFallingToAbyss)
|
if (IsFallingToAbyss)
|
||||||
{
|
{
|
||||||
return; // there is no movement from here....
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFalling)
|
if (IsFalling)
|
||||||
{
|
{
|
||||||
var nextFalling = ResolveFallingPosition(current, deltaTime);
|
var nextFalling = ResolveFallingPosition(current, deltaTime);
|
||||||
@ -71,19 +72,29 @@ namespace Intrepid.Core.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
var movementVelocity = ResolveMovementVelocity(velocity);
|
var movementVelocity = ResolveMovementVelocity(velocity);
|
||||||
var next = current + movementVelocity * deltaTime;
|
var groundMotionDelta = ResolveGroundMotionDelta();
|
||||||
if (TryGetGroundSurfaceAt(next, out _groundHit, out var nextNormal))
|
|
||||||
|
var next = current
|
||||||
|
+ groundMotionDelta
|
||||||
|
+ movementVelocity * deltaTime;
|
||||||
|
|
||||||
|
if (TryGetGroundSurfaceAt(next, out _groundHit, out var nextNormal, out var groundProfiles))
|
||||||
{
|
{
|
||||||
IsGrounded = true;
|
IsGrounded = true;
|
||||||
IsFallingToAbyss = false;
|
IsFallingToAbyss = false;
|
||||||
|
|
||||||
|
_currentGroundProfiles = groundProfiles;
|
||||||
|
|
||||||
RegisterStableGroundNormal(nextNormal);
|
RegisterStableGroundNormal(nextNormal);
|
||||||
|
|
||||||
next.y = _groundHit.point.y + groundOffset;
|
next.y = _groundHit.point.y + groundOffset;
|
||||||
|
|
||||||
LastSafeGroundPosition = new Vector3(
|
LastSafeGroundPosition = new Vector3(
|
||||||
next.x,
|
next.x,
|
||||||
_groundHit.point.y + groundOffset,
|
next.y,
|
||||||
next.z
|
next.z
|
||||||
);
|
);
|
||||||
|
|
||||||
if (IsFalling)
|
if (IsFalling)
|
||||||
{
|
{
|
||||||
IsFalling = false;
|
IsFalling = false;
|
||||||
@ -93,17 +104,14 @@ namespace Intrepid.Core.Entities
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (options.KeepHeightWhenNoGround) // that is probable an ability like sentinel dash, or enemy jump...
|
else if (options.KeepHeightWhenNoGround)
|
||||||
{
|
{
|
||||||
IsGrounded = false;
|
IsGrounded = false;
|
||||||
IsFalling = false;
|
IsFalling = false;
|
||||||
IsFallingToAbyss = false;
|
IsFallingToAbyss = false;
|
||||||
// Important:
|
_currentGroundProfiles = GroundProfiles.None;
|
||||||
// Do not set next.y = current.y here.
|
|
||||||
// The Y value has already been produced by the velocity projected onto the last stable ground normal.
|
|
||||||
// While crossing gaps, the entity keeps moving along the last GroundSurface plane.
|
|
||||||
}
|
}
|
||||||
else if (TryAnyGroundSurfaceBelowAt(next, out var fallHit, out _)
|
else if (TryAnyGroundSurfaceBelowAt(next, out var fallHit, out _, out _)
|
||||||
&& IsGroundMeaningfullyBelow(current, fallHit))
|
&& IsGroundMeaningfullyBelow(current, fallHit))
|
||||||
{
|
{
|
||||||
BeginFall();
|
BeginFall();
|
||||||
@ -118,6 +126,23 @@ namespace Intrepid.Core.Entities
|
|||||||
ApplyMove(body, next);
|
ApplyMove(body, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vector3 ResolveGroundMotionDelta()
|
||||||
|
{
|
||||||
|
if (!IsGrounded || !_currentGroundProfiles.TryGetGroundProfileMotion(out var motion))
|
||||||
|
{
|
||||||
|
return Vector3.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
var delta = motion.DeltaPosition;
|
||||||
|
|
||||||
|
if (inheritGroundMotionY)
|
||||||
|
{
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Vector3(delta.x, 0f, delta.z);
|
||||||
|
}
|
||||||
|
|
||||||
private Vector3 ResolveFallingPosition(Vector3 current, float deltaTime)
|
private Vector3 ResolveFallingPosition(Vector3 current, float deltaTime)
|
||||||
{
|
{
|
||||||
IsGrounded = false;
|
IsGrounded = false;
|
||||||
@ -131,7 +156,10 @@ namespace Intrepid.Core.Entities
|
|||||||
var next = current;
|
var next = current;
|
||||||
next.y -= _fallVerticalSpeed * deltaTime;
|
next.y -= _fallVerticalSpeed * deltaTime;
|
||||||
|
|
||||||
if (!TryAnyGroundSurfaceBelowAt(next, out var fallHit, out var fallNormal))
|
if (!TryAnyGroundSurfaceBelowAt(next,
|
||||||
|
out var fallHit,
|
||||||
|
out var fallNormal,
|
||||||
|
out var fallProfiles))
|
||||||
{
|
{
|
||||||
BeginFallToAbyss();
|
BeginFallToAbyss();
|
||||||
return current; // or next?
|
return current; // or next?
|
||||||
@ -148,17 +176,12 @@ namespace Intrepid.Core.Entities
|
|||||||
|
|
||||||
RegisterStableGroundNormal(fallNormal);
|
RegisterStableGroundNormal(fallNormal);
|
||||||
|
|
||||||
// LastSafeGroundPosition = new Vector3(
|
|
||||||
// next.x,
|
|
||||||
// targetY,
|
|
||||||
// next.z
|
|
||||||
// );
|
|
||||||
|
|
||||||
IsGrounded = true;
|
IsGrounded = true;
|
||||||
IsFalling = false;
|
IsFalling = false;
|
||||||
IsFallingToAbyss = false;
|
IsFallingToAbyss = false;
|
||||||
_fallVerticalSpeed = 0f;
|
_fallVerticalSpeed = 0f;
|
||||||
|
_currentGroundProfiles = fallProfiles;
|
||||||
|
|
||||||
Proxy.Instance.EventBus.Raise(new EntityRecoverStableGroundEvent
|
Proxy.Instance.EventBus.Raise(new EntityRecoverStableGroundEvent
|
||||||
{
|
{
|
||||||
EntityId = entity.Id,
|
EntityId = entity.Id,
|
||||||
@ -178,7 +201,8 @@ namespace Intrepid.Core.Entities
|
|||||||
IsFalling = true;
|
IsFalling = true;
|
||||||
IsFallingToAbyss = false;
|
IsFallingToAbyss = false;
|
||||||
_fallVerticalSpeed = 0f;
|
_fallVerticalSpeed = 0f;
|
||||||
|
_currentGroundProfiles = GroundProfiles.None;
|
||||||
|
|
||||||
Proxy.Instance.EventBus.Raise(new EntityLeaveStableGroundEvent
|
Proxy.Instance.EventBus.Raise(new EntityLeaveStableGroundEvent
|
||||||
{
|
{
|
||||||
EntityId = entity.Id,
|
EntityId = entity.Id,
|
||||||
@ -198,6 +222,7 @@ namespace Intrepid.Core.Entities
|
|||||||
IsFalling = false;
|
IsFalling = false;
|
||||||
IsFallingToAbyss = true;
|
IsFallingToAbyss = true;
|
||||||
_fallVerticalSpeed = 0f;
|
_fallVerticalSpeed = 0f;
|
||||||
|
_currentGroundProfiles = GroundProfiles.None;
|
||||||
|
|
||||||
Proxy.Instance.EventBus.Raise(new EntityFaillingToAbyssEvent
|
Proxy.Instance.EventBus.Raise(new EntityFaillingToAbyssEvent
|
||||||
{
|
{
|
||||||
@ -219,12 +244,15 @@ namespace Intrepid.Core.Entities
|
|||||||
|
|
||||||
public void RefreshStableGroundNormalAt(Vector3 position)
|
public void RefreshStableGroundNormalAt(Vector3 position)
|
||||||
{
|
{
|
||||||
if (!TryGetGroundSurfaceAt(position, out _, out var normal))
|
if (!TryGetGroundSurfaceAt(position, out _, out var normal, out var groundProfiles))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterStableGroundNormal(normal);
|
if (groundProfiles.IsSafe)
|
||||||
|
{
|
||||||
|
RegisterStableGroundNormal(normal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector3 ResolveMovementVelocity(Vector3 velocity)
|
private Vector3 ResolveMovementVelocity(Vector3 velocity)
|
||||||
@ -258,15 +286,17 @@ namespace Intrepid.Core.Entities
|
|||||||
|
|
||||||
public bool HasGroundSurfaceAt(Vector3 position)
|
public bool HasGroundSurfaceAt(Vector3 position)
|
||||||
{
|
{
|
||||||
return TryGetGroundSurfaceAt(position, out _, out _);
|
return TryGetGroundSurfaceAt(position, out _, out _, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetGroundSurfaceAt(
|
private bool TryGetGroundSurfaceAt(
|
||||||
Vector3 position,
|
Vector3 position,
|
||||||
out RaycastHit hit,
|
out RaycastHit hit,
|
||||||
out Vector3 normal)
|
out Vector3 normal,
|
||||||
|
out GroundProfiles groundProfiles)
|
||||||
{
|
{
|
||||||
normal = default;
|
normal = default;
|
||||||
|
groundProfiles = GroundProfiles.None;
|
||||||
|
|
||||||
if (!TryGetGroundAt(position, out hit))
|
if (!TryGetGroundAt(position, out hit))
|
||||||
{
|
{
|
||||||
@ -287,6 +317,8 @@ namespace Intrepid.Core.Entities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groundProfiles = surface.GroundProfiles;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,9 +343,11 @@ namespace Intrepid.Core.Entities
|
|||||||
private bool TryAnyGroundSurfaceBelowAt(
|
private bool TryAnyGroundSurfaceBelowAt(
|
||||||
Vector3 position,
|
Vector3 position,
|
||||||
out RaycastHit hit,
|
out RaycastHit hit,
|
||||||
out Vector3 normal)
|
out Vector3 normal,
|
||||||
|
out GroundProfiles groundProfiles)
|
||||||
{
|
{
|
||||||
normal = default;
|
normal = default;
|
||||||
|
groundProfiles = GroundProfiles.None;
|
||||||
|
|
||||||
var origin = position + Vector3.up * groundCheckHeight;
|
var origin = position + Vector3.up * groundCheckHeight;
|
||||||
|
|
||||||
@ -341,7 +375,14 @@ namespace Intrepid.Core.Entities
|
|||||||
|
|
||||||
normal = surface.Normal;
|
normal = surface.Normal;
|
||||||
|
|
||||||
return IsWalkable(normal);
|
if (!IsWalkable(normal))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
groundProfiles = surface.GroundProfiles;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsWalkable(Vector3 normal)
|
private bool IsWalkable(Vector3 normal)
|
||||||
|
|||||||
9
Assets/Scripts/Intrepid/Core/Grounding/GroundProfile.cs
Normal file
9
Assets/Scripts/Intrepid/Core/Grounding/GroundProfile.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Intrepid.Utilities;
|
||||||
|
|
||||||
|
namespace Intrepid.Core.Grounding
|
||||||
|
{
|
||||||
|
public abstract class GroundProfile : Identification
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fdc7306926734d3bb5b74cc1107abb58
|
||||||
|
timeCreated: 1781275820
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Intrepid.Core.Grounding
|
||||||
|
{
|
||||||
|
public abstract class GroundProfileMotion : GroundProfile
|
||||||
|
{
|
||||||
|
public abstract Vector3 Velocity { get; }
|
||||||
|
public abstract Vector3 DeltaPosition { get; }
|
||||||
|
public abstract bool IsMoving { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e0bf2067f5ce4269a39772ba51ee47e2
|
||||||
|
timeCreated: 1781275853
|
||||||
35
Assets/Scripts/Intrepid/Core/Grounding/GroundProfiles.cs
Normal file
35
Assets/Scripts/Intrepid/Core/Grounding/GroundProfiles.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Intrepid.Core.Grounding
|
||||||
|
{
|
||||||
|
public readonly struct GroundProfiles
|
||||||
|
{
|
||||||
|
public static readonly GroundProfiles None = new(false);
|
||||||
|
|
||||||
|
public bool IsSafe { get; }
|
||||||
|
private GroundProfileMotion GroundProfileMotion { get; }
|
||||||
|
|
||||||
|
public GroundProfiles(bool isSafe, GroundProfileMotion groundProfileMotion = null)
|
||||||
|
{
|
||||||
|
IsSafe = isSafe;
|
||||||
|
GroundProfileMotion = groundProfileMotion;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryGet<T>(T value, out T profile) where T: GroundProfile
|
||||||
|
{
|
||||||
|
if (value.IsNull())
|
||||||
|
{
|
||||||
|
profile = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetGroundProfileMotion(out GroundProfileMotion profile)
|
||||||
|
{
|
||||||
|
return TryGet(GroundProfileMotion, out profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2bcaf8255e9847b8b25727c33769f037
|
||||||
|
timeCreated: 1781276176
|
||||||
@ -12,21 +12,33 @@ namespace Intrepid.Core.Grounding
|
|||||||
public class GroundSurface : MonoBehaviour
|
public class GroundSurface : MonoBehaviour
|
||||||
{
|
{
|
||||||
[GroupInjections, SerializeField] private BoxCollider boxCollider;
|
[GroupInjections, SerializeField] private BoxCollider boxCollider;
|
||||||
|
[GroupConfigurations("Profiles"), SerializeField] private bool safe = true;
|
||||||
|
[GroupConfigurations("Profiles"), SerializeField] private GroundProfileMotion groundProfileMotion;
|
||||||
|
|
||||||
|
|
||||||
[GroupDebug, ShowInInspector, ReadOnly] public Vector3 Position { get; private set; }
|
[GroupDebug, ShowInInspector, ReadOnly] public Vector3 Position { get; private set; }
|
||||||
[GroupDebug, ShowInInspector, ReadOnly] public Vector3 Normal { get; private set; }
|
[GroupDebug, ShowInInspector, ReadOnly] public Vector3 Normal { get; private set; }
|
||||||
|
public GroundProfiles GroundProfiles { get; private set; } = GroundProfiles.None;
|
||||||
|
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
{
|
{
|
||||||
if (boxCollider.IsNull()) return;
|
if (boxCollider.IsNull()) return;
|
||||||
DetectPosition();
|
DetectPosition();
|
||||||
DetectNormal();
|
DetectNormal();
|
||||||
|
RefreshProfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
DetectPosition();
|
DetectPosition();
|
||||||
DetectNormal();
|
DetectNormal();
|
||||||
|
RefreshProfiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
[GroupDebug, Button(ButtonSizes.Medium)]
|
||||||
|
private void RefreshProfiles()
|
||||||
|
{
|
||||||
|
GroundProfiles = new GroundProfiles(safe, groundProfileMotion);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Button(ButtonSizes.Medium)]
|
[Button(ButtonSizes.Medium)]
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
namespace Intrepid.Core.Grounding
|
|
||||||
{
|
|
||||||
public class MovingGroundSurface : GroundSurface
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 488d97fcd10d484b8d9e50393014a05c
|
|
||||||
timeCreated: 1781271534
|
|
||||||
Loading…
x
Reference in New Issue
Block a user