Added Falling and Falling To Abyss
This commit is contained in:
parent
aceb4677aa
commit
e936db5567
38
Assets/# Prototype/Shaders/GroundCollider.mat
Normal file
38
Assets/# Prototype/Shaders/GroundCollider.mat
Normal file
@ -0,0 +1,38 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: GroundCollider
|
||||
m_Shader: {fileID: 203, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 7e4b97337334f42d2a700647fd938234, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _Cutoff: 0.5
|
||||
- _InvFade: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 0, g: 1, b: 0, a: 0.65882355}
|
||||
- _TintColor: {r: 0, g: 0.48937988, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
8
Assets/# Prototype/Shaders/GroundCollider.mat.meta
Normal file
8
Assets/# Prototype/Shaders/GroundCollider.mat.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7a77724098fc4307a013f0b3c4464fe
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -4602,7 +4602,7 @@ MeshRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: bbb235fff4f48426b863b36058ab66d2, type: 2}
|
||||
- {fileID: 2100000, guid: e7a77724098fc4307a013f0b3c4464fe, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
|
||||
4636
Assets/Prefabs/Prototyping/Ground_Ramp_1x2_Prototype.prefab
Normal file
4636
Assets/Prefabs/Prototyping/Ground_Ramp_1x2_Prototype.prefab
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e89966f6cb1bb4daa86f5ab535b27089
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -4602,7 +4602,7 @@ MeshRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: bbb235fff4f48426b863b36058ab66d2, type: 2}
|
||||
- {fileID: 2100000, guid: e7a77724098fc4307a013f0b3c4464fe, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
|
||||
@ -4602,7 +4602,7 @@ MeshRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: bbb235fff4f48426b863b36058ab66d2, type: 2}
|
||||
- {fileID: 2100000, guid: e7a77724098fc4307a013f0b3c4464fe, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
|
||||
@ -301,7 +301,7 @@ MeshRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: bbb235fff4f48426b863b36058ab66d2, type: 2}
|
||||
- {fileID: 2100000, guid: e7a77724098fc4307a013f0b3c4464fe, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
|
||||
@ -301,7 +301,7 @@ MeshRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: bbb235fff4f48426b863b36058ab66d2, type: 2}
|
||||
- {fileID: 2100000, guid: e7a77724098fc4307a013f0b3c4464fe, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
|
||||
@ -301,7 +301,7 @@ MeshRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: bbb235fff4f48426b863b36058ab66d2, type: 2}
|
||||
- {fileID: 2100000, guid: e7a77724098fc4307a013f0b3c4464fe, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
|
||||
@ -301,7 +301,7 @@ MeshRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: bbb235fff4f48426b863b36058ab66d2, type: 2}
|
||||
- {fileID: 2100000, guid: e7a77724098fc4307a013f0b3c4464fe, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -3,24 +3,19 @@ namespace Intrepid.Core.Entities
|
||||
public readonly struct EntityMotorMoveOptions
|
||||
{
|
||||
public readonly bool KeepHeightWhenNoGround;
|
||||
public readonly bool ProjectGapHeightFromLastGround;
|
||||
|
||||
public EntityMotorMoveOptions(
|
||||
bool keepHeightWhenNoGround,
|
||||
bool projectGapHeightFromLastGround)
|
||||
bool keepHeightWhenNoGround)
|
||||
{
|
||||
KeepHeightWhenNoGround = keepHeightWhenNoGround;
|
||||
ProjectGapHeightFromLastGround = projectGapHeightFromLastGround;
|
||||
}
|
||||
|
||||
public static EntityMotorMoveOptions Default => new(
|
||||
keepHeightWhenNoGround: false,
|
||||
projectGapHeightFromLastGround: false
|
||||
keepHeightWhenNoGround: false
|
||||
);
|
||||
|
||||
public static EntityMotorMoveOptions GapCrossing => new(
|
||||
keepHeightWhenNoGround: true,
|
||||
projectGapHeightFromLastGround: true
|
||||
keepHeightWhenNoGround: true
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,36 +1,55 @@
|
||||
using System;
|
||||
using Intrepid.Core.Entities.Messages;
|
||||
using Intrepid.Core.Grounding;
|
||||
using Intrepid.Diagnostics;
|
||||
using Intrepid.GameManagers;
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Core.Entities
|
||||
{
|
||||
public sealed class EntityMotorTopDown : MonoBehaviour
|
||||
{
|
||||
private const float MIN_VELOCITY_SQR_MAGNITUDE = 0.0001f;
|
||||
private const float MIN_PROJECTED_SQR_MAGNITUDE = 0.0001f;
|
||||
|
||||
[GroupInjections, SerializeField] private Entity entity;
|
||||
[GroupConfigurations, SerializeField] private LayerMask groundMask;
|
||||
|
||||
[GroupConfigurations, SerializeField] private float groundCheckHeight = 1.0f;
|
||||
[GroupConfigurations, SerializeField] private float groundCheckDistance = 3.0f;
|
||||
[GroupConfigurations, SerializeField] private float groundOffset;
|
||||
[GroupConfigurations, SerializeField] private float maxSlopeAngle = 45f;
|
||||
[GroupConfigurations, SerializeField] private float groundProbeRadius = 0.25f;
|
||||
[GroupConfigurations, SerializeField] private float groundProbeRadiusGrounded = 0.5f;
|
||||
[GroupConfigurations, SerializeField] private float groundProbeRadiusFalling = 0.2f;
|
||||
[GroupConfigurations, SerializeField] private float fallingGroundCheckDistance = 20f;
|
||||
[GroupConfigurations, SerializeField] private float minFallHeight = 0.25f;
|
||||
[GroupConfigurations, SerializeField] private float fallAcceleration = 35f;
|
||||
[GroupConfigurations, SerializeField] private float maxFallSpeed = 18f;
|
||||
|
||||
|
||||
private Vector3 Origin { get; set; }
|
||||
private Vector3 End { get; set; }
|
||||
private bool HasHit { get; set; }
|
||||
|
||||
private float _fallVerticalSpeed;
|
||||
private RaycastHit _groundHit;
|
||||
|
||||
private bool _hasStableGroundNormal;
|
||||
private Vector3 _stableGroundNormal;
|
||||
private float GroundProbeRadius => IsFalling || IsFallingToAbyss
|
||||
? groundProbeRadiusFalling
|
||||
: groundProbeRadiusGrounded;
|
||||
|
||||
public float MaxSlopeAngle => maxSlopeAngle;
|
||||
public bool HasStableGroundNormal => _hasStableGroundNormal;
|
||||
public Vector3 StableGroundNormal => _stableGroundNormal;
|
||||
[GroupDebug, ShowInInspector, ReadOnly] public Vector3 LastSafeGroundPosition { get; private set; }
|
||||
public bool HasStableGroundNormal { get; private set; }
|
||||
public Vector3 StableGroundNormal { get; private set; }
|
||||
public bool IsFalling { get; private set; }
|
||||
public bool IsFallingToAbyss { get; private set; }
|
||||
public bool IsGrounded { get; private set; }
|
||||
|
||||
public void ResetFallingToAbyss()
|
||||
{
|
||||
IsFalling = false;
|
||||
IsFallingToAbyss = false;
|
||||
}
|
||||
|
||||
public void Move(
|
||||
Rigidbody body,
|
||||
Vector3 velocity,
|
||||
@ -39,32 +58,165 @@ namespace Intrepid.Core.Entities
|
||||
{
|
||||
var current = body.position;
|
||||
|
||||
if (IsFallingToAbyss)
|
||||
{
|
||||
return; // there is no movement from here....
|
||||
}
|
||||
|
||||
if (IsFalling)
|
||||
{
|
||||
var nextFalling = ResolveFallingPosition(current, deltaTime);
|
||||
ApplyMove(body, nextFalling);
|
||||
return;
|
||||
}
|
||||
|
||||
var movementVelocity = ResolveMovementVelocity(velocity);
|
||||
|
||||
var next = current + movementVelocity * deltaTime;
|
||||
|
||||
if (TryGetGroundSurfaceAt(next, out _groundHit, out var nextNormal))
|
||||
{
|
||||
IsGrounded = true;
|
||||
IsFallingToAbyss = false;
|
||||
|
||||
RegisterStableGroundNormal(nextNormal);
|
||||
next.y = _groundHit.point.y + groundOffset;
|
||||
LastSafeGroundPosition = new Vector3(
|
||||
next.x,
|
||||
_groundHit.point.y + groundOffset,
|
||||
next.z
|
||||
);
|
||||
if (IsFalling)
|
||||
{
|
||||
IsFalling = false;
|
||||
Proxy.Instance.EventBus.Raise(new EntityRecoverStableGroundEvent
|
||||
{
|
||||
EntityId = entity.Id,
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (options.KeepHeightWhenNoGround)
|
||||
else if (options.KeepHeightWhenNoGround) // that is probable an ability like sentinel dash, or enemy jump...
|
||||
{
|
||||
IsGrounded = false;
|
||||
IsFalling = false;
|
||||
IsFallingToAbyss = false;
|
||||
// Important:
|
||||
// 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 _)
|
||||
&& IsGroundMeaningfullyBelow(current, fallHit))
|
||||
{
|
||||
BeginFall();
|
||||
next = current;
|
||||
}
|
||||
else
|
||||
{
|
||||
BeginFallToAbyss();
|
||||
next = current;
|
||||
}
|
||||
|
||||
ApplyMove(body, next);
|
||||
}
|
||||
|
||||
private Vector3 ResolveFallingPosition(Vector3 current, float deltaTime)
|
||||
{
|
||||
IsGrounded = false;
|
||||
IsFallingToAbyss = false;
|
||||
|
||||
_fallVerticalSpeed = Mathf.Min(
|
||||
_fallVerticalSpeed + fallAcceleration * deltaTime,
|
||||
maxFallSpeed
|
||||
);
|
||||
|
||||
var next = current;
|
||||
next.y -= _fallVerticalSpeed * deltaTime;
|
||||
|
||||
if (!TryAnyGroundSurfaceBelowAt(next, out var fallHit, out var fallNormal))
|
||||
{
|
||||
BeginFallToAbyss();
|
||||
return current; // or next?
|
||||
}
|
||||
|
||||
var targetY = fallHit.point.y + groundOffset;
|
||||
|
||||
if (next.y > targetY)
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
next.y = targetY;
|
||||
|
||||
RegisterStableGroundNormal(fallNormal);
|
||||
|
||||
// LastSafeGroundPosition = new Vector3(
|
||||
// next.x,
|
||||
// targetY,
|
||||
// next.z
|
||||
// );
|
||||
|
||||
IsGrounded = true;
|
||||
IsFalling = false;
|
||||
IsFallingToAbyss = false;
|
||||
_fallVerticalSpeed = 0f;
|
||||
|
||||
Proxy.Instance.EventBus.Raise(new EntityRecoverStableGroundEvent
|
||||
{
|
||||
EntityId = entity.Id,
|
||||
});
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
private void BeginFall()
|
||||
{
|
||||
if (IsFalling)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsGrounded = false;
|
||||
IsFalling = true;
|
||||
IsFallingToAbyss = false;
|
||||
_fallVerticalSpeed = 0f;
|
||||
|
||||
Proxy.Instance.EventBus.Raise(new EntityLeaveStableGroundEvent
|
||||
{
|
||||
EntityId = entity.Id,
|
||||
});
|
||||
}
|
||||
|
||||
private void BeginFallToAbyss()
|
||||
{
|
||||
if (IsFallingToAbyss)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DLogger.LogDebug("Real abyss fall");
|
||||
|
||||
IsGrounded = false;
|
||||
IsFalling = false;
|
||||
IsFallingToAbyss = true;
|
||||
_fallVerticalSpeed = 0f;
|
||||
|
||||
Proxy.Instance.EventBus.Raise(new EntityFaillingToAbyssEvent
|
||||
{
|
||||
EntityId = entity.Id,
|
||||
});
|
||||
}
|
||||
|
||||
private static void ApplyMove(Rigidbody body, Vector3 next)
|
||||
{
|
||||
body.linearVelocity = Vector3.zero;
|
||||
body.angularVelocity = Vector3.zero;
|
||||
body.MovePosition(next);
|
||||
}
|
||||
|
||||
private bool IsGroundMeaningfullyBelow(Vector3 current, RaycastHit hit)
|
||||
{
|
||||
return hit.point.y + groundOffset < current.y - minFallHeight;
|
||||
}
|
||||
|
||||
public void RefreshStableGroundNormalAt(Vector3 position)
|
||||
{
|
||||
if (!TryGetGroundSurfaceAt(position, out _, out var normal))
|
||||
@ -77,31 +229,31 @@ namespace Intrepid.Core.Entities
|
||||
|
||||
private Vector3 ResolveMovementVelocity(Vector3 velocity)
|
||||
{
|
||||
if (velocity.sqrMagnitude <= MIN_VELOCITY_SQR_MAGNITUDE)
|
||||
if (velocity.sqrMagnitude <= GonConstants.CommonZeroSqrt)
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
if (!_hasStableGroundNormal)
|
||||
if (!HasStableGroundNormal)
|
||||
{
|
||||
return velocity;
|
||||
}
|
||||
|
||||
return ProjectVelocityOnPlane(
|
||||
velocity,
|
||||
_stableGroundNormal
|
||||
StableGroundNormal
|
||||
);
|
||||
}
|
||||
|
||||
private void RegisterStableGroundNormal(Vector3 normal)
|
||||
{
|
||||
if (normal.sqrMagnitude <= MIN_VELOCITY_SQR_MAGNITUDE)
|
||||
if (normal.sqrMagnitude <= GonConstants.CommonZeroSqrt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_stableGroundNormal = normal.normalized;
|
||||
_hasStableGroundNormal = true;
|
||||
StableGroundNormal = normal.normalized;
|
||||
HasStableGroundNormal = true;
|
||||
}
|
||||
|
||||
public bool HasGroundSurfaceAt(Vector3 position)
|
||||
@ -145,7 +297,7 @@ namespace Intrepid.Core.Entities
|
||||
|
||||
HasHit = Physics.SphereCast(
|
||||
Origin,
|
||||
groundProbeRadius,
|
||||
GroundProbeRadius,
|
||||
Vector3.down,
|
||||
out hit,
|
||||
groundCheckDistance,
|
||||
@ -156,6 +308,42 @@ namespace Intrepid.Core.Entities
|
||||
return HasHit;
|
||||
}
|
||||
|
||||
private bool TryAnyGroundSurfaceBelowAt(
|
||||
Vector3 position,
|
||||
out RaycastHit hit,
|
||||
out Vector3 normal)
|
||||
{
|
||||
normal = default;
|
||||
|
||||
var origin = position + Vector3.up * groundCheckHeight;
|
||||
|
||||
HasHit = Physics.SphereCast(
|
||||
origin,
|
||||
GroundProbeRadius,
|
||||
Vector3.down,
|
||||
out hit,
|
||||
fallingGroundCheckDistance,
|
||||
groundMask,
|
||||
QueryTriggerInteraction.Ignore
|
||||
);
|
||||
|
||||
if (!HasHit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var surface = hit.collider.GetComponentInParent<GroundSurface>();
|
||||
|
||||
if (surface.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
normal = surface.Normal;
|
||||
|
||||
return IsWalkable(normal);
|
||||
}
|
||||
|
||||
private bool IsWalkable(Vector3 normal)
|
||||
{
|
||||
var angle = Vector3.Angle(normal, Vector3.up);
|
||||
@ -171,7 +359,7 @@ namespace Intrepid.Core.Entities
|
||||
planeNormal.normalized
|
||||
);
|
||||
|
||||
if (projected.sqrMagnitude <= MIN_PROJECTED_SQR_MAGNITUDE)
|
||||
if (projected.sqrMagnitude <= GonConstants.CommonZeroSqrt)
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
@ -184,27 +372,27 @@ namespace Intrepid.Core.Entities
|
||||
{
|
||||
Gizmos.color = HasHit ? Color.green : Color.red;
|
||||
|
||||
Gizmos.DrawWireSphere(Origin, groundProbeRadius);
|
||||
Gizmos.DrawWireSphere(End, groundProbeRadius);
|
||||
Gizmos.DrawWireSphere(Origin, GroundProbeRadius);
|
||||
Gizmos.DrawWireSphere(End, GroundProbeRadius);
|
||||
|
||||
Gizmos.DrawLine(
|
||||
Origin + Vector3.right * groundProbeRadius,
|
||||
End + Vector3.right * groundProbeRadius
|
||||
Origin + Vector3.right * GroundProbeRadius,
|
||||
End + Vector3.right * GroundProbeRadius
|
||||
);
|
||||
|
||||
Gizmos.DrawLine(
|
||||
Origin - Vector3.right * groundProbeRadius,
|
||||
End - Vector3.right * groundProbeRadius
|
||||
Origin - Vector3.right * GroundProbeRadius,
|
||||
End - Vector3.right * GroundProbeRadius
|
||||
);
|
||||
|
||||
Gizmos.DrawLine(
|
||||
Origin + Vector3.forward * groundProbeRadius,
|
||||
End + Vector3.forward * groundProbeRadius
|
||||
Origin + Vector3.forward * GroundProbeRadius,
|
||||
End + Vector3.forward * GroundProbeRadius
|
||||
);
|
||||
|
||||
Gizmos.DrawLine(
|
||||
Origin - Vector3.forward * groundProbeRadius,
|
||||
End - Vector3.forward * groundProbeRadius
|
||||
Origin - Vector3.forward * GroundProbeRadius,
|
||||
End - Vector3.forward * GroundProbeRadius
|
||||
);
|
||||
|
||||
Gizmos.color = Color.yellow;
|
||||
@ -223,15 +411,15 @@ namespace Intrepid.Core.Entities
|
||||
|
||||
Gizmos.color = Color.blue;
|
||||
var sphereAtHit = Origin + Vector3.down * _groundHit.distance;
|
||||
Gizmos.DrawWireSphere(sphereAtHit, groundProbeRadius);
|
||||
Gizmos.DrawWireSphere(sphereAtHit, GroundProbeRadius);
|
||||
}
|
||||
|
||||
if (_hasStableGroundNormal)
|
||||
if (HasStableGroundNormal)
|
||||
{
|
||||
Gizmos.color = Color.white;
|
||||
Gizmos.DrawLine(
|
||||
transform.position,
|
||||
transform.position + _stableGroundNormal * 1.25f
|
||||
transform.position + StableGroundNormal * 1.25f
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
3
Assets/Scripts/Intrepid/Core/Entities/Messages.meta
Normal file
3
Assets/Scripts/Intrepid/Core/Entities/Messages.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc2e5fbe421d44e78cdc7f66839a97d3
|
||||
timeCreated: 1780904937
|
||||
@ -0,0 +1,9 @@
|
||||
using Intrepid.SimpleEvents;
|
||||
|
||||
namespace Intrepid.Core.Entities.Messages
|
||||
{
|
||||
public class EntityFaillingToAbyssEvent : IEventBase
|
||||
{
|
||||
public string EntityId { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97b2e4a50ae5410fabbdff2346385f1b
|
||||
timeCreated: 1780913231
|
||||
@ -0,0 +1,9 @@
|
||||
using Intrepid.SimpleEvents;
|
||||
|
||||
namespace Intrepid.Core.Entities.Messages
|
||||
{
|
||||
public class EntityLeaveStableGroundEvent : IEventBase
|
||||
{
|
||||
public string EntityId { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d7b62e6ce704eae8efc346f32b38a34
|
||||
timeCreated: 1780906213
|
||||
@ -0,0 +1,9 @@
|
||||
using Intrepid.SimpleEvents;
|
||||
|
||||
namespace Intrepid.Core.Entities.Messages
|
||||
{
|
||||
public class EntityRecoverStableGroundEvent : IEventBase
|
||||
{
|
||||
public string EntityId { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55a7aad450d241ef99ecd460c0507235
|
||||
timeCreated: 1780904942
|
||||
@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Intrepid.Core.Entities;
|
||||
using Intrepid.Core.Entities.Messages;
|
||||
using Intrepid.Gameplay.Entities.Sentinel.StateMachine;
|
||||
using Intrepid.Integration.Input;
|
||||
using Intrepid.Structures;
|
||||
@ -35,13 +37,31 @@ namespace Intrepid.Gameplay.Entities.Sentinel
|
||||
|
||||
protected override void Subscriptions()
|
||||
{
|
||||
Subscribe<EntityFaillingToAbyssEvent>(e =>
|
||||
{
|
||||
if (!string.Equals(Entity.Id, e.EntityId, StringComparison.Ordinal)) return;
|
||||
StateMachine.ChangeState(SentinelStateType.FallToAbyss);
|
||||
});
|
||||
Subscribe<EntityLeaveStableGroundEvent>(e =>
|
||||
{
|
||||
if (!string.Equals(Entity.Id, e.EntityId, StringComparison.Ordinal)) return;
|
||||
if (CurrentState == SentinelStateType.Fall) return;
|
||||
StateMachine.ChangeState(SentinelStateType.Fall);
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateFromUpdatable()
|
||||
{
|
||||
StateMachine.CurrentImplementation.RunAfterUpdate();
|
||||
StateMachine.CurrentImplementation.RunBeforeUpdate();
|
||||
StateMachine.CurrentImplementation.RunOnUpdate();
|
||||
StateMachine.CurrentImplementation.RunAfterUpdate();
|
||||
|
||||
// state machine could take this responsibility in the future...
|
||||
if (Inputs.Reset())
|
||||
{
|
||||
Entity.ResetLastSafeGroundPosition();
|
||||
StateMachine.ChangeState(SentinelStateType.FallLanding);
|
||||
}
|
||||
}
|
||||
|
||||
public override void LateUpdateFromUpdatable()
|
||||
|
||||
@ -28,6 +28,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel
|
||||
public Vector2 DesiredVelocity { get; set; }
|
||||
public Vector3 LinearVelocity { get; private set; }
|
||||
public Vector2 Forward => new Vector2(_desiredForward.x, _desiredForward.z).normalized;
|
||||
public bool IsGrounded => MotorTopDown.IsGrounded;
|
||||
|
||||
public override void DeployEntity(Vector2 position)
|
||||
{
|
||||
@ -98,5 +99,11 @@ namespace Intrepid.Gameplay.Entities.Sentinel
|
||||
{
|
||||
MotorTopDown.RefreshStableGroundNormalAt(UnityRigidbody.position);
|
||||
}
|
||||
|
||||
public void ResetLastSafeGroundPosition()
|
||||
{
|
||||
UnityRigidbody.position = MotorTopDown.LastSafeGroundPosition;
|
||||
MotorTopDown.ResetFallingToAbyss();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,5 +7,8 @@ namespace Intrepid.Gameplay.Entities.Sentinel
|
||||
{
|
||||
public Func<Vector2> Movement { get; set; }
|
||||
public Func<bool> Dash { get; set; }
|
||||
|
||||
// debug
|
||||
public Func<bool> Reset { get; set; }
|
||||
}
|
||||
}
|
||||
@ -18,5 +18,6 @@ namespace Intrepid.Gameplay.Entities.Sentinel
|
||||
|
||||
Fall = 90,
|
||||
FallLanding = 91,
|
||||
FallToAbyss = 92,
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
|
||||
|
||||
protected override void RunOnEnter(ParameterStore parameterStore)
|
||||
{
|
||||
Brain.Controls.ResetDash();
|
||||
Brain.Entity.ModelAnimation.Play(dashBreaking);
|
||||
Timer.Stop();
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
|
||||
{
|
||||
public class SentinelStateDashLanding : SentinelState
|
||||
public class SentinelStateDashWindow : SentinelState
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private AnimationClip dashWindow;
|
||||
[GroupConfigurations, SerializeField, Range(0, 30)] private float speed = 10;
|
||||
@ -44,9 +44,16 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
|
||||
if (CheckDash()) return;
|
||||
if (Timer.IsNotRunning)
|
||||
{
|
||||
Brain.ChangeState(Brain.Controls.DashShouldBreak()
|
||||
? SentinelStateType.DashBreaking
|
||||
: SentinelStateType.Idle);
|
||||
if (Brain.Entity.IsGrounded)
|
||||
{
|
||||
Brain.ChangeState(Brain.Controls.DashShouldBreak()
|
||||
? SentinelStateType.DashBreaking
|
||||
: SentinelStateType.Idle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.Fall);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Timer.Update(Time.deltaTime);
|
||||
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Intrepid.Core.Entities.Messages;
|
||||
using Intrepid.Structures;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
|
||||
{
|
||||
public class SentinelStateFall : SentinelState
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private AnimationClip fall;
|
||||
|
||||
public override SentinelStateType GetStateKey()
|
||||
{
|
||||
return SentinelStateType.Fall;
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
{
|
||||
Subscribe<EntityRecoverStableGroundEvent>(e =>
|
||||
{
|
||||
if (!string.Equals(Brain.Entity.Id, e.EntityId, StringComparison.Ordinal)) return;
|
||||
Brain.ChangeState(SentinelStateType.FallLanding);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void RunOnEnter(ParameterStore ps)
|
||||
{
|
||||
Brain.Controls.ResetDash();
|
||||
Brain.Entity.ModelAnimation.CrossFade(fall, .1f);
|
||||
Brain.Entity.DesiredVelocity = Vector2.zero;
|
||||
}
|
||||
|
||||
protected override void RunOnExit()
|
||||
{
|
||||
}
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05e6adb13632442f84e48179e5b50f39
|
||||
timeCreated: 1780903889
|
||||
@ -0,0 +1,44 @@
|
||||
using Intrepid.Structures;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
|
||||
{
|
||||
public class SentinelStateFallLanding : SentinelState
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private AnimationClip fallLanding;
|
||||
[GroupConfigurations, SerializeField, Range(0, 5)] private float fallLandingDuration = 2f;
|
||||
|
||||
private Timer Timer { get; } = new();
|
||||
|
||||
public override SentinelStateType GetStateKey()
|
||||
{
|
||||
return SentinelStateType.FallLanding;
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void RunOnEnter(ParameterStore ps)
|
||||
{
|
||||
Brain.Entity.ModelAnimation.CrossFade(fallLanding, .1f);
|
||||
Brain.Entity.DesiredVelocity = Vector2.zero;
|
||||
Timer.Start();
|
||||
}
|
||||
|
||||
protected override void RunOnExit()
|
||||
{
|
||||
Timer.Stop();
|
||||
}
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
if (Timer.IsNotRunning) return;
|
||||
Timer.Update(Timer.ScaledTime);
|
||||
if (!Timer.Check(fallLandingDuration)) return;
|
||||
Timer.Stop();
|
||||
Brain.ChangeState(SentinelStateType.Idle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91ab0d94e5374255ba65660f88b1564e
|
||||
timeCreated: 1780903997
|
||||
@ -0,0 +1,35 @@
|
||||
using Intrepid.Structures;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
|
||||
{
|
||||
public class SentinelStateFallToAbyss : SentinelState
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private AnimationClip fallToAbyss;
|
||||
|
||||
public override SentinelStateType GetStateKey()
|
||||
{
|
||||
return SentinelStateType.FallToAbyss;
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void RunOnEnter(ParameterStore ps)
|
||||
{
|
||||
Brain.Controls.ResetDash();
|
||||
Brain.Entity.ModelAnimation.CrossFade(fallToAbyss, .1f);
|
||||
Brain.Entity.DesiredVelocity = Vector2.zero;
|
||||
}
|
||||
|
||||
protected override void RunOnExit()
|
||||
{
|
||||
}
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 087a6debf49045e7a827f2c6eabe08eb
|
||||
timeCreated: 1780913440
|
||||
@ -109,6 +109,15 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
},
|
||||
{
|
||||
""name"": ""Reset"",
|
||||
""type"": ""Button"",
|
||||
""id"": ""30a345d6-b3e2-4f9c-86cc-8998ab80ebd4"",
|
||||
""expectedControlType"": """",
|
||||
""processors"": """",
|
||||
""interactions"": """",
|
||||
""initialStateCheck"": false
|
||||
}
|
||||
],
|
||||
""bindings"": [
|
||||
@ -199,6 +208,28 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
|
||||
""action"": ""Dash"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""4c704831-ecdf-4210-9e62-1893dc62274c"",
|
||||
""path"": """",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": """",
|
||||
""action"": ""Reset"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
},
|
||||
{
|
||||
""name"": """",
|
||||
""id"": ""94bc0bb4-e442-42e3-b785-48f17ff1f9c2"",
|
||||
""path"": ""<Keyboard>/r"",
|
||||
""interactions"": """",
|
||||
""processors"": """",
|
||||
""groups"": "";Keyboard & Mouse"",
|
||||
""action"": ""Reset"",
|
||||
""isComposite"": false,
|
||||
""isPartOfComposite"": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -237,6 +268,7 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
|
||||
m_sentinel = asset.FindActionMap("sentinel", throwIfNotFound: true);
|
||||
m_sentinel_Movement = m_sentinel.FindAction("Movement", throwIfNotFound: true);
|
||||
m_sentinel_Dash = m_sentinel.FindAction("Dash", throwIfNotFound: true);
|
||||
m_sentinel_Reset = m_sentinel.FindAction("Reset", throwIfNotFound: true);
|
||||
}
|
||||
|
||||
~@InputActions()
|
||||
@ -319,6 +351,7 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
|
||||
private List<ISentinelActions> m_SentinelActionsCallbackInterfaces = new List<ISentinelActions>();
|
||||
private readonly InputAction m_sentinel_Movement;
|
||||
private readonly InputAction m_sentinel_Dash;
|
||||
private readonly InputAction m_sentinel_Reset;
|
||||
/// <summary>
|
||||
/// Provides access to input actions defined in input action map "sentinel".
|
||||
/// </summary>
|
||||
@ -339,6 +372,10 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
|
||||
/// </summary>
|
||||
public InputAction @Dash => m_Wrapper.m_sentinel_Dash;
|
||||
/// <summary>
|
||||
/// Provides access to the underlying input action "sentinel/Reset".
|
||||
/// </summary>
|
||||
public InputAction @Reset => m_Wrapper.m_sentinel_Reset;
|
||||
/// <summary>
|
||||
/// Provides access to the underlying input action map instance.
|
||||
/// </summary>
|
||||
public InputActionMap Get() { return m_Wrapper.m_sentinel; }
|
||||
@ -370,6 +407,9 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
|
||||
@Dash.started += instance.OnDash;
|
||||
@Dash.performed += instance.OnDash;
|
||||
@Dash.canceled += instance.OnDash;
|
||||
@Reset.started += instance.OnReset;
|
||||
@Reset.performed += instance.OnReset;
|
||||
@Reset.canceled += instance.OnReset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -387,6 +427,9 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
|
||||
@Dash.started -= instance.OnDash;
|
||||
@Dash.performed -= instance.OnDash;
|
||||
@Dash.canceled -= instance.OnDash;
|
||||
@Reset.started -= instance.OnReset;
|
||||
@Reset.performed -= instance.OnReset;
|
||||
@Reset.canceled -= instance.OnReset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -467,5 +510,12 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.performed" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.canceled" />
|
||||
void OnDash(InputAction.CallbackContext context);
|
||||
/// <summary>
|
||||
/// Method invoked when associated input action "Reset" is either <see cref="UnityEngine.InputSystem.InputAction.started" />, <see cref="UnityEngine.InputSystem.InputAction.performed" /> or <see cref="UnityEngine.InputSystem.InputAction.canceled" />.
|
||||
/// </summary>
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.started" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.performed" />
|
||||
/// <seealso cref="UnityEngine.InputSystem.InputAction.canceled" />
|
||||
void OnReset(InputAction.CallbackContext context);
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,15 @@
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "Reset",
|
||||
"type": "Button",
|
||||
"id": "30a345d6-b3e2-4f9c-86cc-8998ab80ebd4",
|
||||
"expectedControlType": "",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
}
|
||||
],
|
||||
"bindings": [
|
||||
@ -113,6 +122,28 @@
|
||||
"action": "Dash",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "4c704831-ecdf-4210-9e62-1893dc62274c",
|
||||
"path": "",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "Reset",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "94bc0bb4-e442-42e3-b785-48f17ff1f9c2",
|
||||
"path": "<Keyboard>/r",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": ";Keyboard & Mouse",
|
||||
"action": "Reset",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -62,6 +62,9 @@ namespace Intrepid.Integration.Input
|
||||
? InputActions.sentinel.Movement.ReadValue<Vector2>()
|
||||
: Vector2.zero,
|
||||
Dash = () => Locking.IsNotLocked && InputActions.sentinel.Dash.WasPressedThisFrame(),
|
||||
|
||||
// debug
|
||||
Reset = () => Locking.IsNotLocked && InputActions.sentinel.Reset.WasPressedThisFrame(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user