Init a tilemap via threads

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Degreeno
:warning: Old Version Published before Godot 3 was released.

Hi, I’m trying to use threads to ini a tilemap. In this example, I created 4 new threads and start them in a loop. My tilemap is 1000x1000 and it keeps crashing on execution. When I init the tilemap without threads, then everything works fine.

initWorldGeneration([0, 0, Global.worldSize.x, Global.worldSize.y])

I added a lock to ensure, taht the threads don’t interfere and even tested it with only one therad, but it keeps crashing.

extends Panel

var worldTile
var timer
var threads = []
var finished = 0
var wait
var maxValues = Vector2(2, 2)
var stage = 0


func _ready():
	wait = Mutex.new()
	for i in range(0, maxValues.x+maxValues.y):
		threads.append(Thread.new())
	worldTile = self.get_node("worldTile")
	self.set_size(Vector2(32*Global.worldSize.x, 32*Global.worldSize.y))
	initTimer()
	#initWorldGeneration([0, 0, Global.worldSize.x, Global.worldSize.y])


func startThreads():
	var idx = 0
	for x in range(0, maxValues.x):
		for y in range(0, maxValues.y):
			if(not threads[idx].is_active()):
				threads[idx].start(self, "initWorldGeneration", [x*Global.worldSize.x/maxValues.x, y*Global.worldSize.y/maxValues.y, (x+1)*Global.worldSize.x/maxValues.x, (y+1)*Global.worldSize.y/maxValues.y], 1)
				idx += 1


func initTimer():
	timer = Timer.new()
	timer.set_one_shot(false)
	timer.set_timer_process_mode(Timer.TIMER_PROCESS_FIXED)
	timer.set_wait_time(0.6)
	timer.connect("timeout", self, "_timer_callback")
	self.add_child(timer)
	timer.start()


func _timer_callback():
	if(stage == 0):
		stage == 1
		startThreads()
	elif(stage == 1 and finished == maxValues.x + maxValues.y):
		print("finished")
		stage == 1


func initWorldGeneration(arg):
	print(str("Starting thread with: ", arg))
	for x in range(arg[0], arg[2], 1):
		for y in range(arg[1], arg[3], 1):
			wait.lock()
			worldTile.set_cellv(Vector2(x, y), 0)
			wait.unlock()
	finished += 1
	return null

Thanks.

AFAIK, you should not do something to manipulate elements those will be rendered on screen on not main thread.

volzhs | 2017-07-18 22:03

Which means it is not possible to use more than one core to create/fill
tilemaps?

Degreeno | 2017-07-21 11:45

:bust_in_silhouette: Reply From: katuiche

It could be too late but I found a solution:

  1. Remove the tileMap from the tree
  2. Set the tileMap tiles
  3. Add the tileMap again to the tree

Those crashes seems to appear because the game is trying to update the collision/draw of the tileMap every frame. Removing from the tree makes the engine only update it once.

Note: Reducing the quadrant size bring backs the problem: 16 works fine, 2 don’t