Files
demo-godot/move_utils.gd
2026-01-07 23:54:15 +08:00

49 lines
2.5 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends RefCounted
class_name MoveUtils
## 角色的质量,单位 kg
var weight = 60.0
## 角色前进的动力,同样先简化处理,单位
var power = 1000.0
## 冲销系数,当角色的指令方向当前实际方向不同时,有多少的力用来冲销原有的冲量以更快转向指令方向
## 冲销还是要仔细设计。仔细想想,假如当前力方向和指令方向完全相同时,肯定就不需要冲销
var offset_coefficient := 0.5
## 刹车系数,在没有明确指令时,用多少的动力来刹车
var brake = 0.7
## 一个最简单的阻尼系数[br]
## 阻力计算公式 速度² × 阻尼系数[br]
## 假设最高速度是慢跑 10km/h , 2.77m/s那么阻力需要在这个速度下维持和动力平衡。也就是...104.3
var damping = 10.0
func _init() -> void:
return
func get_horizontal_velocity( cmd_direction: Vector3, velocity: Vector3, delta: float ) -> Vector3:
var target_velocity
var velocity_direction: Vector3 = velocity.normalized()
# 当前阻力向量
var damping_vector: Vector3 = -velocity_direction * velocity.length_squared() * damping
if cmd_direction == Vector3.ZERO:
# 为什么这里要加上动力呢?我是这样思考的。
# 当用户停止输入指令的话,我认用户的意思是“现在不需要移动”。既然现在不需要移动,那当然应该把力用来刹车。对吧?
# 当然,此处可以考虑。哪怕你正常走路时,如果想要停下也不会全力急停的。理论上应该乘个小于 1 的系数。但是先这样试试效果。
var speed = ( damping_vector.length() + power * brake ) / weight * delta
# 目前产生的阻力速度大于当前速度。直接降为 0
if speed * speed > velocity.length_squared():
target_velocity = Vector3.ZERO
else:
var speed_velocity = damping_vector.normalized() * speed
target_velocity = velocity + speed_velocity
else:
# 这里来考虑转向问题。需要一个转向系数来来冲销当前的速度,让运动方向更快改变
var diff_coefficient = velocity.angle_to(cmd_direction) / PI * offset_coefficient
# 冲销力
var offset_vector = -velocity.normalized() * sqrt(power * power * diff_coefficient)
# 指令力
var cmd_vector = cmd_direction * sqrt(power * power * ( 1 - diff_coefficient ))
# 阻力 + 指令力合力
var result_vector: Vector3 = offset_vector + cmd_vector + damping_vector
# 合力下发生的速度变化
var speed_vector = result_vector.normalized() * result_vector.length() / weight * delta
target_velocity = velocity + speed_vector
return target_velocity