Skip to content

Commit

Permalink
Improve TileMap performances by using quadrants only for rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
groud committed Sep 8, 2023
1 parent 31a7fd1 commit 8c1e282
Show file tree
Hide file tree
Showing 6 changed files with 1,362 additions and 1,099 deletions.
35 changes: 27 additions & 8 deletions doc/classes/TileMap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
</brief_description>
<description>
Node for 2D tile-based maps. Tilemaps use a [TileSet] which contain a list of tiles which are used to create grid-based maps. A TileMap may have several layers, layouting tiles on top of each other.
For performance reasons, all TileMap updates are batched at the end of a frame. Notably, this means that scene tiles from a [TileSetScenesCollectionSource] may be initialized after their parent.
To force an update earlier on, call [method update_internals].
</description>
<tutorials>
<link title="Using Tilemaps">$DOCS_URL/tutorials/2d/using_tilemaps.html</link>
Expand All @@ -25,7 +27,7 @@
Called with a TileData object about to be used internally by the TileMap, allowing its modification at runtime.
This method is only called if [method _use_tile_data_runtime_update] is implemented and returns [code]true[/code] for the given tile [param coords] and [param layer].
[b]Warning:[/b] The [param tile_data] object's sub-resources are the same as the one in the TileSet. Modifying them might impact the whole TileSet. Instead, make sure to duplicate those resources.
[b]Note:[/b] If the properties of [param tile_data] object should change over time, use [method force_update] to trigger a TileMap update.
[b]Note:[/b] If the properties of [param tile_data] object should change over time, use [method notify_runtime_tile_data_update] to notify the TileMap it needs an update.
</description>
</method>
<method name="_use_tile_data_runtime_update" qualifiers="virtual">
Expand All @@ -35,6 +37,7 @@
<description>
Should return [code]true[/code] if the tile at coordinates [param coords] on layer [param layer] requires a runtime update.
[b]Warning:[/b] Make sure this function only return [code]true[/code] when needed. Any tile processed at runtime without a need for it will imply a significant performance penalty.
[b]Note:[/b] If the result of this function should changed, use [method notify_runtime_tile_data_update] to notify the TileMap it needs an update.
</description>
</method>
<method name="add_layer">
Expand Down Expand Up @@ -73,13 +76,11 @@
Clears cells that do not exist in the tileset.
</description>
</method>
<method name="force_update">
<method name="force_update" is_deprecated="true">
<return type="void" />
<param index="0" name="layer" type="int" default="-1" />
<description>
Triggers an update of the TileMap. If [param layer] is provided and is positive, only updates the given layer.
[b]Note:[/b] The TileMap node updates automatically when one of its properties is modified. A manual update is only needed if runtime modifications (implemented in [method _tile_data_runtime_update]) need to be applied.
[b]Warning:[/b] Updating the TileMap is computationally expensive and may impact performance. Try to limit the number of updates and the tiles they impact (by placing frequently updated tiles in a dedicated layer for example).
[i]Deprecated.[/i] See [method notify_runtime_tile_data_update] and [method update_internals].
</description>
</method>
<method name="get_cell_alternative_tile" qualifiers="const">
Expand Down Expand Up @@ -301,6 +302,16 @@
Moves the layer at index [param layer] to the given position [param to_position] in the array.
</description>
</method>
<method name="notify_runtime_tile_data_update">
<return type="void" />
<param index="0" name="layer" type="int" default="-1" />
<description>
Notifies the TileMap node that calls to [method _use_tile_data_runtime_update] or [method _tile_data_runtime_update] will lead to different results. This will thus trigger a TileMap update.
If [param layer] is provided, only notifies changes for the given layer. Providing the [param layer] argument (when applicable) is usually preferred for performance reasons.
[b]Warning:[/b] Updating the TileMap is computationally expensive and may impact performance. Try to limit the number of calls to this function to avoid unnecessary update.
[b]Note:[/b] This does not trigger a direct update of the TileMap, the update will be done at the end of the frame as usual (unless you call [method update_internals]).
</description>
</method>
<method name="remove_layer">
<return type="void" />
<param index="0" name="layer" type="int" />
Expand Down Expand Up @@ -437,11 +448,16 @@
If [param layer] is negative, the layers are accessed from the last one.
</description>
</method>
<method name="update_internals">
<return type="void" />
<description>
Triggers a direct update of the TileMap. Usually, calling this function is not needed, as TileMap node updates automatically when one of its properties or cells is modified.
However, for performance reasons, those updates are batched and delayed to the end of the frame. Calling this function will force the TileMap to update right away instead.
[b]Warning:[/b] Updating the TileMap is computationally expensive and may impact performance. Try to limit the number of updates and how many tiles they impact.
</description>
</method>
</methods>
<members>
<member name="cell_quadrant_size" type="int" setter="set_quadrant_size" getter="get_quadrant_size" default="16">
The TileMap's quadrant size. Optimizes drawing by batching, using chunks of this size.
</member>
<member name="collision_animatable" type="bool" setter="set_collision_animatable" getter="is_collision_animatable" default="false">
If enabled, the TileMap will see its collisions synced to the physics tick and change its collision type from static to kinematic. This is required to create TileMap-based moving platform.
[b]Note:[/b] Enabling [member collision_animatable] may have a small performance impact, only do it if the TileMap is moving and has colliding tiles.
Expand All @@ -452,6 +468,9 @@
<member name="navigation_visibility_mode" type="int" setter="set_navigation_visibility_mode" getter="get_navigation_visibility_mode" enum="TileMap.VisibilityMode" default="0">
Show or hide the TileMap's navigation meshes. If set to [constant VISIBILITY_MODE_DEFAULT], this depends on the show navigation debug settings.
</member>
<member name="rendering_quadrant_size" type="int" setter="set_rendering_quadrant_size" getter="get_rendering_quadrant_size" default="16">
The TileMap's quadrant size. Optimizes drawing by batching, using chunks of this size.
</member>
<member name="tile_set" type="TileSet" setter="set_tileset" getter="get_tileset">
The assigned [TileSet].
</member>
Expand Down
7 changes: 7 additions & 0 deletions misc/extension_api_validation/4.1-stable.expected
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,10 @@ Validate extension JSON: API was removed: classes/GraphNode/signals/raise_reques
Validate extension JSON: API was removed: classes/GraphNode/signals/resize_request

