Added ground-like movement (i.e. air control when close to ground) and wall jumping away from the wall is always possible even when facing it

This commit is contained in:
2026-01-12 11:52:35 +01:00
parent 66be7838bb
commit 04054cfeae
3 changed files with 45 additions and 15 deletions

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=48 format=3 uid="uid://bei4nhkf8lwdo"]
[gd_scene load_steps=49 format=3 uid="uid://bei4nhkf8lwdo"]
[ext_resource type="Script" uid="uid://bbbrf5ckydfna" path="res://player_controller/Scripts/PlayerController.cs" id="1_poq2x"]
[ext_resource type="PackedScene" uid="uid://cf3rrgr1imvv4" path="res://scenes/path/path.tscn" id="2_6lejt"]
@@ -57,6 +57,10 @@ top_radius = 0.2
bottom_radius = 0.2
height = 1.0
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_6lejt"]
radius = 1.0
height = 3.0
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_2q0ik"]
blend_mode = 1
@@ -179,7 +183,6 @@ target_position = Vector3(0, 1, 0)
[node name="TweenQueueSystem" parent="." instance=ExtResource("22_rpwev")]
[node name="WallHugSystem" type="Node3D" parent="."]
visible = false
script = ExtResource("27_n7qhm")
[node name="back" type="RayCast3D" parent="WallHugSystem"]
@@ -236,6 +239,11 @@ visible = false
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 0, -1)
mesh = SubResource("CylinderMesh_nodcl")
[node name="GroundDetector" type="ShapeCast3D" parent="."]
shape = SubResource("CapsuleShape3D_6lejt")
target_position = Vector3(0, -0.5, 0)
collision_mask = 2
[node name="DashCooldown" type="Timer" parent="."]
wait_time = 0.8
one_shot = true
@@ -698,12 +706,6 @@ delay_in_seconds = "0.0"
script = ExtResource("26_infe6")
initial_state = NodePath("Hugging")
[node name="OnDash" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Dashing/Dash")
event = &"dash"
delay_in_seconds = "0.0"
[node name="OnGrounded" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Grounded")
@@ -746,6 +748,12 @@ delay_in_seconds = "0.0"
[node name="Hugging" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("27_34snm")
[node name="OnDash" type="Node" parent="StateChart/Root/Movement/OnWall/Hugging"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Dashing/Dash")
event = &"dash"
delay_in_seconds = "0.0"
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/OnWall/Hugging"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Jump/DoubleJump")
@@ -755,6 +763,12 @@ delay_in_seconds = "0.0"
[node name="Hanging" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("27_34snm")
[node name="OnDash" type="Node" parent="StateChart/Root/Movement/OnWall/Hanging"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Dashing/Dash")
event = &"dash"
delay_in_seconds = "0.0"
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/OnWall/Hanging"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Jump/DoubleJump")

View File

@@ -44,6 +44,7 @@ public partial class PlayerController : CharacterBody3D
public MeshInstance3D DashIndicatorMesh;
public CylinderMesh DashIndicatorMeshCylinder;
public RayCast3D WallRunSnapper;
public ShapeCast3D GroundDetector;
private bool _movementEnabled = true;
@@ -296,6 +297,7 @@ public partial class PlayerController : CharacterBody3D
StairsSystem = GetNode<StairsSystem>("StairsSystem");
WallHugSystem = GetNode<WallHugSystem>("WallHugSystem");
WallRunSnapper = GetNode<RayCast3D>("%WallRunSnapper");
GroundDetector = GetNode<ShapeCast3D>("GroundDetector");
RayCast3D stairsBelowRayCast3D = GetNode<RayCast3D>("StairsBelowRayCast3D");
RayCast3D stairsAheadRayCast3D = GetNode<RayCast3D>("StairsAheadRayCast3D");
_headCollisionDetectors = new RayCast3D[NUM_OF_HEAD_COLLISION_DETECTORS];
@@ -442,6 +444,15 @@ public partial class PlayerController : CharacterBody3D
_onLeaveWallFromRunCoyote.Taken += OnLeaveWallFromRun;
}
public void OnGroundDetected(Node3D _)
{
GD.Print("Ground-like");
}
public void OnGroundLost(Node3D _)
{
GD.Print("Ground-less");
}
public void SetAllowedInputsAll()
{
CurrentlyAllowedInputs = AllowedInputs.All;
@@ -540,7 +551,8 @@ public partial class PlayerController : CharacterBody3D
public void HandleAirborne(float delta)
{
MoveInAir(delta);
var isGroundLike = GroundDetector.GetCollisionResult().Count > 0;
MoveInAir(delta, isGroundLike);
if (isOnFloorCustom())
_playerState.SendEvent("grounded");
@@ -627,6 +639,9 @@ public partial class PlayerController : CharacterBody3D
public void HandleWallHugging(float delta)
{
_canDash = true;
_canDashAirborne = true;
WallHug(delta);
if (isOnFloorCustom())
_playerState.SendEvent("grounded");
@@ -642,6 +657,9 @@ public partial class PlayerController : CharacterBody3D
public void HandleWallRunning(float delta)
{
_canDash = false;
_canDashAirborne = false;
// Find horizontal velocity projected on the current wall
var hvel = new Vector3(Velocity.X, 0, Velocity.Z);
var hvelProjected = hvel.Slide(_wallHugStartNormal);
@@ -703,7 +721,6 @@ public partial class PlayerController : CharacterBody3D
return;
}
if (_onWall.Active && !_isWallJumpAvailable && IsFacingWall()) return;
_playerState.SendEvent("jump");
}
@@ -766,7 +783,7 @@ public partial class PlayerController : CharacterBody3D
public void OnJumpFromWall()
{
if (!IsFacingWall())
if (!IsFacingWall() || (!_isWallJumpAvailable && IsFacingWall()))
{
ComputeJumpFromWallHSpeed(WallJumpStartVelocity);
}
@@ -1330,9 +1347,9 @@ public partial class PlayerController : CharacterBody3D
Velocity = new Vector3(horizontalVelocity.X, Velocity.Y, horizontalVelocity.Z);
}
public void MoveInAir(double delta)
public void MoveInAir(double delta, bool isGroundLike = false)
{
var horizontalVelocity = ComputeHVelocityAir((float) delta);
var horizontalVelocity = isGroundLike ? ComputeHVelocityGround((float) delta) : ComputeHVelocityAir((float) delta);
var verticalVelocity = Velocity.Y - (CalculateGravityForce() * (float)delta);
Velocity = new Vector3(horizontalVelocity.X, verticalVelocity, horizontalVelocity.Z);
}
@@ -1471,7 +1488,6 @@ public partial class PlayerController : CharacterBody3D
CameraModifications((float) delta);
HandleStairs((float) delta);
MantleSystem.ProcessMantle(_grounded.Active);
if (WeaponSystem.InHandState.Active)
RotateWeaponWithPlayer();

View File

@@ -20,6 +20,6 @@ public partial class Path : Path3D
public void Teardown()
{
QueueFree();
if (!IsQueuedForDeletion()) QueueFree();
}
}