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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:43:12