Godot中CharacterBody3D在地面时velocity.y持续增长问题排查
问题描述
- 实现了一个类似推箱子(Sokoban)的
CharacterBody3D盒子,每个垂直侧面配有Area3D碰撞体,玩家进入Area3D时通过tween实现盒子移动。 - 期望盒子不在地面时能下落,但
_physics_process代码存在异常:即使盒子处于地面,is_on_floor()始终返回false,导致velocity.y持续累加增长。 - 单个盒子时卡顿不明显,同时存在12个盒子时卡顿严重,注释
_physics_process函数后卡顿完全消失。 - 补充信息:盒子不会出现穿模问题,碰撞层设置正确,尝试将
velocity重置为Vector3(0,0,0)无法解决问题。
完整脚本
extends CharacterBody3D @export var move_distance: float = 4000 @export var move_duration: float = 4000 @onready var gravity = 30.0 @onready var vel = Vector3.ZERO @onready var block = $".\" @onready var s_tween @onready var n_tween @onready var e_tween @onready var w_tween @onready var south_bool:bool = true @onready var north_bool:bool = true @onready var east_bool:bool = true @onready var west_bool:bool = true @onready var south_nagative_z: bool = false @onready var north_positive_z: bool = false @onready var east_positive_x: bool = false @onready var west_nagative_x: bool = false @onready var south_tween_started: bool = false @onready var north_tween_started: bool = false @onready var east_tween_started: bool = false @onready var west_tween_started: bool = false @onready var pl_south_material = %PushLight_South.get_surface_override_material(0) @onready var pl_north_material = %PushLight_North.get_surface_override_material(0) @onready var pl_east_material = %PushLight_East.get_surface_override_material(0) @onready var pl_west_material = %PushLight_West.get_surface_override_material(0) func _ready() -> void: pl_south_material.emission_enabled = false pl_north_material.emission_enabled = false pl_east_material.emission_enabled = false pl_west_material.emission_enabled = false func _physics_process(delta: float) -> void: if not is_on_floor(): print("inside") velocity += get_gravity() * delta print(velocity) else: velocity = Vector3(0,0,0) move_and_slide() func _process(_delta: float) -> void: %"South_Negative-Z".monitorable = south_bool %"South_Negative-Z".monitoring = south_bool %"North_Positive-Z".monitorable = north_bool %"North_Positive-Z".monitoring = north_bool %"East_Positive-X".monitorable = east_bool %"East_Positive-X".monitoring = east_bool %"West_Negative-X".monitorable = west_bool %"West_Negative-X".monitoring = west_bool if GameManager.num_num_raycast_is_colliding == true and GameManager.push_raycast_is_coliding == true: south_bool = false north_bool = false east_bool = false west_bool = false elif GameManager.num_num_raycast_is_colliding != true and GameManager.push_raycast_is_coliding != true: south_bool = true north_bool = true east_bool = true west_bool = true #***************SOUTH*************** if south_nagative_z == true and south_bool == true: if GameManager.num_num_raycast_is_colliding == false: if south_tween_started == false: var current_z = block.position.z s_tween = get_tree().create_tween() s_tween.tween_property(block, "position:z", current_z + -move_distance, move_duration) south_tween_started = true if south_nagative_z == false: if s_tween != null: s_tween.kill() s_tween = null south_tween_started = false if south_bool == false: if s_tween != null: s_tween.kill() s_tween = null south_tween_started = false #***************NORTH*************** if north_positive_z == true and north_bool == true: if GameManager.num_num_raycast_is_colliding == false: if north_tween_started == false: var current_z = block.position.z n_tween = get_tree().create_tween() n_tween.tween_property(block, "position:z", current_z + move_distance, move_duration) north_tween_started = true if north_positive_z == false: if n_tween != null: n_tween.kill() n_tween = null north_tween_started = false if north_bool == false: if n_tween != null: n_tween.kill() n_tween = null north_tween_started = false #***************EAST*************** if east_positive_x == true and east_bool == true: if GameManager.num_num_raycast_is_colliding == false: if east_tween_started == false: var current_x = block.position.x e_tween = get_tree().create_tween() e_tween.tween_property(block, "position:x", current_x + -move_distance, move_duration) east_tween_started = true if east_positive_x == false: if e_tween != null: e_tween.kill() e_tween = null east_tween_started = false if east_bool == false: if e_tween != null: e_tween.kill() e_tween = null east_tween_started = false ##***************WEST*************** if west_nagative_x == true and west_bool == true: if GameManager.num_num_raycast_is_colliding == false: if west_tween_started == false: var current_x = block.position.x w_tween = get_tree().create_tween() w_tween.tween_property(block, "position:x", current_x + move_distance, move_duration) west_tween_started = true if west_nagative_x == false: if w_tween != null: w_tween.kill() west_tween_started = false if west_bool == false: if w_tween != null: w_tween.kill() w_tween = null west_tween_started = false func _on_south_negative_z_body_entered(body: Node3D) -> void: if body.is_in_group("player") and Input.is_action_pressed("move_up"): south_nagative_z = true pl_south_material.emission_enabled = true elif body.is_in_group("player") and !Input.is_action_pressed("move_up"): south_nagative_z = false elif !body.is_in_group("player") and !Input.is_action_pressed("move_up"): south_nagative_z = false func _on_south_negative_z_body_exited(_body: Node3D) -> void: south_nagative_z = false pl_south_material.emission_enabled = false func _on_north_positive_z_body_entered(body: Node3D) -> void: if body.is_in_group("player") and Input.is_action_pressed("move_up"): north_positive_z = true pl_north_material.emission_enabled = true elif body.is_in_group("player") and !Input.is_action_pressed("move_up"): north_positive_z = false elif !body.is_in_group("player") and !Input.is_action_pressed("move_up"): north_positive_z = false func _on_north_positive_z_body_exited(_body: Node3D) -> void: north_positive_z = false pl_north_material.emission_enabled = false func _on_east_positive_x_body_entered(body: Node3D) -> void: if body.is_in_group("player") and Input.is_action_pressed("move_up"): east_positive_x = true pl_east_material.emission_enabled = true elif body.is_in_group("player") and !Input.is_action_pressed("move_up"): east_positive_x = false elif !body.is_in_group("player") and !Input.is_action_pressed("move_up"): east_positive_x = false func _on_east_positive_x_body_exited(_body: Node3D) -> void: east_positive_x = false pl_east_material.emission_enabled = false func _on_west_negative_x_body_entered(body: Node3D) -> void: if body.is_in_group("player") and Input.is_action_pressed("move_up"): west_nagative_x = true pl_west_material.emission_enabled = true elif body.is_in_group("player") and !Input.is_action_pressed("move_up"): west_nagative_x = false elif !body.is_in_group("player") and !Input.is_action_pressed("move_up"): west_nagative_x = false func _on_west_negative_x_body_exited(_body: Node3D) -> void: west_nagative_x = false pl_west_material.emission_enabled = false
内容的提问来源于stack exchange,提问作者FatMunkey
相关产品推荐
相关产品推荐

