Multiple threads - set_shape_transform: Index p_index = 0 is out of bounds (shapes.size() = 0)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Vildnex

Hello guys, I’m trying to make a simulation in Godot on multiple threads, I’m trying to implement a small MAS(Multi-agent system) in it just for the simulation purpose.
In other words, I’m trying to spawn N NPCs(agents) which they are going to attack each other if they are going to be found one by another.
Each agent is a scene in which I want to be placed on separate threads and also I want them will be distinct one to another.
But not raise the question, can I do that? Or I can just instance each one of them?

Main.gd

extends Node2D

var dragons = 3
var screen_size

var dragon = preload("res://Player.tscn")

var thread_1
var thread_2
var thread_3


func _thread_function(userdata):
	var x = floor(rand_range(0, screen_size.x))
	var y = floor(rand_range(0, screen_size.y))
	
	var dr = dragon.instance()
	
	dr.start(Vector2(x,y))
	call_deferred("add_child", dr)
		
func _ready():
	screen_size = get_viewport_rect().size
	thread_1 = Thread.new()
	thread_1.start(self, "_thread_function")

	thread_2 = Thread.new()
	thread_2.start(self, "_thread_function")

	thread_3 = Thread.new()
	thread_3.start(self, "_thread_function")

func _exit_tree():
	thread_1.wait_to_finish()
	thread_2.wait_to_finish()
	thread_3.wait_to_finish()

Player.gd

extends Area2D

#export (PackedScene) var Attack

export (int) var speed = 200
var velocity = Vector2()


var is_fliped = false


var atk
var screen_size

var has_arrived = false
var destination_point = Vector2()

var target = Vector2()
var is_enemy_found = false
var can_shot = false 

var spawn

onready var target_found = get_node("RayCast2D")
#onready var attack = get_node("Attack")

var hits = 5
	
onready var attack = preload("res://Attack.tscn")
var flip_ray2d = false

signal _on_Player_hit

func _ready():
#	$AttackTimer.stop()	
	randomize()
	$AnimatedSprite.modulate = Color(randf(), randf(), randf())
	screen_size = get_viewport_rect().size
	destination_point = decide_next_move()

func start(pos):
	position = pos

func decide_next_move():
	var x = floor(rand_range(0, screen_size.x))
	var y = floor(rand_range(0, screen_size.y))
	
	return Vector2(x,y)
	
func move_character():
	if has_arrived:
		destination_point = decide_next_move()
		has_arrived = false
	velocity = Vector2()
	var is_walk = true
	
#	print(is_fliped)
#	print(position.x, " ",destination_point.x)
#	print(position.y ," ", destination_point.y)
#	print("\n")
	if position.x <= destination_point.x:
		is_fliped = false
		velocity.x += 1
	elif position.x > destination_point.x:
		is_fliped = true
		velocity.x -= 1
	if position.y < destination_point.y:
		velocity.y += 1
	elif position.y > destination_point.y:
		velocity.y -= 1
	
	has_arrived = position.distance_to(destination_point) < 2
		
	$AnimatedSprite.play('walk')
	$AnimatedSprite.flip_h = is_fliped
	
	target_found.rotate(1)
	
#	print(target_found.is_colliding())
	
	if target_found.is_colliding():
		is_enemy_found = true
		var d =  target_found.get_collider()
		target = d.position
		_attack()
		
		
	velocity = velocity.normalized() * speed

func _attack():
	spawn = attack.instance()
	get_tree().root.add_child(spawn)
	# Set the bullet's direction the same as the player's
	spawn.connect("_on_Player_hit", self, "_on_Player_hit") 
	spawn.start(target)
	spawn.rotation = global_rotation
	# Set the mob's position to the player's.
	spawn.position = global_position
	# Set the velocity (speed & direction).
	spawn.linear_velocity = Vector2(20, 0)
	spawn.linear_velocity = spawn.linear_velocity.rotated(global_rotation)
	
	return

func _process(delta):
	move_character()
	position += velocity * delta
	
#func _on_AttackTimer_timeout():
#	_attack()
	pass

func _on_Player_hit():
	hits -= 1
	if hits <= 0:
		queue_free()
#	spawn.hide()
#	remove_child(attack.instance())
#	print("HIT")
	pass # Replace with function body.

ERROR MESSAGE:

E 0:00:00.589 set_shape_transform: Index p_index = 0 is out of
bounds (shapes.size() = 0). <C++ Source>
servers/physics_2d/collision_object_2d_sw.cpp:78 @
set_shape_transform() E 0:00:00.589 area_set_shape_disabled: Index
p_shape = 0 is out of bounds (area->get_shape_count() = 0). <C++
Source> servers/physics_2d/physics_2d_server_sw.cpp:408 @
area_set_shape_disabled()

Could any of you explain to me what I’m doing wrong? And also if it’s possible at least o instantiate each Player.tscn on an individual thread.