CharacterController Update

This commit is contained in:
Josef 2025-12-21 19:56:48 +01:00
parent 81cf77ce54
commit f37b4b41c8
39 changed files with 119267 additions and 140 deletions

View File

@ -12,6 +12,9 @@ namespace Rokojori
[Export] [Export]
public CharacterBody3D body; public CharacterBody3D body;
[Export]
public Grounding grounding;
public enum CharacterUpdateMode public enum CharacterUpdateMode
{ {
Process, Process,
@ -39,10 +42,17 @@ namespace Rokojori
[Export] [Export]
public float lastGroundedHeight = 0; public float lastGroundedHeight = 0;
public float delta = 0; public float delta = 0;
public bool isGrounded
{
get
{
return grounding == null ? body.IsOnFloor() : grounding.isGrounded;
}
}
public override void _Process( double delta ) public override void _Process( double delta )
{ {
if ( Engine.IsEditorHint() && graphics == null || body == null ) if ( Engine.IsEditorHint() && graphics == null || body == null )
@ -55,7 +65,7 @@ namespace Rokojori
ProcessActions( (float) delta ); ProcessActions( (float) delta );
} }
if ( body.IsOnFloor() ) if ( isGrounded )
{ {
lastGroundedHeight = graphics.GlobalPosition.Y; lastGroundedHeight = graphics.GlobalPosition.Y;
} }

View File

@ -21,16 +21,39 @@ namespace Rokojori
[Export] [Export]
public SceneCondition sceneCondition; public SceneCondition sceneCondition;
[Export]
public CharacterControllerAction[] blockers = [];
public bool isGrounded => _controller.isGrounded;
public void SetCharacterController( CharacterController cc ) public void SetCharacterController( CharacterController cc )
{ {
_controller = cc; _controller = cc;
} }
public virtual bool HasActiveForces()
{
return false;
}
public CharacterBody3D body => controller.body; 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 ) public void AddVelocity( Vector3 velocity, float delta = -1 )
{ {
if ( blockersActive )
{
return;
}
delta = delta < 0 ? controller.delta : delta; delta = delta < 0 ? controller.delta : delta;
body.Velocity += velocity * delta; body.Velocity += velocity * delta;
@ -38,11 +61,21 @@ namespace Rokojori
public void SetScaledVelocity( float scale ) public void SetScaledVelocity( float scale )
{ {
if ( blockersActive )
{
return;
}
body.Velocity *= scale; body.Velocity *= scale;
} }
public void SetVelocity( Vector3 velocity, float delta = -1 ) public void SetVelocity( Vector3 velocity, float delta = -1 )
{ {
if ( blockersActive )
{
return;
}
delta = delta < 0 ? controller.delta : delta; delta = delta < 0 ? controller.delta : delta;
body.Velocity = velocity * delta; body.Velocity = velocity * delta;
} }

View File

@ -103,7 +103,7 @@ namespace Rokojori
protected override void _OnTrigger() protected override void _OnTrigger()
{ {
var onFloor = body.IsOnFloor(); var onFloor = isGrounded;
_onFloor = onFloor; _onFloor = onFloor;
characterMovementData.Reset( this ); characterMovementData.Reset( this );

View File

@ -9,17 +9,24 @@ namespace Rokojori
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCGravity.svg")] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCGravity.svg")]
public partial class Gravity:CharacterControllerAction public partial class Gravity:CharacterControllerAction
{ {
public static readonly float EarthGravity = 9.80665f;
[Export] [Export]
public float strength = 10; public GravityStrength strength;
[Export]
public GravityStrength fallingStrength;
protected override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( body.IsOnFloor() ) if ( isGrounded || strength == null )
{ {
return; 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 ) );
} }
} }
} }

View File

@ -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;
}
}
}

View File

@ -0,0 +1 @@
uid://dug045ws8o2fy

View File

@ -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 );
}
}

View File

@ -0,0 +1 @@
uid://bey6k6vokedqx

View File

