From f37b4b41c8a6c8498afee8c8463d0a3a02a7b15f Mon Sep 17 00:00:00 2001 From: Josef Date: Sun, 21 Dec 2025 19:56:48 +0100 Subject: [PATCH] CharacterController Update --- .../CharacterController.cs | 16 +- .../CharacterControllerAction.cs | 33 + .../CharacterController/CharacterMovement.cs | 2 +- .../CharacterController/Gravity.cs | 17 +- .../Gravity/EarthGravityStrength.cs | 20 + .../Gravity/EarthGravityStrength.cs.uid | 1 + .../Gravity/GravityStrength.cs | 14 + .../Gravity/GravityStrength.cs.uid | 1 + .../Gravity/HeightDurationGravityStrength.cs | 20 + .../HeightDurationGravityStrength.cs.uid | 1 + .../Gravity/RawGravityStrength.cs | 20 + .../Gravity/RawGravityStrength.cs.uid | 1 + .../Gravity/ReferencedGravityStrength.cs | 23 + .../Gravity/ReferencedGravityStrength.cs.uid | 1 + .../CharacterController/GroundReset.cs | 2 +- .../Grounding/DownGroundingType.cs | 35 + .../Grounding/DownGroundingType.cs.uid | 1 + .../Grounding/Grounding.cs | 154 + .../Grounding/Grounding.cs.uid | 1 + .../Grounding/GroundingType.cs | 36 + .../Grounding/GroundingType.cs.uid | 1 + .../CharacterController/HeightDuration.cs | 18 + .../CharacterController/HeightDuration.cs.uid | 1 + .../Interactions/CharacterController/Jump.cs | 175 +- .../Jumping/HeightBasedJumpStrength.cs | 33 + .../Jumping/HeightBasedJumpStrength.cs.uid | 1 + .../Jumping/HeightDurationJumpStrength.cs | 20 + .../Jumping/HeightDurationJumpStrength.cs.uid | 1 + .../Jumping/HumanJumpStrength.cs | 22 + .../Jumping/HumanJumpStrength.cs.uid | 1 + .../Jumping/JumpStrength.cs | 14 + .../Jumping/JumpStrength.cs.uid | 1 + .../Jumping/RawJumpStrength.cs | 51 + .../Jumping/RawJumpStrength.cs.uid | 1 + Runtime/Physics/CollisionData.cs | 61 +- Runtime/Physics/PhysicsRayCast.cs | 60 + Runtime/Physics/PhysicsRayCast.cs.uid | 1 + Runtime/Sensors/SensorManager.cs | 2 +- rokojori-action-library-images.svg | 118544 ++++++++++++++- 39 files changed, 119267 insertions(+), 140 deletions(-) create mode 100644 Runtime/Interactions/CharacterController/Gravity/EarthGravityStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Gravity/EarthGravityStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Gravity/GravityStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Gravity/GravityStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Gravity/HeightDurationGravityStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Gravity/HeightDurationGravityStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Gravity/RawGravityStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Gravity/RawGravityStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Gravity/ReferencedGravityStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Gravity/ReferencedGravityStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Grounding/DownGroundingType.cs create mode 100644 Runtime/Interactions/CharacterController/Grounding/DownGroundingType.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Grounding/Grounding.cs create mode 100644 Runtime/Interactions/CharacterController/Grounding/Grounding.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Grounding/GroundingType.cs create mode 100644 Runtime/Interactions/CharacterController/Grounding/GroundingType.cs.uid create mode 100644 Runtime/Interactions/CharacterController/HeightDuration.cs create mode 100644 Runtime/Interactions/CharacterController/HeightDuration.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Jumping/HeightBasedJumpStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Jumping/HeightBasedJumpStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Jumping/HeightDurationJumpStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Jumping/HeightDurationJumpStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Jumping/HumanJumpStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Jumping/HumanJumpStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Jumping/JumpStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Jumping/JumpStrength.cs.uid create mode 100644 Runtime/Interactions/CharacterController/Jumping/RawJumpStrength.cs create mode 100644 Runtime/Interactions/CharacterController/Jumping/RawJumpStrength.cs.uid create mode 100644 Runtime/Physics/PhysicsRayCast.cs create mode 100644 Runtime/Physics/PhysicsRayCast.cs.uid diff --git a/Runtime/Interactions/CharacterController/CharacterController.cs b/Runtime/Interactions/CharacterController/CharacterController.cs index 9fd5ef3..fbb4e60 100644 --- a/Runtime/Interactions/CharacterController/CharacterController.cs +++ b/Runtime/Interactions/CharacterController/CharacterController.cs @@ -12,6 +12,9 @@ namespace Rokojori [Export] public CharacterBody3D body; + [Export] + public Grounding grounding; + public enum CharacterUpdateMode { Process, @@ -39,10 +42,17 @@ namespace Rokojori [Export] public float lastGroundedHeight = 0; - public float delta = 0; - + + public bool isGrounded + { + get + { + return grounding == null ? body.IsOnFloor() : grounding.isGrounded; + } + } + public override void _Process( double delta ) { if ( Engine.IsEditorHint() && graphics == null || body == null ) @@ -55,7 +65,7 @@ namespace Rokojori ProcessActions( (float) delta ); } - if ( body.IsOnFloor() ) + if ( isGrounded ) { lastGroundedHeight = graphics.GlobalPosition.Y; } diff --git a/Runtime/Interactions/CharacterController/CharacterControllerAction.cs b/Runtime/Interactions/CharacterController/CharacterControllerAction.cs index f1a1fc1..a0691f8 100644 --- a/Runtime/Interactions/CharacterController/CharacterControllerAction.cs +++ b/Runtime/Interactions/CharacterController/CharacterControllerAction.cs @@ -21,16 +21,39 @@ namespace Rokojori [Export] public SceneCondition sceneCondition; + [Export] + public CharacterControllerAction[] blockers = []; + + public bool isGrounded => _controller.isGrounded; + public void SetCharacterController( CharacterController cc ) { _controller = cc; } + public virtual bool HasActiveForces() + { + return false; + } + public CharacterBody3D body => controller.body; + public bool blockersActive + { + get + { + return blockers != null && blockers.Has( b => b.HasActiveForces() ); + } + } + public void AddVelocity( Vector3 velocity, float delta = -1 ) { + if ( blockersActive ) + { + return; + } + delta = delta < 0 ? controller.delta : delta; body.Velocity += velocity * delta; @@ -38,11 +61,21 @@ namespace Rokojori public void SetScaledVelocity( float scale ) { + if ( blockersActive ) + { + return; + } + body.Velocity *= scale; } public void SetVelocity( Vector3 velocity, float delta = -1 ) { + if ( blockersActive ) + { + return; + } + delta = delta < 0 ? controller.delta : delta; body.Velocity = velocity * delta; } diff --git a/Runtime/Interactions/CharacterController/CharacterMovement.cs b/Runtime/Interactions/CharacterController/CharacterMovement.cs index e453103..74c4e4b 100644 --- a/Runtime/Interactions/CharacterController/CharacterMovement.cs +++ b/Runtime/Interactions/CharacterController/CharacterMovement.cs @@ -103,7 +103,7 @@ namespace Rokojori protected override void _OnTrigger() { - var onFloor = body.IsOnFloor(); + var onFloor = isGrounded; _onFloor = onFloor; characterMovementData.Reset( this ); diff --git a/Runtime/Interactions/CharacterController/Gravity.cs b/Runtime/Interactions/CharacterController/Gravity.cs index ad309fa..b0d305c 100644 --- a/Runtime/Interactions/CharacterController/Gravity.cs +++ b/Runtime/Interactions/CharacterController/Gravity.cs @@ -9,17 +9,24 @@ namespace Rokojori [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCGravity.svg")] public partial class Gravity:CharacterControllerAction { + public static readonly float EarthGravity = 9.80665f; + [Export] - public float strength = 10; + public GravityStrength strength; + + [Export] + public GravityStrength fallingStrength; protected override void _OnTrigger() { - if ( body.IsOnFloor() ) + if ( isGrounded || strength == null ) { return; - } - // RJLog.Log( controller.body.Velocity ); - AddVelocity( Vector3.Down * strength ); + } + + var strengthSource = body.Velocity.Y > 0 || fallingStrength == null ? strength : fallingStrength; + + AddVelocity( Vector3.Down * strengthSource.GetGravityStrength( this ) ); } } } \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Gravity/EarthGravityStrength.cs b/Runtime/Interactions/CharacterController/Gravity/EarthGravityStrength.cs new file mode 100644 index 0000000..4b7f06b --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/EarthGravityStrength.cs @@ -0,0 +1,20 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class EarthGravityStrength:GravityStrength + { + [Export] + public float multiply = 1f; + + public override float GetGravityStrength( Gravity gravity ) + { + return Gravity.EarthGravity * multiply; + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Gravity/EarthGravityStrength.cs.uid b/Runtime/Interactions/CharacterController/Gravity/EarthGravityStrength.cs.uid new file mode 100644 index 0000000..4c714ec --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/EarthGravityStrength.cs.uid @@ -0,0 +1 @@ +uid://dug045ws8o2fy diff --git a/Runtime/Interactions/CharacterController/Gravity/GravityStrength.cs b/Runtime/Interactions/CharacterController/Gravity/GravityStrength.cs new file mode 100644 index 0000000..24edec2 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/GravityStrength.cs @@ -0,0 +1,14 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public abstract partial class GravityStrength:Resource + { + public abstract float GetGravityStrength( Gravity gravity ); + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Gravity/GravityStrength.cs.uid b/Runtime/Interactions/CharacterController/Gravity/GravityStrength.cs.uid new file mode 100644 index 0000000..08ca695 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/GravityStrength.cs.uid @@ -0,0 +1 @@ +uid://bey6k6vokedqx diff --git a/Runtime/Interactions/CharacterController/Gravity/HeightDurationGravityStrength.cs b/Runtime/Interactions/CharacterController/Gravity/HeightDurationGravityStrength.cs new file mode 100644 index 0000000..faf2b53 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/HeightDurationGravityStrength.cs @@ -0,0 +1,20 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class HeightDurationGravityStrength:GravityStrength + { + [Export] + public HeightDuration heightDuration; + + public override float GetGravityStrength( Gravity gravity ) + { + return heightDuration.height * 2f / ( heightDuration.duration * heightDuration.duration ); + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Gravity/HeightDurationGravityStrength.cs.uid b/Runtime/Interactions/CharacterController/Gravity/HeightDurationGravityStrength.cs.uid new file mode 100644 index 0000000..ecf91b2 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/HeightDurationGravityStrength.cs.uid @@ -0,0 +1 @@ +uid://c0qpyxi2615lf diff --git a/Runtime/Interactions/CharacterController/Gravity/RawGravityStrength.cs b/Runtime/Interactions/CharacterController/Gravity/RawGravityStrength.cs new file mode 100644 index 0000000..80be7dc --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/RawGravityStrength.cs @@ -0,0 +1,20 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class RawGravityStrength:GravityStrength + { + [Export] + public float strength = Gravity.EarthGravity; + + public override float GetGravityStrength( Gravity gravity ) + { + return strength; + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Gravity/RawGravityStrength.cs.uid b/Runtime/Interactions/CharacterController/Gravity/RawGravityStrength.cs.uid new file mode 100644 index 0000000..dff29ca --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/RawGravityStrength.cs.uid @@ -0,0 +1 @@ +uid://cgg7rx8nnpqv5 diff --git a/Runtime/Interactions/CharacterController/Gravity/ReferencedGravityStrength.cs b/Runtime/Interactions/CharacterController/Gravity/ReferencedGravityStrength.cs new file mode 100644 index 0000000..50d477b --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/ReferencedGravityStrength.cs @@ -0,0 +1,23 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class ReferencedGravityStrength:GravityStrength + { + [Export] + public GravityStrength referencedStrength; + + [Export] + public float multiplier = 1f; + + public override float GetGravityStrength( Gravity gravity ) + { + return multiplier * referencedStrength.GetGravityStrength( gravity ); + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Gravity/ReferencedGravityStrength.cs.uid b/Runtime/Interactions/CharacterController/Gravity/ReferencedGravityStrength.cs.uid new file mode 100644 index 0000000..cc16197 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Gravity/ReferencedGravityStrength.cs.uid @@ -0,0 +1 @@ +uid://qstgyis6jyd6 diff --git a/Runtime/Interactions/CharacterController/GroundReset.cs b/Runtime/Interactions/CharacterController/GroundReset.cs index fb87fe4..f0baec3 100644 --- a/Runtime/Interactions/CharacterController/GroundReset.cs +++ b/Runtime/Interactions/CharacterController/GroundReset.cs @@ -11,7 +11,7 @@ namespace Rokojori { protected override void _OnTrigger() { - if ( ! body.IsOnFloor() ) + if ( ! isGrounded ) { return; } diff --git a/Runtime/Interactions/CharacterController/Grounding/DownGroundingType.cs b/Runtime/Interactions/CharacterController/Grounding/DownGroundingType.cs new file mode 100644 index 0000000..09c3645 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Grounding/DownGroundingType.cs @@ -0,0 +1,35 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCGroundReset.svg")] + public partial class DownGroundingType:GroundingType + { + [Export] + public float downLength = 0.3f; + + [Export] + public float upOffset = 0f; + + + protected override bool _IsGrounded( Grounding grounding, List collisionData ) + { + var position = grounding.body.GlobalPosition; + var from = position + upOffset * Vector3.Up; + var to = from + Vector3.Down * downLength; + + var hits = PhysicsRayCast.GetAll( collisionData, grounding.body, from, to ); + + if ( hits == 0 ) + { + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Grounding/DownGroundingType.cs.uid b/Runtime/Interactions/CharacterController/Grounding/DownGroundingType.cs.uid new file mode 100644 index 0000000..1b5c53e --- /dev/null +++ b/Runtime/Interactions/CharacterController/Grounding/DownGroundingType.cs.uid @@ -0,0 +1 @@ +uid://bs6oahk3jrjcq diff --git a/Runtime/Interactions/CharacterController/Grounding/Grounding.cs b/Runtime/Interactions/CharacterController/Grounding/Grounding.cs new file mode 100644 index 0000000..d54d2e8 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Grounding/Grounding.cs @@ -0,0 +1,154 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCGroundReset.svg")] + public partial class Grounding:CharacterControllerAction + { + [Export] + public GroundingType groundingType; + + bool _grounded = false; + + public new bool isGrounded => _hasGroundedOverwrite ? _groundedOverwriteValue : _grounded; + + bool _currentlyGrounded = false; + + public bool isCurrentlyGrounded => _currentlyGrounded; + + [Export] + public Action onGrounded; + + [Export] + public Action onUngrounded; + + [Export] + public Action onCurrentlyGrounded; + + [Export] + public Action onCurrentlyUngrounded; + + [Export] + public float keepGroundedDuration = 0.1f; + + [ExportGroup( "Velocity Resetting" )] + [Export] + public bool resetVelocityWhenGrounded = true; + + bool _hasGroundedOverwrite = false; + bool _groundedOverwriteValue = false; + + [ExportGroup( "Debugging")] + + [Export] + public bool outputDebugInfo = false; + + [Export] + public bool currentlyGrounded = false; + + [Export] + public bool grounded = false; + + [Export] + public Node groundedCollider; + + [Export] + public Node3D groundedPositionTarget; + + + + + protected List _collisionData = CollisionData.ForMaxHits( 1 ); + + public CollisionData collisionData => _grounded ? null : _collisionData[ 0 ]; + + float _durationSinceLastGrounded = -1; + CollisionData _lastGroundedCollision = new CollisionData(); + + public void ApplyUngroundedOverwrite() + { + _hasGroundedOverwrite = true; + _groundedOverwriteValue = false; + } + + protected override void _OnTrigger() + { + _hasGroundedOverwrite = false; + + var cg = _currentlyGrounded; + var g = _grounded; + + _currentlyGrounded = GroundingType.IsGrounded( this, _collisionData ); + + if ( cg != _currentlyGrounded ) + { + if ( _currentlyGrounded ) + { + onCurrentlyGrounded?.Trigger(); + } + else + { + onCurrentlyUngrounded?.Trigger(); + } + } + + if ( _currentlyGrounded ) + { + _lastGroundedCollision.CopyFrom( _collisionData[ 0 ] ); + _durationSinceLastGrounded = 0; + } + + _grounded = _currentlyGrounded || _durationSinceLastGrounded < keepGroundedDuration; + + if ( g != _grounded ) + { + if ( _grounded ) + { + onGrounded?.Trigger(); + } + else + { + onUngrounded?.Trigger(); + } + } + + _durationSinceLastGrounded += controller.delta; + + if ( outputDebugInfo ) + { + currentlyGrounded = _currentlyGrounded; + grounded = _grounded; + groundedCollider = _collisionData[ 0 ].collider; + + if ( IsInstanceValid( groundedPositionTarget ) ) + { + groundedPositionTarget.GlobalPosition = _lastGroundedCollision.position; + } + } + + if ( ! isGrounded || ! resetVelocityWhenGrounded ) + { + return; + } + + + // for ( int i = 0; i < resetBlockers.Length; i++ ) + // { + // if ( resetBlockers[ i ].HasActiveForces() ) + // { + // return; + // } + // } + + + SetVelocity( Vector3.Zero ); + + } + + + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Grounding/Grounding.cs.uid b/Runtime/Interactions/CharacterController/Grounding/Grounding.cs.uid new file mode 100644 index 0000000..ec246a5 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Grounding/Grounding.cs.uid @@ -0,0 +1 @@ +uid://b6stp3kea0qo8 diff --git a/Runtime/Interactions/CharacterController/Grounding/GroundingType.cs b/Runtime/Interactions/CharacterController/Grounding/GroundingType.cs new file mode 100644 index 0000000..edfdf21 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Grounding/GroundingType.cs @@ -0,0 +1,36 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCGroundReset.svg")] + public abstract partial class GroundingType:Resource + { + protected abstract bool _IsGrounded( Grounding grounding, List collisionData ); + + public static bool IsGrounded( Grounding grounding, List collisionData ) + { + if ( grounding == null ) + { + return false; + } + + if ( grounding.groundingType == null ) + { + var grounded = grounding.body.IsOnFloor(); + + if ( grounded ) + { + collisionData[ 0 ].CopyFrom( grounding.body.GetLastSlideCollision() ); + } + + return grounded; + } + + return grounding.groundingType._IsGrounded( grounding, collisionData ); + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Grounding/GroundingType.cs.uid b/Runtime/Interactions/CharacterController/Grounding/GroundingType.cs.uid new file mode 100644 index 0000000..6b91947 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Grounding/GroundingType.cs.uid @@ -0,0 +1 @@ +uid://hrrp2b8esaws diff --git a/Runtime/Interactions/CharacterController/HeightDuration.cs b/Runtime/Interactions/CharacterController/HeightDuration.cs new file mode 100644 index 0000000..c1ba30d --- /dev/null +++ b/Runtime/Interactions/CharacterController/HeightDuration.cs @@ -0,0 +1,18 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class HeightDuration:Resource + { + [Export] + public float height = 1; + + [Export] + public float duration = 0.5f; + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/HeightDuration.cs.uid b/Runtime/Interactions/CharacterController/HeightDuration.cs.uid new file mode 100644 index 0000000..aa1660d --- /dev/null +++ b/Runtime/Interactions/CharacterController/HeightDuration.cs.uid @@ -0,0 +1 @@ +uid://0ao3381pywpg diff --git a/Runtime/Interactions/CharacterController/Jump.cs b/Runtime/Interactions/CharacterController/Jump.cs index f04d5df..ca3e5a3 100644 --- a/Runtime/Interactions/CharacterController/Jump.cs +++ b/Runtime/Interactions/CharacterController/Jump.cs @@ -15,28 +15,51 @@ namespace Rokojori [Export] public Action onJump; - [ExportGroup( "Jump Impulse")] - - [Export] - public float jumpImpulseStrength; - - [Export( PropertyHint.Range, "0,100" )] - public float velocityToJumpDirection = 0.5f; + [ExportGroup( "Jumping")] [Export] - public float velocityTresholdForJumpDirection = 1f; + public JumpStrength strength; + [Export] + public float minJumpDuration = 0.5f; + + [Export] + public Gravity gravity; + + + + [ExportGroup( "Movement")] + + [Export] + public float forwardStrength = 0; + + [Export] + public float rightStrength = 0; + + [Export] + public CharacterMovement movement; + + [Export( PropertyHint.Range, "0,5" )] + public float movementToJumpDirection = 0.5f; + + [Export( PropertyHint.Range, "0,100" )] + public float movementDirectionToFixedJumpDirection = 0.5f; + + [Export] + public float movementTresholdForJumpDirection = 1f; [ExportGroup( "Air Control")] + [Export] + public GravityStrength airControlGravityStrength; + + [Export] + public float maxAirControlDuration; + [Export] public Curve airControlCurveStrength = MathX.Curve( 1, 0 ); - [Export] - public float airMaxControlStrength; - [Export] - public float maxAirControlDuration; float jumpedDuration; @@ -46,91 +69,109 @@ namespace Rokojori bool needsToRelease = false; - bool inAir = false; - float airStart = 0; + bool jumping = false; + float jumpStart = 0; + + Vector3 jumpDirection; + + public override bool HasActiveForces() + { + return jumping; + } public bool IsJumping() { - return inAir; + return jumping; } - public float GetAirTime() + public float GetJumpStartTime() { - return airStart == -1 ? 0 : ( TimeLine.osTime - airStart ); + return jumpStart == -1 ? 0 : ( TimeLine.osTime - jumpStart ); } protected override void _OnTrigger() { - if ( body.IsOnFloor() ) + if ( ! jumping && isGrounded && button.isDown ) { - if ( inAir ) + _StartJump(); + } + + if ( jumping ) + { + _OnJumping(); + } + + } + + protected void _StartJump() + { + // jumpPressing = true; + jumpedDuration = 0; + jumping = true; + jumpStart = TimeLine.osTime; + + Trigger( onJump ); + + jumpDirection = Vector3.Up * strength.GetJumpStrength( this ); + + if ( movement != null ) + { + var currentMovement = movement.smoothedMovement * controller.delta; + this.LogInfo( body.Velocity, currentMovement ); + + if ( currentMovement.Length() > movementTresholdForJumpDirection ) { - inAir = false; - airStart = -1; + var xz = currentMovement; + xz.Y = 0; + + jumpDirection += xz * movementToJumpDirection + xz.Normalized() * movementDirectionToFixedJumpDirection; } - if ( jumpPressing ) - { - jumpPressing = false; - needsToRelease = true; - } } - if ( ! ( jumpPressing || body.IsOnFloor() ) ) - { - return; - } + jumpDirection += body.GlobalForward() * forwardStrength; + jumpDirection += body.GlobalRight() * rightStrength; - if ( ! button.isActive ) - { - jumpPressing = false; - needsToRelease = false; - return; - } + SetVelocity( jumpDirection, 1 ); + this.LogInfo( jumpDirection ); - if ( needsToRelease ) - { - return; - } + + } - if ( ! jumpPressing ) + protected void _OnJumping() + { + if ( jumping && jumpedDuration < minJumpDuration ) { - jumpPressing = true; - jumpedDuration = 0; - inAir = true; - airStart = TimeLine.osTime; - - Trigger( onJump ); + if ( controller.grounding != null ) + { + controller.grounding.ApplyUngroundedOverwrite(); + } - var jumpDirection = Vector3.Up * jumpImpulseStrength; + } - if ( body.Velocity.Length() > velocityTresholdForJumpDirection ) + if ( airControlGravityStrength != null && gravity != null && button.isHold && + jumpedDuration < maxAirControlDuration + ) + { + var gravityStrength = airControlGravityStrength.GetGravityStrength( gravity ); + var gravityStrengthMultiply = 1f; + + if ( airControlCurveStrength != null ) { - var xz = body.Velocity; - xz.Y = 0; - // xz = xz.Normalized(); - - jumpDirection += xz * velocityToJumpDirection; + gravityStrengthMultiply = airControlCurveStrength.Sample( jumpedDuration / maxAirControlDuration ); } - - SetVelocity( jumpDirection ); - - return; - + + AddVelocity( gravityStrength * Vector3.Up * gravityStrengthMultiply ); } jumpedDuration += controller.delta; - canJump = jumpedDuration < maxAirControlDuration; - - - if ( canJump ) + if ( jumpedDuration > minJumpDuration ) { - var jumpStrengthMultiply = airControlCurveStrength.Sample( jumpedDuration / maxAirControlDuration ); - AddVelocity( Vector3.Up * airMaxControlStrength * jumpStrengthMultiply ); + jumping = false; } - - } + + } } \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Jumping/HeightBasedJumpStrength.cs b/Runtime/Interactions/CharacterController/Jumping/HeightBasedJumpStrength.cs new file mode 100644 index 0000000..822896a --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/HeightBasedJumpStrength.cs @@ -0,0 +1,33 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class HeightBasedJumpStrength:JumpStrength + { + [Export] + public float height = 1; + + [Export] + public float airControlAmount = 1f; + + public override float GetJumpStrength( Jump jump ) + { + var gravityStrength = jump.gravity == null ? Gravity.EarthGravity : + jump.gravity.strength.GetGravityStrength( jump.gravity ); + + if ( airControlAmount > 0f ) + { + var airGravityStrength = jump.airControlGravityStrength.GetGravityStrength( jump.gravity ) * 0.5f; + + gravityStrength -= airGravityStrength * airControlAmount; + } + + return Mathf.Sqrt( 2f * gravityStrength * height ); + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Jumping/HeightBasedJumpStrength.cs.uid b/Runtime/Interactions/CharacterController/Jumping/HeightBasedJumpStrength.cs.uid new file mode 100644 index 0000000..3838838 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/HeightBasedJumpStrength.cs.uid @@ -0,0 +1 @@ +uid://dpqn3p0013myo diff --git a/Runtime/Interactions/CharacterController/Jumping/HeightDurationJumpStrength.cs b/Runtime/Interactions/CharacterController/Jumping/HeightDurationJumpStrength.cs new file mode 100644 index 0000000..1ad6ae5 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/HeightDurationJumpStrength.cs @@ -0,0 +1,20 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class HeightDurationJumpStrength:JumpStrength + { + [Export] + public HeightDuration heightDuration; + + public override float GetJumpStrength( Jump jump ) + { + return heightDuration.height * 2f / heightDuration.duration; + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Jumping/HeightDurationJumpStrength.cs.uid b/Runtime/Interactions/CharacterController/Jumping/HeightDurationJumpStrength.cs.uid new file mode 100644 index 0000000..4eb1e7a --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/HeightDurationJumpStrength.cs.uid @@ -0,0 +1 @@ +uid://dtgxngdobln4x diff --git a/Runtime/Interactions/CharacterController/Jumping/HumanJumpStrength.cs b/Runtime/Interactions/CharacterController/Jumping/HumanJumpStrength.cs new file mode 100644 index 0000000..8c86c54 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/HumanJumpStrength.cs @@ -0,0 +1,22 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class HumanJumpStrength:JumpStrength + { + public static readonly float HumanAverageStrength = 3; + + [Export] + public float humanPowerMultiply = 1f; + + public override float GetJumpStrength( Jump jump ) + { + return HumanJumpStrength.HumanAverageStrength * humanPowerMultiply; + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Jumping/HumanJumpStrength.cs.uid b/Runtime/Interactions/CharacterController/Jumping/HumanJumpStrength.cs.uid new file mode 100644 index 0000000..7fab317 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/HumanJumpStrength.cs.uid @@ -0,0 +1 @@ +uid://bp4v0yyavxvxc diff --git a/Runtime/Interactions/CharacterController/Jumping/JumpStrength.cs b/Runtime/Interactions/CharacterController/Jumping/JumpStrength.cs new file mode 100644 index 0000000..9923566 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/JumpStrength.cs @@ -0,0 +1,14 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public abstract partial class JumpStrength:Resource + { + public abstract float GetJumpStrength( Jump jump ); + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Jumping/JumpStrength.cs.uid b/Runtime/Interactions/CharacterController/Jumping/JumpStrength.cs.uid new file mode 100644 index 0000000..cfb95a6 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/JumpStrength.cs.uid @@ -0,0 +1 @@ +uid://c3t2qjq71h4gb diff --git a/Runtime/Interactions/CharacterController/Jumping/RawJumpStrength.cs b/Runtime/Interactions/CharacterController/Jumping/RawJumpStrength.cs new file mode 100644 index 0000000..1781dd2 --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/RawJumpStrength.cs @@ -0,0 +1,51 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; +using Godot.Collections; + +namespace Rokojori +{ + [Tool] + [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")] + public partial class RawJumpStrength:JumpStrength + { + [Export] + public float jumpImpulseStrength = 200; + + [ExportGroup( "Debug Info")] + [ExportToolButton( "Compute Height")] + public Callable computeHeightButton => Callable.From( + ( )=> + { + var y = 0f; + var v = jumpImpulseStrength; + var gravity = Gravity.EarthGravity; + var timeStep = 1f/60f; + var maxY = y; + var zeroTime = 0f; + var maxTime = -1f; + + while ( y >= 0 ) + { + v -= gravity * timeStep;; + y += v * timeStep; + + if ( y > maxY ) + { + maxY = Mathf.Max( y, maxY ); + maxTime = zeroTime; + } + + zeroTime += timeStep; + } + + this.LogInfo( "MaxY:", maxY, "Max Time:", maxTime, "Zero Time:", zeroTime ); + } + ); + + public override float GetJumpStrength( Jump jump ) + { + return jumpImpulseStrength; + } + } +} \ No newline at end of file diff --git a/Runtime/Interactions/CharacterController/Jumping/RawJumpStrength.cs.uid b/Runtime/Interactions/CharacterController/Jumping/RawJumpStrength.cs.uid new file mode 100644 index 0000000..5e8620a --- /dev/null +++ b/Runtime/Interactions/CharacterController/Jumping/RawJumpStrength.cs.uid @@ -0,0 +1 @@ +uid://c3uursukaal3n diff --git a/Runtime/Physics/CollisionData.cs b/Runtime/Physics/CollisionData.cs index 325d235..80fd04f 100644 --- a/Runtime/Physics/CollisionData.cs +++ b/Runtime/Physics/CollisionData.cs @@ -16,6 +16,61 @@ namespace Rokojori public Rid rid; + public void CopyFrom( KinematicCollision3D kinematicCollision3D, int collisionIndex = 0 ) + { + if ( kinematicCollision3D.GetCollisionCount() <= collisionIndex ) + { + Reset(); + return; + } + + hasCollision = true; + position = kinematicCollision3D.GetPosition(); + normal = kinematicCollision3D.GetNormal(); + collider = (Node) kinematicCollision3D.GetCollider( collisionIndex ); + rid = (Rid) kinematicCollision3D.GetColliderRid( collisionIndex ); + shape = (Shape3D) kinematicCollision3D.GetColliderShape( collisionIndex ); + } + + void Reset() + { + hasCollision = false; + + position = Vector3.Zero; + normal = Vector3.Up; + collider = null; + rid = new Rid(); + shape = null; + } + + public void CopyFrom( CollisionData collisionData ) + { + if ( ! collisionData.hasCollision ) + { + Reset(); + return; + } + + hasCollision = true; + position = collisionData.position; + normal = collisionData.normal; + collider = collisionData.collider; + rid = collisionData.rid; + shape = collisionData.shape; + } + + public static List ForMaxHits( int maxHits ) + { + var data = new List(); + + for ( int i = 0; i < maxHits; i++ ) + { + data.Add( new CollisionData() ); + } + + return data; + } + public static bool HasCollisionMask( Node n ) { return n is CsgShape3D || n is CollisionObject3D; @@ -85,7 +140,7 @@ namespace Rokojori { var physics = world.DirectSpaceState; - var excludes = new Array(); + var excludes = rayParameters.Exclude; var maxHits = 10000; @@ -118,7 +173,7 @@ namespace Rokojori { var physics = world.DirectSpaceState; - var excludes = new Array(); + var excludes = rayParameters.Exclude; var numCollisions = 0; @@ -147,7 +202,7 @@ namespace Rokojori { var physics = world.DirectSpaceState; - var excludes = new Array(); + var excludes = rayParameters.Exclude; var collisions = new List(); diff --git a/Runtime/Physics/PhysicsRayCast.cs b/Runtime/Physics/PhysicsRayCast.cs new file mode 100644 index 0000000..5d4a739 --- /dev/null +++ b/Runtime/Physics/PhysicsRayCast.cs @@ -0,0 +1,60 @@ +using Godot; +using System.Collections; +using System.Collections.Generic; + +namespace Rokojori +{ + public class PhysicsRayCast + { + public static CollisionData GetFirst( CharacterBody3D body, Vector3 from, Vector3 to ) + { + var world = body.GetWorld3D(); + var rayParameters = new PhysicsRayQueryParameters3D + { + From = from, + To = to, + CollisionMask = body.CollisionMask, + CollideWithAreas = false, + CollideWithBodies = true + }; + + rayParameters.Exclude = [ body.GetRid() ]; + var hits = CollisionData.MultiRayCast( world, rayParameters, 1 ); + + return hits.Count == 0 ? null : hits[ 0 ]; + } + + public static CollisionData GetFirst( CharacterBody3D body, Vector3 direction ) + { + var from = body.GlobalPosition; + var to = from + direction; + + return GetFirst( body, from, to ); + } + + public static int GetAll( List outputCollisionData, CharacterBody3D body, Vector3 from, Vector3 to ) + { + var world = body.GetWorld3D(); + var rayParameters = new PhysicsRayQueryParameters3D + { + From = from, + To = to, + CollisionMask = body.CollisionMask, + CollideWithAreas = false, + CollideWithBodies = true + }; + + rayParameters.Exclude = [ body.GetRid() ]; + return CollisionData.MultiRayCast( world, rayParameters, outputCollisionData ); + } + + public static int GetAll( List outputCollisionData, CharacterBody3D body, Vector3 direction ) + { + var from = body.GlobalPosition; + var to = from + direction; + + return GetAll( outputCollisionData, body, from, to ); + } + + } +} \ No newline at end of file diff --git a/Runtime/Physics/PhysicsRayCast.cs.uid b/Runtime/Physics/PhysicsRayCast.cs.uid new file mode 100644 index 0000000..a84ab1b --- /dev/null +++ b/Runtime/Physics/PhysicsRayCast.cs.uid @@ -0,0 +1 @@ +uid://cu5o06n50gy8g diff --git a/Runtime/Sensors/SensorManager.cs b/Runtime/Sensors/SensorManager.cs index 4763ae2..adf6bf3 100644 --- a/Runtime/Sensors/SensorManager.cs +++ b/Runtime/Sensors/SensorManager.cs @@ -138,7 +138,7 @@ namespace Rokojori hasDevice = true; - this.LogInfo( "Device Type Change:", lastActiveDevice.GetInfo() ); + // this.LogInfo( "Device Type Change:", lastActiveDevice.GetInfo() ); if ( confineMouse && DefaultSensorDeviceSelector.IsMouseDevice( lastActiveDevice ) ) { diff --git a/rokojori-action-library-images.svg b/rokojori-action-library-images.svg index 85193a3..19c575f 100644 --- a/rokojori-action-library-images.svg +++ b/rokojori-action-library-images.svg @@ -25,17 +25,50 @@ inkscape:deskcolor="#333333" inkscape:document-units="px" showgrid="false" - inkscape:zoom="0.53305" - inkscape:cx="308.60144" - inkscape:cy="5012.663" + inkscape:zoom="0.266525" + inkscape:cx="834.8185" + inkscape:cy="1804.7087" inkscape:window-width="1920" inkscape:window-height="1017" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" - inkscape:current-layer="layer5" />WINTERTALESWINTERTALESWINTERTALESWINTERTALESWINTERTALESWINTERTALESWINTERTALESWINTERTALES