Godot 4.1中Camera3D环绕CharacterBody3D的定位控制问题
Godot 3D相机问题:旋转时焦点偏移+相机异常前移
问题描述
刚接触Godot 3D开发,想要实现如下场景:
- CharacterBody3D(下称焦点)始终处于屏幕中心
- Camera3D固定在焦点的上方后方位置
- 按Q/E键时,相机围绕焦点旋转,其余世界随之转动,焦点保持居中
但实际运行时出现两个问题:
- 按Q/E旋转时,焦点沿椭圆路径移动,无法保持屏幕中心
- 之前实现过居中旋转与WASD平移,但相机突然前移,导致焦点被截断一半,仅能看到焦点前方(屏幕上半部分)的行星
相关代码位于res://camera/CameraFocus.gd,修改后的关键代码片段如下:
func rotate_around_focus_character(delta): # 围绕焦点角色旋转相机 var theta = deg_to_rad(rotation_speed * delta) #var rotation_center = focus.global_transform.origin #+ Vector3(0, 10, 0) if Input.is_action_pressed("rotate_left"): global_transform.origin = focus.global_transform.origin global_transform.basis = camera_3d.global_transform.basis.rotated(Vector3(0, 1, 0), theta) if Input.is_action_pressed("rotate_right"): global_transform.origin = focus.global_transform.origin global_transform.basis = camera_3d.global_transform.basis.rotated(Vector3(0, 1, 0), -theta)
func track_focus_with_camera(delta): if focus: var camera_3d_pos = camera_3d.global_transform.origin print("camera_3d_pos = " + str(camera_3d_pos)) global_transform.origin = focus.global_transform.origin.lerp(camera_3d.position, 0.1)
问题根源与解决方案
1. 旋转逻辑错误
直接将相机原点绑定到焦点原点再旋转basis,会导致相机局部坐标系混乱,旋转路径偏离预期,出现椭圆偏移。正确做法是基于相机与焦点的偏移向量做旋转,再更新位置并让相机始终看向焦点。
修正后的旋转函数:
func rotate_around_focus_character(delta): var theta = deg_to_rad(rotation_speed * delta) # 计算相机相对于焦点的偏移向量 var offset = global_transform.origin - focus.global_transform.origin if Input.is_action_pressed("rotate_left"): # 绕焦点的Y轴旋转偏移向量 offset = offset.rotated(Vector3.UP, theta) if Input.is_action_pressed("rotate_right"): offset = offset.rotated(Vector3.UP, -theta) # 更新相机位置并保持看向焦点 global_transform.origin = focus.global_transform.origin + offset look_at(focus.global_transform.origin, Vector3.UP)
2. 跟踪逻辑反向
原track_focus_with_camera函数的插值方向搞反了,导致相机异常前移。应该让相机从当前位置向焦点的目标偏移位置平滑插值。
修正后的跟踪函数(假设相机需要固定在焦点上方后方Vector3(0,5,-10)的位置,可按需调整):
func track_focus_with_camera(delta): if focus: # 定义相机相对于焦点的固定偏移 var target_offset = Vector3(0, 5, -10) # 将偏移转换为全局坐标系下的目标位置 var target_pos = focus.global_transform.origin + focus.global_transform.basis * target_offset # 平滑插值到目标位置 global_transform.origin = global_transform.origin.lerp(target_pos, 0.1) # 始终看向焦点 look_at(focus.global_transform.origin, Vector3.UP)
额外提示
- 确保没有多个脚本同时修改相机的变换属性,避免逻辑冲突
- 调整
rotation_speed和插值系数(0.1)可以控制旋转速度和跟踪的平滑度
内容的提问来源于stack exchange,提问作者Ian McCurdy
相关产品推荐
相关产品推荐

