如何阻止 Sprite2D 对象在 Godot 中重绘?

问题描述 投票:0回答:1

我正在制作一款 2D 回合制游戏。当玩家动作发生时,各种 Node2D 对象会移动。

但是当他们移动时,他们会进行基于物理的检查。因为我希望前一个节点所做的移动影响后一个节点所做的移动,所以我有这样的东西:

 for individual in individuals:
  # We need to wait for the move to take effect so that the next
  # collision calculations take it into account.
  await get_tree().physics_frame
  individual.do_thing_using_area2d()

这可以确保发生物理更新,以便下一次物理检查有效。 (例如,如果一个人刚刚移动到即将移动的人前面,就会发生碰撞。)

这样做的问题是 Sprite2D 附加到正在移动的节点上。因此它们会在单独的帧中重新绘制并导致闪烁。

为了使所有精灵在一帧中更新,我这样做了:

    # Stop _process and draw calls, but keep physics going.
    get_tree().paused = true
    PhysicsServer2D.set_active(true)

然后,在所有个人都移动并更新物理对象后,我取消暂停:

    await get_tree().create_timer(0.1).timeout
    # Unpause to get _process and _draw going again.
    get_tree().paused = false

这确实有效,但感觉有点太多了,而且可能会产生后果。有没有更干净、更传统的方法来批量Sprite2D更新?

gdscript flicker godot4
1个回答
0
投票

我能想到的最接近禁用a

Node
重绘的方法是禁用a
Viewport
的自动重绘。

所以我不会回答这个问题...

相反,这就是我的想法:您可以将

top_level
设置为
true
上的
Node2D
,这样它就不会随其父级移动(同时仍处于场景树中的位置),然后您必须移动它...

例如,您可以给它一个类似这样的脚本:

func _physics_process(_delta: float) -> void:
    var parent := get_parent() as Node2D
    if is_instance_valid(parent):
        global_transform = parent.global_transform

或者像这样保存几个周期:

extends Node2D


var parent_node_2d:Node2D


func _ready() -> void:
    top_level = true
    parent_node_2d = get_parent() as Node2D
    set_physics_process(is_instance_valid(parent_node_2d))


func _exit_tree() -> void:
    parent_node_2d = null
    request_ready()


func _physics_process(_delta: float) -> void:
    global_transform = parent_node_2d.global_transform

这里我使用

set_physics_process
来根据父级启用或禁用
_physics_process
。让我们通过配置警告来加强它:

@tool
extends Node2D


var parent_node_2d:Node2D


func _ready() -> void:
    top_level = true
    parent_node_2d = get_parent() as Node2D
    set_physics_process(is_instance_valid(parent_node_2d))


func _exit_tree() -> void:
    parent_node_2d = null
    request_ready()


func _physics_process(_delta: float) -> void:
    global_transform = parent_node_2d.global_transform


func _get_configuration_warnings() -> PackedStringArray:
    if not is_instance_valid(parent_node_2d):
        return ["Must be a child of a Node2D"]

    return []

或者您可以使用

_process
,这就是您开始编写自己的物理插值的方式。

@tool
extends Node2D


var parent_node_2d:Node2D


func _ready() -> void:
    top_level = true
    parent_node_2d = get_parent() as Node2D
    set_process(is_instance_valid(parent_node_2d))


func _exit_tree() -> void:
    parent_node_2d = null
    request_ready()


func _process(delta: float) -> void:
    var final_transform := parent_node_2d.global_transform
    var factor := get_approach_factor(1.0 / Engine.physics_ticks_per_second, delta)
    global_transform = global_transform.interpolate_with(final_transform, factor)


func _get_configuration_warnings() -> PackedStringArray:
    if not is_instance_valid(parent_node_2d):
        return ["Must be a child of a Node2D"]

    return []


func get_approach_factor(total_time:float, delta_time:float) -> float:
     # Constants
    const EPSILON := 0.00001
    const SCALE := 1000.0

    # When the total_time is not finite, the approach factor is zero
    if not is_finite(total_time):
        return 0.0

    # When the total_time is approximately zero, the approach factor is one
    if total_time < EPSILON / SCALE:
        return 1.0

    # Compute the approach factor
    var base := pow(EPSILON, 1.0 / (total_time * SCALE))
    var approach_factor := 1.0 - pow(base, delta_time * SCALE)
    return approach_factor
© www.soinside.com 2019 - 2024. All rights reserved.