首先,鉴于这是 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)。这不会免费对同一帧中的变换进行多次更新,但会比其他方式更便宜。
我还提醒您,查看源代码并不能替代使用探查器。
你应该检查吗?也许……如果有很多孩子需要更新,那么额外的线路可能就足够便宜了。如有疑问:使用剖面仪进行测量。