切换玩家时空中角色冻结,如何使其受物理影响下落?
问题:切换玩家后空中角色冻结,如何让其正常下落?
当原操控角色处于空中时进行玩家切换,该角色会冻结在当前位置。需要实现切换玩家后,原操控角色能够遵循物理规律下落至地面。
角色控制代码
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
相关产品推荐
相关产品推荐

