Pool de objetos

Duas fontes emitindo no mesmo ritmo, uma alocando cada partícula e outra pegando de volta de um pool. Os contadores é que discutem.

O editor acima está rodando este projeto. Mude uma linha e ele recarrega.

Classes do Godot usadas

Node.queue_freePolygon2DPerformance

O código

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)

Mais exemplos de Dados