Fix slow slope speed with CharacterBody3D's Constant Speed instead

This commit is contained in:
Jens Pitkänen 2026-07-26 21:45:23 +03:00
parent 2c7fef2bfa
commit b8578a0a95
3 changed files with 13 additions and 37 deletions

View File

@ -37,6 +37,8 @@ hit_sound = NodePath("hit_sound")
health = 100
punch_cooldown = 1.0
collision_mask = 4
slide_on_ceiling = false
floor_constant_speed = true
[node name="camera_3d" type="Camera3D" parent="." unique_id=1773137418]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.8724979, -0.2644562)

View File

@ -46,6 +46,8 @@ health_bar = NodePath("health_bar_sprite/health_bar_viewport/health_bar")
health_bar_sprite = NodePath("health_bar_sprite")
collision_layer = 2
collision_mask = 4
slide_on_ceiling = false
floor_constant_speed = true
[node name="soldier_m" parent="." unique_id=281995630 instance=ExtResource("1_e2ekk")]
transform = Transform3D(-0.5, 0, -4.371139e-08, 0, 0.5, 0, 4.371139e-08, 0, -0.5, 0, 0, 0)

View File

@ -1,10 +1,6 @@
use std::{collections::HashSet, f32::consts::PI, ops::Neg};
use godot::{
classes::{ICharacterBody3D, KinematicCollision3D},
obj::WithBaseField,
prelude::*,
};
use godot::{classes::ICharacterBody3D, obj::WithBaseField, prelude::*};
use serde::{Deserialize, Serialize};
use crate::{
@ -74,47 +70,23 @@ pub trait PlayerCommon {
impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
fn player_update(&mut self, delta: f64) {
// Gravity
self.set_y_speed(self.get_y_speed() - 9.8 * delta as f32);
if self.base().is_on_floor() && self.get_y_speed() < 0. {
self.set_y_speed(0.);
}
let vertical_velocity = Vector3::UP * self.get_y_speed();
// Figure out the ground plane normal (to move on the right plane)
let mut up_vector = Vector3::UP;
let mut most_upward_coll: Option<Gd<KinematicCollision3D>> = None;
for coll in (0..self.base().get_slide_collision_count())
.flat_map(|i| self.base().get_slide_collision(i))
{
let coll_norm_y = coll.get_normal().y;
if let Some(prev_most_upward) = &most_upward_coll {
if coll_norm_y > prev_most_upward.get_normal().y {
most_upward_coll = Some(coll);
}
} else if coll_norm_y > 0.5 {
// sin(30 deg) == 0.5, so this only accepts 30 deg or shallower slopes
most_upward_coll = Some(coll);
}
}
if let Some(coll) = most_upward_coll {
up_vector = coll.get_normal();
}
let speed = Vector3::UP * self.get_y_speed()
+ self
.get_movement_dir()
.try_normalized()
.unwrap_or_default()
.rotated(Vector3::UP, self.base().get_rotation().y)
* self.get_move_speed();
// Ground movement (along the plane the player is currently on)
let input_move_on_xz = self.get_movement_dir().try_normalized().unwrap_or_default();
let ground_plane_basis = Basis::from_axis_angle(up_vector, self.base().get_rotation().y);
let input_move_on_ground_plane = ground_plane_basis * input_move_on_xz;
let move_speed = self.get_move_speed();
let ground_plane_velocity = input_move_on_ground_plane * move_speed;
// Commit
if self.is_dead() {
self.base_mut().set_velocity(Vector3::ZERO);
} else {
self.base_mut()
.set_velocity(vertical_velocity + ground_plane_velocity);
self.base_mut().set_velocity(speed);
self.base_mut().move_and_slide();
}