如何让播放器顺畅旋转
How to make player rotate smoothly
下面是我的整个播放器脚本(如果内容混乱请见谅),如果您能告诉我为什么旋转不起作用,那将非常有帮助。我希望播放器在按下某个键时能够平稳转动。非常感谢!
extends KinematicBody
var moveSpeed : float = 5.0
var jumpForce : float = 10.0
var gravity : float = 20
var vel : Vector3 = Vector3()
const _angular_speed:float = TAU
func _physics_process(delta):
vel.x = 0
vel.z = 0
var turn_input := Vector2(
Input.get_action_strength("move_left") - Input.get_action_strength("move_right"),
Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
)
var movement = Vector3()
var input_angle := turn_input.angle()
var _target_angle:float
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
if Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_left"):
movement[2] = 1
movement[0] = 1
elif Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_right"):
movement[2] = 1
movement[0] = -1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_left"):
movement[2] = -1
movement[0] = 1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_right"):
movement[2] = -1
movement[0] = -1
else:
if Input.is_action_pressed("move_forward"):
movement[2] = 1
if Input.is_action_pressed("move_backward"):
movement[2] = -1
if Input.is_action_pressed("move_left"):
movement[0] = 1
if Input.is_action_pressed("move_right"):
movement[0] = -1
movement = movement.normalized()
global_transform[3] += movement/7
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
vel = move_and_slide(vel, Vector3.UP)
编辑:此问题现已得到解答。
你在这里做一些奇怪的事情。
未使用input_angle
首先,只需将其复制到 Godot。我收到一条警告,指出未使用 input_angle
。快速查看后,下一个 _target_angle
从未分配:
var input_angle := turn_input.angle()
var _target_angle:float
这很容易解决。只保留 _target_angle
:
var _target_angle := turn_input.angle()
清理
其次,不是真正的问题,但是movement
是这样的:
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
这样,您将看到所有这些代码:
if Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_left"):
movement[2] = 1
movement[0] = 1
elif Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_right"):
movement[2] = 1
movement[0] = -1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_left"):
movement[2] = -1
movement[0] = 1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_right"):
movement[2] = -1
movement[0] = -1
else:
if Input.is_action_pressed("move_forward"):
movement[2] = 1
if Input.is_action_pressed("move_backward"):
movement[2] = -1
if Input.is_action_pressed("move_left"):
movement[0] = 1
if Input.is_action_pressed("move_right"):
movement[0] = -1
movement = movement.normalized()
删除它。走了。只保留上面的一个衬垫。它应该做同样的事情。 它应该做同样的事情,具有奇怪的行为等等,但现在更容易看到代码。
代码现在看起来像这样:
extends KinematicBody
var moveSpeed : float = 5.0
var jumpForce : float = 10.0
var gravity : float = 20
var vel : Vector3 = Vector3()
const _angular_speed:float = TAU
func _physics_process(delta):
vel.x = 0
vel.z = 0
var turn_input := Vector2(
Input.get_action_strength("move_left") - Input.get_action_strength("move_right"),
Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
)
var _target_angle := turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
global_transform[3] += movement/7
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
vel = move_and_slide(vel, Vector3.UP)
什么movement
?
看看这一行:
global_transform[3] += movement/7
什么鬼,密歇根?
那一行相当于:
global_transform.origin += movement * 1/7
注意这是运动,它没有使用 delta
。我会回到那个。
旋转重置
我们需要将_target_angle
提升为一个字段,只有在有输入的时候才设置。 我也进一步清理了字段。代码现在看起来像这样:
extends KinematicBody
const _angular_speed:float = TAU
var moveSpeed := 5.0
var jumpForce := 10.0
var gravity := 20
var vel := Vector3()
var _target_angle:float
func _physics_process(delta):
vel.x = 0
vel.z = 0
var turn_input := Vector2(
Input.get_action_strength("move_left") - Input.get_action_strength("move_right"),
Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
)
if turn_input.length_squared() > 0:
_target_angle = turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
global_transform[3] += movement/7
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
vel = move_and_slide(vel, Vector3.UP)
如你所见,我在开始时声明了target_angle
,所以它不是局部变量。这样,它就保持了它的价值。我也这样做:
if turn_input.length_squared() > 0:
_target_angle = turn_input.angle()
这样,只有当turn_input
不为空时,才设置_target_angle
。
方向错误
它似乎在向相反的方向移动。鉴于我遵守了您的订单,我不确定这是不是故意的。
无论如何,修复它就是翻转输入的问题:
var turn_input := Vector2(
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward")
)
这是有道理的,因为 x
向右增长,并且 - 实际上 - Godot 中的前向是负数 z
(这里存储在 y
中)。
方向错误
角色的旋转似乎偏离了四分之一圈。这解决了它:
_target_angle = 0.75 * TAU - turn_input.angle()
实际上这是有道理的,因为 turn_input.angle()
是从 x
轴测量的,但是 0 旋转是向下看 z
轴。我确实忽略了这一点。
再次运动
不要更改转换的 origin
(通过狡猾的方式,不少于此),而是使用您已经在使用的 move_and_slide
。因此,我们不会 movement
,而是写入 vel
。为了简化操作,我决定对 turn_input
进行归一化,以便我们可以直接使用它来计算 vel
。在此期间,让我们使用您拥有的 moveSpeed
字段。 顺便说一句,它很小。
这是最终代码:
extends KinematicBody
const _angular_speed:float = TAU
var moveSpeed := 500.0
var jumpForce := 10.0
var gravity := 20
var vel := Vector3()
var _target_angle:float
func _physics_process(delta:float) -> void:
# Input
var turn_input := Vector2(
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward")
).normalized()
# Rotation
if turn_input.length_squared() > 0:
_target_angle = 0.75 * TAU - turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
# Velocity
vel.x = turn_input.x * moveSpeed * delta
vel.z = turn_input.y * moveSpeed * delta
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
# Motion
vel = move_and_slide(vel, Vector3.UP)
下面是我的整个播放器脚本(如果内容混乱请见谅),如果您能告诉我为什么旋转不起作用,那将非常有帮助。我希望播放器在按下某个键时能够平稳转动。非常感谢!
extends KinematicBody
var moveSpeed : float = 5.0
var jumpForce : float = 10.0
var gravity : float = 20
var vel : Vector3 = Vector3()
const _angular_speed:float = TAU
func _physics_process(delta):
vel.x = 0
vel.z = 0
var turn_input := Vector2(
Input.get_action_strength("move_left") - Input.get_action_strength("move_right"),
Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
)
var movement = Vector3()
var input_angle := turn_input.angle()
var _target_angle:float
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
if Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_left"):
movement[2] = 1
movement[0] = 1
elif Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_right"):
movement[2] = 1
movement[0] = -1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_left"):
movement[2] = -1
movement[0] = 1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_right"):
movement[2] = -1
movement[0] = -1
else:
if Input.is_action_pressed("move_forward"):
movement[2] = 1
if Input.is_action_pressed("move_backward"):
movement[2] = -1
if Input.is_action_pressed("move_left"):
movement[0] = 1
if Input.is_action_pressed("move_right"):
movement[0] = -1
movement = movement.normalized()
global_transform[3] += movement/7
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
vel = move_and_slide(vel, Vector3.UP)
编辑:此问题现已得到解答。
你在这里做一些奇怪的事情。
未使用input_angle
首先,只需将其复制到 Godot。我收到一条警告,指出未使用 input_angle
。快速查看后,下一个 _target_angle
从未分配:
var input_angle := turn_input.angle()
var _target_angle:float
这很容易解决。只保留 _target_angle
:
var _target_angle := turn_input.angle()
清理
其次,不是真正的问题,但是movement
是这样的:
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
这样,您将看到所有这些代码:
if Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_left"):
movement[2] = 1
movement[0] = 1
elif Input.is_action_pressed("move_forward") and Input.is_action_pressed("move_right"):
movement[2] = 1
movement[0] = -1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_left"):
movement[2] = -1
movement[0] = 1
elif Input.is_action_pressed("move_backward") and Input.is_action_pressed("move_right"):
movement[2] = -1
movement[0] = -1
else:
if Input.is_action_pressed("move_forward"):
movement[2] = 1
if Input.is_action_pressed("move_backward"):
movement[2] = -1
if Input.is_action_pressed("move_left"):
movement[0] = 1
if Input.is_action_pressed("move_right"):
movement[0] = -1
movement = movement.normalized()
删除它。走了。只保留上面的一个衬垫。它应该做同样的事情。 它应该做同样的事情,具有奇怪的行为等等,但现在更容易看到代码。
代码现在看起来像这样:
extends KinematicBody
var moveSpeed : float = 5.0
var jumpForce : float = 10.0
var gravity : float = 20
var vel : Vector3 = Vector3()
const _angular_speed:float = TAU
func _physics_process(delta):
vel.x = 0
vel.z = 0
var turn_input := Vector2(
Input.get_action_strength("move_left") - Input.get_action_strength("move_right"),
Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
)
var _target_angle := turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
global_transform[3] += movement/7
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
vel = move_and_slide(vel, Vector3.UP)
什么movement
?
看看这一行:
global_transform[3] += movement/7
什么鬼,密歇根?
那一行相当于:
global_transform.origin += movement * 1/7
注意这是运动,它没有使用 delta
。我会回到那个。
旋转重置
我们需要将_target_angle
提升为一个字段,只有在有输入的时候才设置。 我也进一步清理了字段。代码现在看起来像这样:
extends KinematicBody
const _angular_speed:float = TAU
var moveSpeed := 5.0
var jumpForce := 10.0
var gravity := 20
var vel := Vector3()
var _target_angle:float
func _physics_process(delta):
vel.x = 0
vel.z = 0
var turn_input := Vector2(
Input.get_action_strength("move_left") - Input.get_action_strength("move_right"),
Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
)
if turn_input.length_squared() > 0:
_target_angle = turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
var movement := Vector3(turn_input.x, 0.0, turn_input.y).normalized()
global_transform[3] += movement/7
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
vel = move_and_slide(vel, Vector3.UP)
如你所见,我在开始时声明了target_angle
,所以它不是局部变量。这样,它就保持了它的价值。我也这样做:
if turn_input.length_squared() > 0:
_target_angle = turn_input.angle()
这样,只有当turn_input
不为空时,才设置_target_angle
。
方向错误
它似乎在向相反的方向移动。鉴于我遵守了您的订单,我不确定这是不是故意的。
无论如何,修复它就是翻转输入的问题:
var turn_input := Vector2(
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward")
)
这是有道理的,因为 x
向右增长,并且 - 实际上 - Godot 中的前向是负数 z
(这里存储在 y
中)。
方向错误
角色的旋转似乎偏离了四分之一圈。这解决了它:
_target_angle = 0.75 * TAU - turn_input.angle()
实际上这是有道理的,因为 turn_input.angle()
是从 x
轴测量的,但是 0 旋转是向下看 z
轴。我确实忽略了这一点。
再次运动
不要更改转换的 origin
(通过狡猾的方式,不少于此),而是使用您已经在使用的 move_and_slide
。因此,我们不会 movement
,而是写入 vel
。为了简化操作,我决定对 turn_input
进行归一化,以便我们可以直接使用它来计算 vel
。在此期间,让我们使用您拥有的 moveSpeed
字段。 顺便说一句,它很小。
这是最终代码:
extends KinematicBody
const _angular_speed:float = TAU
var moveSpeed := 500.0
var jumpForce := 10.0
var gravity := 20
var vel := Vector3()
var _target_angle:float
func _physics_process(delta:float) -> void:
# Input
var turn_input := Vector2(
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward")
).normalized()
# Rotation
if turn_input.length_squared() > 0:
_target_angle = 0.75 * TAU - turn_input.angle()
var angle_diff := wrapf(_target_angle - rotation.y, -PI, PI)
rotation.y += clamp(delta * _angular_speed, 0, abs(angle_diff)) * sign(angle_diff)
# Velocity
vel.x = turn_input.x * moveSpeed * delta
vel.z = turn_input.y * moveSpeed * delta
vel.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
vel.y = jumpForce
# Motion
vel = move_and_slide(vel, Vector3.UP)