Refactor GraphNode (splitup in GraphElement and GraphNode)
GH-81070
--------
Validate extension JSON: API was removed: classes/TileMap/methods/get_quadrant_size
Validate extension JSON: API was removed: classes/TileMap/methods/set_quadrant_size
Validate extension JSON: API was removed: classes/TileMap/properties/cell_quadrant_size

cell_quadrant_size/quadrant_size of the TileMap API was renamed to rendering_quadrant_size.
10 changes: 10 additions & 0 deletions scene/2d/tile_map.compat.inc
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,18 @@ Rect2i TileMap::_get_used_rect_bind_compat_78328() {
return get_used_rect();
}

void TileMap::_set_quadrant_size_compat_81070(int p_quadrant_size) {
set_rendering_quadrant_size(p_quadrant_size);
}

int TileMap::_get_quadrant_size_compat_81070() const {
return get_rendering_quadrant_size();
}

void TileMap::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("get_used_rect"), &TileMap::_get_used_rect_bind_compat_78328);
ClassDB::bind_compatibility_method(D_METHOD("set_quadrant_size", "quadrant_size"), &TileMap::_set_quadrant_size_compat_81070);
ClassDB::bind_compatibility_method(D_METHOD("get_quadrant_size"), &TileMap::_get_quadrant_size_compat_81070);
}

#endif
Loading

0 comments on commit 8c1e282

Please sign in to comment.