Despawning with KDTree

I am implementing a spawner/despawner system in my game.
To improve performance I use kdtree to check whether an Empty is within the radius of the player or not. If so, the empty spawns the object (could be a sound, an effect, ai… whatever). That is working fine so far.
The problem is the despawning.
I need the empty to stop spawning if the player leaves the kdtree radius and be ready to spawn items again if the player re-enters the area.

My code so far looks like this

	def start(self, args):
		self.scene = self.object.scene
		self.timer = Timer(0)
		self.spawnerEmpty = [obj for obj in self.scene.objects if "spawner" in obj]
		self.kd = kdtree.KDTree(len(self.spawnerEmpty))
		self.radius = args["Radius"]
		self.objList = []

		for id, obj in enumerate(self.objectEmpty):
			self.kd.insert(obj.worldPosition, id)

		self.kd.balance() = None

	def objectAdder(self, obj, add):
		addObj= obj["Name"]
		if add == True:
			if obj["adder"] == 0:
				obj["adder"] = 1
				self.scene.addObject(addObj, obj, 0)
		elif add == False:
			obj["adder"] -= 1

	def update(self):
		if self.timer.getElapsedTime() > 2:
			nearList = self.kd.find_range(self.object.worldPosition, self.radius)
			for obj in nearList:
				self.objectAdder(self.spawnerEmpty[obj[1]], True)

				if nearList[-1][2] > self.radius:
					self.objectAdder(self.spawnerEmpty[obj[1]], False)

So the objects that are spawned can have their own code and despawn themselves whenever the player is out of reach.
But I don’t want every spawnerEmpty to run its own code so I do this centralized from the player.

Basically, what I would like to achieve is setting back the obj[“adder”] property in the objectAdder() function back to 0 so it will be able to spawn items again whenever the player is back in the kdtree reach.

Does anybody know how to solve this? I’ve tried so many things but can’t find a solution :confused:

Check the objList, or add another list with the kdtree position and check if position is in the kdtree?


for obj in objList:
    if obj.worldPosition in nearList:
        #in range
        #not in range
1 Like

So, since the kdtree return is a list in the order of distance, you can simply make the radius a little bigger,
And use a if switch when proccessing the list,

for returned in kd.find_range(point, radius):
    if returned[2]<cuttoff:
    elif reutrned[2]> maxDist:

You can also separate the cleanup check to look from the back side of the list, negative index values = the stuff furthest away

1 Like

Thanks guys, that was how I solved it in the end…
To despawn stuff, I just subtracted a value from the radius and that worked :slight_smile:

Not sure if this is what your looking for, but I’ve personally found this example really helpful for learning to spawn/de-spawn objects using KDTree.