@ -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 );
}
}
}

View File

@ -0,0 +1 @@
uid://c0qpyxi2615lf

View File

@ -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;
}
}
}

View File

@ -0,0 +1 @@
uid://cgg7rx8nnpqv5

View File

@ -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 );
}
}
}

View File

@ -0,0 +1 @@
uid://qstgyis6jyd6

View File

@ -11,7 +11,7 @@ namespace Rokojori
{ {
protected override void _OnTrigger() protected override void _OnTrigger()
{ {
if ( ! body.IsOnFloor() ) if ( ! isGrounded )
{ {
return; return;
} }

View File

@ -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> 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;
}
}
}

View File

@ -0,0 +1 @@
uid://bs6oahk3jrjcq

View File

@ -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 = 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 );
}
}
}

View File

@ -0,0 +1 @@
uid://b6stp3kea0qo8

View File

@ -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> collisionData );
public static bool IsGrounded( Grounding grounding, List<CollisionData> 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 );
}
}
}

View File

@ -0,0 +1 @@
uid://hrrp2b8esaws

View File

@ -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;
}
}

View File

@ -0,0 +1 @@
uid://0ao3381pywpg

View File

@ -15,28 +15,51 @@ namespace Rokojori
[Export] [Export]
public Action onJump; public Action onJump;
[ExportGroup( "Jump Impulse")] [ExportGroup( "Jumping")]
[Export] [Export]
public float jumpImpulseStrength; 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" )] [Export( PropertyHint.Range, "0,100" )]
public float velocityToJumpDirection = 0.5f; public float movementDirectionToFixedJumpDirection = 0.5f;
[Export] [Export]
public float velocityTresholdForJumpDirection = 1f; public float movementTresholdForJumpDirection = 1f;
[ExportGroup( "Air Control")] [ExportGroup( "Air Control")]
[Export]
public GravityStrength airControlGravityStrength;
[Export]
public float maxAirControlDuration;
[Export] [Export]
public Curve airControlCurveStrength = MathX.Curve( 1, 0 ); public Curve airControlCurveStrength = MathX.Curve( 1, 0 );
[Export]
public float airMaxControlStrength;
[Export]
public float maxAirControlDuration;
float jumpedDuration; float jumpedDuration;
@ -46,91 +69,109 @@ namespace Rokojori
bool needsToRelease = false; bool needsToRelease = false;
bool inAir = false; bool jumping = false;
float airStart = 0; float jumpStart = 0;
Vector3 jumpDirection;
public override bool HasActiveForces()
{
return jumping;
}
public bool IsJumping() 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() 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; var xz = currentMovement;
airStart = -1;
}
if ( jumpPressing )
{
jumpPressing = false;
needsToRelease = true;
}
}
if ( ! ( jumpPressing || body.IsOnFloor() ) )
{
return;
}
if ( ! button.isActive )
{
jumpPressing = false;
needsToRelease = false;
return;
}
if ( needsToRelease )
{
return;
}
if ( ! jumpPressing )
{
jumpPressing = true;
jumpedDuration = 0;
inAir = true;
airStart = TimeLine.osTime;
Trigger( onJump );
var jumpDirection = Vector3.Up * jumpImpulseStrength;
if ( body.Velocity.Length() > velocityTresholdForJumpDirection )
{
var xz = body.Velocity;
xz.Y = 0; xz.Y = 0;
// xz = xz.Normalized();
jumpDirection += xz * velocityToJumpDirection; jumpDirection += xz * movementToJumpDirection + xz.Normalized() * movementDirectionToFixedJumpDirection;
} }
SetVelocity( jumpDirection ); }
return; jumpDirection += body.GlobalForward() * forwardStrength;
jumpDirection += body.GlobalRight() * rightStrength;
SetVelocity( jumpDirection, 1 );
this.LogInfo( jumpDirection );
}
protected void _OnJumping()
{
if ( jumping && jumpedDuration < minJumpDuration )
{
if ( controller.grounding != null )
{
controller.grounding.ApplyUngroundedOverwrite();
}
}
if ( airControlGravityStrength != null && gravity != null && button.isHold &&
jumpedDuration < maxAirControlDuration
)
{
var gravityStrength = airControlGravityStrength.GetGravityStrength( gravity );
var gravityStrengthMultiply = 1f;
if ( airControlCurveStrength != null )
{
gravityStrengthMultiply = airControlCurveStrength.Sample( jumpedDuration / maxAirControlDuration );
}
AddVelocity( gravityStrength * Vector3.Up * gravityStrengthMultiply );
} }
jumpedDuration += controller.delta; jumpedDuration += controller.delta;
canJump = jumpedDuration < maxAirControlDuration; if ( jumpedDuration > minJumpDuration )
if ( canJump )
{ {
var jumpStrengthMultiply = airControlCurveStrength.Sample( jumpedDuration / maxAirControlDuration ); jumping = false;
AddVelocity( Vector3.Up * airMaxControlStrength * jumpStrengthMultiply );
} }
} }
} }
} }

