fix: player considers whether the hang ray is reachable

This commit is contained in:
Sara Gerretsen 2026-05-20 15:15:25 +02:00
parent ec5d9727f1
commit cdf5b018bf
3 changed files with 23 additions and 3 deletions

View file

@ -13,6 +13,7 @@ void PlayerBehaviourTree::_bind_methods() {
BIND_HPROPERTY(Variant::OBJECT, anim, PROPERTY_HINT_NODE_TYPE, "AnimationPlayer", PROPERTY_USAGE_READ_ONLY);
BIND_HPROPERTY(Variant::OBJECT, hang_ray, PROPERTY_HINT_NODE_TYPE, "RayCast3D", PROPERTY_USAGE_READ_ONLY);
BIND_HPROPERTY(Variant::OBJECT, ground_ray, PROPERTY_HINT_NODE_TYPE, "RayCast3D", PROPERTY_USAGE_READ_ONLY);
BIND_HPROPERTY(Variant::OBJECT, high_wall_ray, PROPERTY_HINT_NODE_TYPE, "RayCast3D", PROPERTY_USAGE_READ_ONLY);
ClassDB::bind_method(D_METHOD("get_world_move_input"), &self_type::get_world_move_input);
ClassDB::bind_method(D_METHOD("get_ground_distance"), &self_type::get_ground_distance);
}
@ -32,6 +33,7 @@ void PlayerBehaviourTree::_notification(int what) {
if (this->character) {
this->anim = cast_to<AnimationTree>(this->character->get_node(NodePath("AnimationTree")));
this->hang_ray = cast_to<RayCast3D>(this->character->get_node(NodePath("HangRay")));
this->high_wall_ray = cast_to<RayCast3D>(this->character->get_node(NodePath("HighWallRay")));
}
return;
case NOTIFICATION_READY:

View file

@ -26,6 +26,7 @@ private:
AnimationTree *anim{ nullptr };
RayCast3D *hang_ray{ nullptr };
RayCast3D *ground_ray{ nullptr };
RayCast3D *high_wall_ray{ nullptr };
public:
GET_SET_FNS(RayCast3D *, ground_ray);
@ -34,5 +35,6 @@ public:
GET_SET_FNS(Node3D *, character);
GET_SET_FNS(AnimationTree *, anim);
GET_SET_FNS(RayCast3D *, hang_ray);
GET_SET_FNS(RayCast3D *, high_wall_ray);
float get_ground_distance() const;
};

View file

@ -192,6 +192,16 @@ func _physics_process(_delta : float):
global_position = body.global_position + Vector3.UP * height + last_direction * dist_mul
"
[sub_resource type="GDScript" id="GDScript_4vq5b"]
resource_name = "PlayerHighWallRay"
script/source = "extends RayCast3D
func _process(_delta : float):
target_position = $\"../HangRay\".global_position - global_position
global_rotation = Vector3.ZERO
global_position = get_parent_node_3d().global_position + Vector3.UP * 2.0
"
[sub_resource type="GDScript" id="GDScript_3rerk"]
resource_name = "BelowLedgePrerequisite"
script/source = "extends PlayerAction
@ -204,7 +214,8 @@ func _ready():
func _enter() -> int:
blackboard.hang_ray.force_raycast_update()
blackboard.ground_ray.force_raycast_update()
if not timeout and not body.is_on_floor() and blackboard.hang_ray.is_colliding():
blackboard.high_wall_ray.force_raycast_update()
if not timeout and not body.is_on_floor() and blackboard.hang_ray.is_colliding() and not blackboard.high_wall_ray.is_colliding():
var wall_normal_y : float = blackboard.hang_ray.get_collision_normal().y
var edge_distance : float = blackboard.hang_ray.get_collision_point().distance_to(blackboard.hang_ray.global_position)
if wall_normal_y > 0.9 and body.is_on_wall() and blackboard.get_ground_distance() > edge_distance:
@ -289,7 +300,7 @@ func _enter() -> int:
var flat_velocity := Vector2(body.velocity.x, body.velocity.z)
var input_velocity_dot : float = blackboard.get_world_move_input().normalized().dot(body.velocity.normalized())
var ground_velocity := Vector3(body.velocity.x, 0, body.velocity.z)
if body.is_on_wall_only() and input_velocity_dot > 0.01 and ground_velocity.length() >= min_ground_speed and flat_velocity.length() > -body.velocity.y * 4.0 and not blackboard.hang_ray.is_colliding():
if body.is_on_wall_only() and input_velocity_dot > 0.01 and ground_velocity.length() >= min_ground_speed and flat_velocity.length() > -body.velocity.y * 4.0:
if Input.is_action_just_pressed(\"jump\") and run_time > min_run_time:
var wall_flat := Vector3(body.get_wall_normal().x, 0, body.get_wall_normal().z)
body.velocity = wall_flat * jump_normal_force + (ground_velocity + blackboard.get_world_move_input()).normalized() * jump_input_force * ground_velocity.length()
@ -324,7 +335,7 @@ script/source = "extends PlayerAction
func _enter() -> int:
var flat_wall := Vector3(body.get_wall_normal().x, 0, body.get_wall_normal().z)
var input_into_wall := blackboard.get_world_move_input().normalized().dot(body.get_wall_normal()) < 0.1
if body.is_on_wall_only() and input_into_wall and not blackboard.hang_ray.is_colliding() and blackboard.get_ground_distance() > .5 and body.velocity.y < 1.0:
if body.is_on_wall_only() and input_into_wall and blackboard.get_ground_distance() > .5 and body.velocity.y < 1.0:
if Input.is_action_just_pressed(\"jump\"):
body.velocity = flat_wall * jump_normal_force
body.velocity.y = jump_vertical_force
@ -433,6 +444,11 @@ target_position = Vector3(0, -2, 0)
script = SubResource("GDScript_f46kd")
dist_mul = -0.508
[node name="HighWallRay" type="RayCast3D" parent="PlayerModel" unique_id=2283840]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
target_position = Vector3(0, 0, -0.5)
script = SubResource("GDScript_4vq5b")
[node name="Camera3D" type="PlayerCamera" parent="." unique_id=709217818]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.3841858e-07, 0.81082594, 1.2089427)
fov = 96.8