【问题标题】:Should the variable value be checked before assigning?在赋值之前是否应该检查变量值?
【发布时间】:2023-01-07 05:29:24
【问题描述】:

我知道这听起来像是一个愚蠢的问题,但我很好奇我是否应该在分配之前检查我的变量值?

例如,如果我根据方向 (Vector2) 翻转我的 skin(由精灵和光线投射组成的 Node2D):

func _process(delta):
    ...

    if(direction.x>0):
        skin.scale.x=1
    elif(direction.x<0):
        skin.scale.x=-1
  
   #OR


    if(direction.x>0):
        if(skin.scale.x!=1):
           skin.scale.x=1
    elif(direction.x<0):
        if(skin.scale.x!=-1):
           skin.scale.x=-1

每个_process都会改变皮肤比例从而消耗更多的CPU使用率
或者
如果值相同会被忽略吗?

【问题讨论】:

    标签: godot gdscript


    【解决方案1】:

    首先,鉴于这是 GDScript,所以行数将是一个性能因素。

    我们将看看 C++ 方面……


    但在此之前……请注意 GDScript 会对属性进行一些欺骗。

    当你说skin.scale时,Godot 将在skin 对象上调用get_scale,它返回一个Vector2。而Vector2 是一个值类型。 Vector2 不是对象具有的比例,而是副本,值的快照。因此,在几乎任何其他语言中,skin.scale.x=1 正在修改 Vector2,并且不会影响对象的比例。这意味着你应该这样做:

    skin.scale = Vector2(skin.scale.x + 1, skin.scale.y)
    

    或这个:

    var skin_scale = skin.scale
    skin_scale.x += 1
    skin.scale = skin_scale
    

    我敢打赌使用 C# 的人会觉得很熟悉。

    但您不需要在 GDScript 中这样做。 Godot 会打电话给set_scale,这是大多数人所期望的。这是一个特点!


    所以,你设置了scale,Godot 就会调用set_scale

    void Node2D::set_scale(const Size2 &p_scale) {
        if (_xform_dirty) {
            ((Node2D *)this)->_update_xform_values();
        }
        _scale = p_scale;
        // Avoid having 0 scale values, can lead to errors in physics and rendering.
        if (Math::is_zero_approx(_scale.x)) {
            _scale.x = CMP_EPSILON;
        }
        if (Math::is_zero_approx(_scale.y)) {
            _scale.y = CMP_EPSILON;
        }
        _update_transform();
        _change_notify("scale");
    }
    

    _change_notify 方法只在编辑器中做一些事情。它是用于撤消/重做等的 Godot 3.x 工具。

    set_scale 将调用 _update_transform

    void Node2D::_update_transform() {
        _mat.set_rotation_and_scale(angle, _scale);
        _mat.elements[2] = pos;
    
        VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), _mat);
    
        if (!is_inside_tree()) {
            return;
        }
    
        _notify_transform();
    }
    

    如您所见,这将更新Node2D (_mat) 的Transform2D。然后关闭VisualServer

    然后到_notify_transform。这就是传播场景树中变化的原因。如果您已使用 set_notify_transform 启用它,它也会调用 notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED)。它看起来像这样(这来自“canvas_item.h”):

        _FORCE_INLINE_ void _notify_transform() {
            if (!is_inside_tree()) {
                return;
            }
            _notify_transform(this);
            if (!block_transform_notify && notify_local_transform) {
                notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
            }
        }
    

    你可以看到它委托给另一个看起来像这样的_notify_transform(这来自“canvas_item.cpp”):

    void CanvasItem::_notify_transform(CanvasItem *p_node) {
        /* This check exists to avoid re-propagating the transform
         * notification down the tree on dirty nodes. It provides
         * optimization by avoiding redundancy (nodes are dirty, will get the
         * notification anyway).
         */
    
        if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid) {
            return; //nothing to do
        }
    
        p_node->global_invalid = true;
    
        if (p_node->notify_transform && !p_node->xform_change.in_list()) {
            if (!p_node->block_transform_notify) {
                if (p_node->is_inside_tree()) {
                    get_tree()->xform_change_list.add(&p_node->xform_change);
                }
            }
        }
    
        for (CanvasItem *ci : p_node->children_items) {
            if (ci->top_level) {
                continue;
            }
            _notify_transform(ci);
        }
    }
    

    所以不行。如果值相同,则不会检查忽略更改。

    然而,值得注意的是 Godot 使全局变换无效而不是立即计算它 (global_invalid)。这不会免费对同一帧中的变换进行多次更新,但会比其他方式更便宜。


    我还提醒您,查看源代码并不能替代使用探查器。

    你应该检查吗?也许……如果有很多孩子需要更新,那么额外的线路可能就足够便宜了。如有疑问:使用剖面仪进行测量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-08
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-25
      相关资源
      最近更新 更多