Pool d'objets
Deux fontaines émettant au même rythme, l'une allouant chaque particule et l'autre les reprenant d'un pool. Ce sont les compteurs qui argumentent.
L'éditeur ci-dessus fait tourner ce projet. Changez une ligne et il se recharge.
Classes Godot utilisées
Node.queue_freePolygon2DPerformance
Le code
scripts/main.gd
extends Node
const RATE: int = 2
const LIFE: float = 0.6
const DOT: float = 13.0
const GRAVITY: float = 1500.0
const ORIGIN_Y: float = 650.0
# { origin, tint, pooled, live: Array, idle: Array, created, recycled, released, stats: Dictionary }
var lanes: Array = []
var node_count: Label
func _ready() -> void:
_add_background()
var row: HBoxContainer = _root()
lanes.append(_lane(row, 'new plus queue_free', Color('#fc7f7f'), 320.0, false))
lanes.append(_lane(row, 'take from a pool', Color('#8eef97'), 960.0, true))
print('both fountains spawn at the same rate, only the right one reuses what it already made')
func _process(delta: float) -> void:
for lane in lanes:
_spawn(lane)
_advance(lane, delta)
_report(lane)
node_count.text = 'nodes alive in the whole scene: %d' % Performance.get_monitor(Performance.OBJECT_NODE_COUNT)
func _spawn(lane: Dictionary) -> void:
for i in RATE:
var dot: Polygon2D = null
if lane.pooled and not lane.idle.is_empty():
dot = lane.idle.pop_back()
dot.visible = true
lane.recycled += 1
else:
dot = _make_dot(lane.tint)
add_child(dot)
lane.created += 1
dot.position = Vector2(lane.origin, ORIGIN_Y)
lane.live.append({node = dot, velocity = Vector2(randf_range(-260, 260), randf_range(-1000, -750)), life = LIFE})
func _advance(lane: Dictionary, delta: float) -> void:
for i in range(lane.live.size() - 1, -1, -1):
var dot: Dictionary = lane.live[i]
var velocity: Vector2 = dot.velocity
velocity.y += GRAVITY * delta
dot.velocity = velocity
dot.node.position += velocity * delta
dot.life -= delta
if dot.life > 0.0:
continue
lane.live.remove_at(i)
lane.released += 1
if lane.pooled:
dot.node.visible = false
lane.idle.append(dot.node)
else:
dot.node.queue_free()
func _report(lane: Dictionary) -> void:
var stats: Dictionary = lane.stats
stats.created.text = str(lane.created)
stats.recycled.text = str(lane.recycled)
stats.live.text = str(lane.live.size())
stats.idle.text = str(lane.idle.size())
func _lane(row: HBoxContainer, heading: String, tint: Color, origin: float, pooled: bool) -> Dictionary:
var column: VBoxContainer = VBoxContainer.new()
column.size_flags_horizontal = Control.SIZE_EXPAND_FILL
column.add_theme_constant_override('separation', 10)
row.add_child(column)
var title: Label = Label.new()
title.text = heading
title.add_theme_font_size_override('font_size', 24)
title.add_theme_color_override('font_color', tint)
column.add_child(title)
var stats: Dictionary = {}
for entry in [{key = 'created', label = 'instances created'}, {key = 'recycled', label = 'taken from the pool'}, {key = 'live', label = 'in the air now'}, {key = 'idle', label = 'waiting in the pool'}]:
var line: HBoxContainer = HBoxContainer.new()
line.add_theme_constant_override('separation', 12)
column.add_child(line)
var name_label: Label = Label.new()
name_label.text = entry.label
name_label.custom_minimum_size = Vector2(210, 0)
name_label.add_theme_color_override('font_color', Color('#8a90a0'))
line.add_child(name_label)
var value: Label = Label.new()
value.text = '0'
value.add_theme_font_size_override('font_size', 22)
line.add_child(value)
stats[entry.key] = value
return {origin = origin, tint = tint, pooled = pooled, live = [], idle = [], created = 0, recycled = 0, released = 0, stats = stats}
func _make_dot(tint: Color) -> Polygon2D:
var dot: Polygon2D = Polygon2D.new()
dot.polygon = PackedVector2Array([Vector2(-DOT, -DOT), Vector2(DOT, -DOT), Vector2(DOT, DOT), Vector2(-DOT, DOT)])
dot.color = tint
return dot
func _root() -> HBoxContainer:
var margin: MarginContainer = MarginContainer.new()
for side in ['margin_left', 'margin_right', 'margin_top']:
margin.add_theme_constant_override(side, 44)
add_child(margin)
margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var column: VBoxContainer = VBoxContainer.new()
column.add_theme_constant_override('separation', 16)
margin.add_child(column)
var title: Label = Label.new()
title.text = 'Allocate every time, or reuse'
title.add_theme_font_size_override('font_size', 28)
column.add_child(title)
var row: HBoxContainer = HBoxContainer.new()
row.add_theme_constant_override('separation', 40)
column.add_child(row)
node_count = Label.new()
node_count.add_theme_color_override('font_color', Color('#8da5f3'))
column.add_child(node_count)
return row
func _add_background() -> void:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)