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

切换玩家时空中角色冻结,如何使其受物理影响下落?

问题:切换玩家后空中角色冻结,如何让其正常下落?

当原操控角色处于空中时进行玩家切换,该角色会冻结在当前位置。需要实现切换玩家后,原操控角色能够遵循物理规律下落至地面。

角色控制代码

extends CharacterBody3D
@onready var camera_mount = $camera_mount
@onready var animation_player = $visuals/mixamo_base/AnimationPlayer
@onready var visuals = $visuals
@onready var camera_3d = $camera_mount/Camera3D

@export var is_current:bool = true
@export var is_main = true
@export var SPEED = 5.0
@export var JUMP_VELOCITY = 4.5
@export var SENSIVITY = 0.05
var walk_speed = 3.0
var run_speed = 5.0
var is_running = false
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")

func _ready() -> void:
    if is_main:
        Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _input(event):
    if is_main:
        if event is InputEventMouseMotion:
            rotate_y(deg_to_rad(-event.relative.x*SENSIVITY))
            visuals.rotate_y(deg_to_rad(event.relative.x*SENSIVITY))
            camera_mount.rotate_x(deg_to_rad(-event.relative.y*SENSIVITY))
            

    
func _physics_process(delta):
    if is_main:
        camera_3d.current = is_current

        if not is_on_floor():
            velocity.y -= gravity * delta
        if Input.is_action_pressed("run"):
            SPEED = run_speed
            is_running = true
        else:
            is_running = false
            SPEED = walk_speed
            

        if Input.is_action_just_pressed("ui_accept") and is_on_floor():
            velocity.y = JUMP_VELOCITY
            
        if Input.is_action_just_pressed("ui_cancel"):
            Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)


        var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
        
        var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
        if direction:
            if animation_player.current_animation != "walking" && is_running == false:
                animation_player.play("walking")
                
            if animation_player.current_animation != "running" && is_running:
                animation_player.play("running")
            
                
            visuals.look_at(position+direction)
                
            velocity.x = direction.x * SPEED
            velocity.z = direction.z * SPEED
        else:
            if animation_player.current_animation != "idle":
                animation_player.play("idle")
                
            velocity.x = move_toward(velocity.x, 0, SPEED)
            velocity.z = move_toward(velocity.z, 0, SPEED)
            
        camera_mount.rotation.x = clamp(camera_mount.rotation.x, 
            deg_to_rad(-90), 
            deg_to_rad(70)
        )

        move_and_slide()

玩家切换脚本

extends Node3D

@onready var player_1 = $"../Player1"
@onready var player_2 = $"../Player2"

func _physics_process(_delta):
    if Input.is_action_just_pressed("switch_player"):
        if player_1.is_main:
            player_1.is_main = false
            player_2.is_main = true
            player_2.is_current = true
            player_1.animation_player.play("idle")
        else:
            player_1.is_main = true
            player_2.is_main = false
            player_1.is_current = true
            player_2.animation_player.play("idle")

解决方案

问题根源

角色控制代码中,_physics_process内的所有物理逻辑(重力应用、move_and_slide执行)都被包裹在if is_main:判断中。当切换玩家后,原角色的is_main变为false,这些物理逻辑不再执行,导致角色冻结在空中。

修改步骤

1. 调整角色控制代码的物理逻辑

将重力应用和move_and_slide移出if is_main:判断,让所有角色(无论是否为主角色)都能处理物理下落和移动。修改后的_physics_process函数如下:

func _physics_process(delta):
    # 所有角色都执行物理下落逻辑
    if not is_on_floor():
        velocity.y -= gravity * delta
    
    if is_main:
        camera_3d.current = is_current

        if Input.is_action_pressed("run"):
            SPEED = run_speed
            is_running = true
        else:
            is_running = false
            SPEED = walk_speed

        if Input.is_action_just_pressed("ui_accept") and is_on_floor():
            velocity.y = JUMP_VELOCITY
            
        if Input.is_action_just_pressed("ui_cancel"):
            Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)

        var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
        
        var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
        if direction:
            if animation_player.current_animation != "walking" && is_running == false:
                animation_player.play("walking")
                
            if animation_player.current_animation != "running" && is_running:
                animation_player.play("running")
            
            visuals.look_at(position+direction)
                
            velocity.x = direction.x * SPEED
            velocity.z = direction.z * SPEED
        else:
            if animation_player.current_animation != "idle":
                animation_player.play("idle")
                
            velocity.x = move_toward(velocity.x, 0, SPEED)
            velocity.z = move_toward(velocity.z, 0, SPEED)
            
        camera_mount.rotation.x = clamp(camera_mount.rotation.x, 
            deg_to_rad(-90), 
            deg_to_rad(70)
        )
    
    # 所有角色都执行移动更新
    move_and_slide()

2. 优化切换脚本的动画逻辑(可选)

切换玩家时,根据原角色是否在地面,播放对应的动画(如果有下落动画的话),让表现更自然:

extends Node3D

@onready var player_1 = $"../Player1"
@onready var player_2 = $"../Player2"

func _physics_process(_delta):
    if Input.is_action_just_pressed("switch_player"):
        if player_1.is_main:
            player_1.is_main = false
            player_2.is_main = true
            player_2.is_current = true
            # 空中角色播放下落动画,地面角色播放idle
            if not player_1.is_on_floor():
                player_1.animation_player.play("falling")
            else:
                player_1.animation_player.play("idle")
        else:
            player_1.is_main = true
            player_2.is_main = false
            player_1.is_current = true
            if not player_2.is_on_floor():
                player_2.animation_player.play("falling")
            else:
                player_2.animation_player.play("idle")

修改完成后,切换玩家时,空中的原角色会继续受到重力影响,自然下落至地面,同时保持正确的动画状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:17:34