多轴旋转异常:复现Hadamard门时仅X轴旋转生效
问题
我正在尝试复现Hadamard门的工作机制,系统由球体加附着的圆柱体组成,希望先绕X轴旋转90度,再绕Z轴旋转180度。但点击圆柱体时仅执行了X轴旋转,请问主Node3D的脚本需修改哪些地方?
初始配置:
当前脚本:
extends Node3D @onready var click_area: Area3D = $State/ClickArea @onready var state_node: Node3D = $State var tween: Tween const ROTATION_AROUND_X := 90.0 #const ROTATION_AROUND_Y := 0.0 const ROTATION_AROUND_Z := 180.0 func _ready(): click_area.input_event.connect(_on_click_area_input_event) func _on_click_area_input_event(_camera: Camera3D, event: InputEvent, _pos: Vector3, _normal: Vector3, _shape_idx: int) -> void: if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: _play_hadamard_animation() func _play_hadamard_animation(): # Kill any existing tween to ensure the animation starts fresh if tween and tween.is_valid(): tween.kill() # Create the new tween tween = get_tree().create_tween() tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) var start_rotation := state_node.rotation_degrees tween.tween_property(state_node, "rotation_degrees", start_rotation + Vector3(ROTATION_AROUND_X, 0.0, ROTATION_AROUND_Z), 1.2)
解决方案
问题出在当前代码是同时对X和Z轴应用旋转,而非按顺序执行两个旋转步骤。要实现先绕X转90度、再绕Z转180度的效果,需做以下修改:
- 拆分动画阶段:将两个旋转拆分为Tween的连续步骤,而非一次性设置最终旋转向量。GDScript的Tween会按调用顺序依次执行
tween_property,无需额外链式调用。 - 分步计算目标值:第一步目标为当前旋转加X轴90度,第二步目标为第一步完成后的旋转加Z轴180度。
修改后的完整脚本:
extends Node3D @onready var click_area: Area3D = $State/ClickArea @onready var state_node: Node3D = $State var tween: Tween const ROTATION_AROUND_X := 90.0 const ROTATION_AROUND_Z := 180.0 func _ready(): click_area.input_event.connect(_on_click_area_input_event) func _on_click_area_input_event(_camera: Camera3D, event: InputEvent, _pos: Vector3, _normal: Vector3, _shape_idx: int) -> void: if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: _play_hadamard_animation() func _play_hadamard_animation(): # 终止现有动画,确保新动画从头开始 if tween and tween.is_valid(): tween.kill() tween = get_tree().create_tween() tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) # 第一步:绕X轴旋转90度 var x_rotate_target = state_node.rotation_degrees + Vector3(ROTATION_AROUND_X, 0.0, 0.0) tween.tween_property(state_node, "rotation_degrees", x_rotate_target, 0.6) # 第二步:绕Z轴旋转180度(自动衔接上一步完成后执行) var z_rotate_target = x_rotate_target + Vector3(0.0, 0.0, ROTATION_AROUND_Z) tween.tween_property(state_node, "rotation_degrees", z_rotate_target, 0.6)
额外优化方案:
如果需要确保旋转基于节点本地坐标系(避免欧拉角可能的万向锁问题),可以改用tween_method调用节点的旋转方法:
# 替代tween_property的写法,直接基于本地轴旋转 tween.tween_method(func(amount): state_node.rotate_x(deg_to_rad(amount)), 0, ROTATION_AROUND_X, 0.6) tween.tween_method(func(amount): state_node.rotate_z(deg_to_rad(amount)), 0, ROTATION_AROUND_Z, 0.6)
内容的提问来源于stack exchange,提问作者albusdemens
相关产品推荐
相关产品推荐

