rj-action-library/Runtime/Interactions/CharacterController/MoveAndSlide.cs

80 lines
2.0 KiB
C#

using Godot;
using System.Collections;
using System.Collections.Generic;
using Godot.Collections;
namespace Rokojori
{
[Tool]
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCMoveAndSlide.svg")]
public partial class MoveAndSlide:CharacterControllerAction
{
[Export]
public bool useStepping = false;
[Export]
public float stepMaxHeight = 0.2f;
protected override void _OnTrigger()
{
var body = controller.body;
var motion = controller.body.Velocity * controller.delta;
var collision = body.MoveAndCollide( motion, testOnly: true );
if ( collision != null && StepUp( motion ) )
{
return;
}
controller.body.MoveAndSlide();
}
protected bool StepUp( Vector3 motion )
{
var up = Vector3.Up * stepMaxHeight;
var hitAbove = controller.body.TestMove( controller.body.GlobalTransform, up );
if ( hitAbove )
{
return false;
}
bool hitForward = controller.body.TestMove( controller.body.GlobalTransform.Translated( up ), motion );
if ( ! hitForward )
{
var space = controller.body.GetWorld3D().DirectSpaceState;
var origin = controller.body.GlobalPosition;
var stepUpOrigin = controller.body.GlobalPosition + up;
var downHit = space.IntersectRay(
new PhysicsRayQueryParameters3D
{
From = stepUpOrigin,
To = stepUpOrigin + Vector3.Down * ( stepMaxHeight + 0.1f ),
CollisionMask = 1,
CollideWithAreas = false,
CollideWithBodies = true
}
);
if ( downHit.Count == 0 )
{
return false;
}
var exactStepAmount = downHit[ "position" ].AsVector3().Y - origin.Y;
if ( exactStepAmount > 0 && exactStepAmount <= stepMaxHeight )
{
controller.body.GlobalTranslate( new Vector3( 0, exactStepAmount, 0 ) );
return true;
}
}
return false;
}
}
}