View File

@ -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 );
}
}
}

View File

@ -0,0 +1 @@
uid://dpqn3p0013myo

View File

@ -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;
}
}
}

View File

@ -0,0 +1 @@
uid://dtgxngdobln4x

View File

@ -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;
}
}
}

View File

@ -0,0 +1 @@
uid://bp4v0yyavxvxc

View File

@ -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 );
}
}

View File

@ -0,0 +1 @@
uid://c3t2qjq71h4gb

View File

@ -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;
}
}
}

View File

@ -0,0 +1 @@
uid://c3uursukaal3n

View File

@ -16,6 +16,61 @@ namespace Rokojori
public Rid rid; 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<CollisionData> ForMaxHits( int maxHits )
{
var data = new List<CollisionData>();
for ( int i = 0; i < maxHits; i++ )
{
data.Add( new CollisionData() );
}
return data;
}
public static bool HasCollisionMask( Node n ) public static bool HasCollisionMask( Node n )
{ {
return n is CsgShape3D || n is CollisionObject3D; return n is CsgShape3D || n is CollisionObject3D;
@ -85,7 +140,7 @@ namespace Rokojori
{ {
var physics = world.DirectSpaceState; var physics = world.DirectSpaceState;
var excludes = new Array<Rid>(); var excludes = rayParameters.Exclude;
var maxHits = 10000; var maxHits = 10000;
@ -118,7 +173,7 @@ namespace Rokojori
{ {
var physics = world.DirectSpaceState; var physics = world.DirectSpaceState;
var excludes = new Array<Rid>(); var excludes = rayParameters.Exclude;
var numCollisions = 0; var numCollisions = 0;
@ -147,7 +202,7 @@ namespace Rokojori
{ {
var physics = world.DirectSpaceState; var physics = world.DirectSpaceState;
var excludes = new Array<Rid>(); var excludes = rayParameters.Exclude;
var collisions = new List<CollisionData>(); var collisions = new List<CollisionData>();

View File

@ -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<CollisionData> 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<CollisionData> outputCollisionData, CharacterBody3D body, Vector3 direction )
{
var from = body.GlobalPosition;
var to = from + direction;
return GetAll( outputCollisionData, body, from, to );
}
}
}

View File

@ -0,0 +1 @@
uid://cu5o06n50gy8g

View File

@ -138,7 +138,7 @@ namespace Rokojori
hasDevice = true; hasDevice = true;
this.LogInfo( "Device Type Change:", lastActiveDevice.GetInfo() ); // this.LogInfo( "Device Type Change:", lastActiveDevice.GetInfo() );
if ( confineMouse && DefaultSensorDeviceSelector.IsMouseDevice( lastActiveDevice ) ) if ( confineMouse && DefaultSensorDeviceSelector.IsMouseDevice( lastActiveDevice ) )
{ {

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 45 MiB

After

Width:  |  Height:  |  Size: 53 MiB