You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot 4中如何让玩家移动时朝向相机pivot_y的Y轴方向?

解决方案

要实现移动时玩家朝向相机水平旋转(pivot_y的Y轴方向),可以通过以下调整解决:

核心修改点

  • 移动方向基于pivot_y的水平朝向计算,而非玩家自身朝向
  • 移动时让玩家平滑朝向当前移动的水平方向,避免look_at导致的地面朝向问题
  • 修正移动状态下的相机旋转逻辑,保持pivot_y作为相机旋转的核心节点

修改后的完整脚本

extends CharacterBody3D

@onready var pivot_y = $CamOriginY
@onready var pivot_x = $CamOriginY/CamOriginX
@onready var springarm = $CamOriginY/CamOriginX/SpringArm3D

const SPEED = 5.0
const JUMP_VELOCITY = 4.5
const ROTATION_SPEED = 8.0  # 新增:玩家转向速度

@export var is_moving = false
@export var forward_angle = ""
@export var facing_dir = ""
@export var sens: float = 0.5
@export var zoom_speed: float = 14.0
@export var spring_length_default: float = 1.0
@export var spring_length_min: float = 0.0
@export var spring_length_max: float = 2.0
@export var spring_length_target = spring_length_default
@export var spring_length_current = spring_length_default

var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")

func _ready():
    Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _input(event):
    if event is InputEventMouseMotion:
        # 相机X轴旋转(上下)始终由pivot_x处理
        pivot_x.rotate_x(deg_to_rad(-event.relative.y * sens))
        pivot_x.rotation.x = clamp(pivot_x.rotation.x, deg_to_rad(-30), deg_to_rad(45))
        
        if is_moving:
            # 移动时:玩家跟随相机水平旋转,pivot_y保持和玩家Y轴旋转同步
            rotate_y(deg_to_rad(-event.relative.x * sens))
            pivot_y.rotation.y = rotation.y
        else:
            # 静止时:仅旋转pivot_y,玩家朝向不变
            pivot_y.rotate_y(deg_to_rad(-event.relative.x * sens))
            
    if event.is_action_pressed("cam_zoom_in"):
        if spring_length_current > spring_length_min:
            spring_length_target = spring_length_current - 0.4
        else:
            print("At minimum value")
    elif event.is_action_pressed("cam_zoom_out"):
        if spring_length_current < spring_length_max:
            spring_length_target = spring_length_current + 0.4
        else:
            print("At maximum value")

    # 方向标记若未使用可考虑移除
    if event.is_action_pressed("left"):
        facing_dir = "left"
    elif event.is_action_pressed("right"):
        facing_dir = "right"
    elif event.is_action_pressed("up"):
        print("hello")
    elif event.is_action_pressed("down"):
        facing_dir = "down"

func _physics_process(delta):
    is_moving = false
    
    # 重力与跳跃处理
    if not is_on_floor():
        velocity.y -= gravity * delta
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = JUMP_VELOCITY
    if Input.is_action_just_pressed("quit"):
        get_tree().quit()

    # 相机变焦处理
    spring_length_current = lerp(spring_length_current, float(spring_length_target), delta * zoom_speed)
    springarm.set_length(spring_length_current)

    # 移动方向计算:基于pivot_y的水平朝向
    var input_dir = Input.get_vector("left", "right", "up", "down")
    if input_dir.length_squared() > 0:
        is_moving = true
        # 获取pivot_y的水平前向向量(忽略Y轴)
        var cam_forward = pivot_y.transform.basis.z
        cam_forward.y = 0
        cam_forward = cam_forward.normalized()
        # 获取pivot_y的水平右向向量
        var cam_right = pivot_y.transform.basis.x
        cam_right.y = 0
        cam_right = cam_right.normalized()
        
        # 计算最终移动方向
        var direction = cam_right * input_dir.x + cam_forward * input_dir.y
        direction = direction.normalized()
        
        # 设置移动速度
        velocity.x = direction.x * SPEED
        velocity.z = direction.z * SPEED
        
        # 玩家平滑朝向移动方向(仅水平旋转)
        if direction.length_squared() > 0:
            var target_rotation = atan2(direction.x, direction.z)
            rotation.y = lerp(rotation.y, target_rotation, delta * ROTATION_SPEED)
            # 同步pivot_y的Y轴旋转,保持相机和玩家朝向一致
            pivot_y.rotation.y = rotation.y
    else:
        # 减速停止
        velocity.x = move_toward(velocity.x, 0, SPEED)
        velocity.z = move_toward(velocity.z, 0, SPEED)

    move_and_slide()

关键逻辑说明

  1. 相机旋转同步:移动时玩家旋转后,立刻同步pivot_y.rotation.y = rotation.y,确保相机水平方向和玩家朝向始终一致;静止时仅旋转pivot_y,玩家朝向不变。
  2. 移动方向计算:通过pivot_y.transform.basis获取相机的水平前向/右向向量,以此计算玩家的移动方向,确保移动方向跟随相机视角。
  3. 平滑转向:用lerp实现玩家朝向的平滑过渡,避免生硬旋转,ROTATION_SPEED可根据手感调整。
  4. 避免地面朝向:计算方向时将向量的Y轴设为0,只保留水平分量,解决look_at导致的朝向地面问题。

内容的提问来源于stack exchange,提问作者plinkmaster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 01:29:52