我知道这听起来像是一个愚蠢的问题,但我很好奇我应该在分配之前检查我的变量值吗?
例如,如果我根据方向(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 使用率
OR
如果值相同,是否会被忽略?
首先,鉴于这是GDScript,所以行数将是一个性能因素。
我们将看看C++面...
<小时 />但在此之前...请注意,GDScript 对属性做了一些欺骗。
当你说skin.scale
戈多会在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中这样做。戈多会叫set_scale
,这是大多数人所期望的。这是一个功能!
所以,你设置scale
,戈多会打电话给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
仅在编辑器中执行某些操作。它是用于撤消/重做 et.al 的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
的Transform2D
(_mat
)。然后就去VisualServer
了.
然后_notify_transform
.这就是在场景树中传播更改的原因。如果您启用了它,这也是调用notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED)
set_notify_transform
.它看起来像这样(这是来自"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);
}
}
所以,没有。如果值相同,则不会进行检查以忽略更改。
然而,值得注意的是,戈多使全局变换无效,而不是立即计算它(global_invalid
)。这不会使同一帧中的转换的多次更新免费,但它使它们比其他方式更便宜。
我还提醒您,查看源代码不能替代使用探查器。
你应该检查吗?也许。。。如果有很多孩子需要更新,额外的线路可能足够便宜。如有疑问:使用探查器进行测量。