What's the best way to instantiate dozens of clickable polygons ?

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

I’ve been implementing a Voronoi module in order to compute a map composed of randomly generated Voronoi cells, here is what it looks when I use the godot-built-in _draw() function.

My goal is to set up clickable polygons for a stategy game, one per province - I guess, even if this idea might be questionable.

My first approach was : generate a CollisionShape based on each cells’ corners (given by the module), then a RigidBody2D and add the CollisionShape as a child of it. At this point I have no idea how to connect the input (as a mouse click) of the RigidBody2D, because this newly generated RigidBody2D obviously doesn’t have a script. I thought that instantiating a general-purpose RigidBody2D scene with a script might be the solution, but I’m afraid that I would a heavy process to instantiate dozens, not to say hundreds, of scenes.

I guess another approach could be to use an UI texture button but I thought that 2D nodes were a cleaner and more appropriate solution, mainly because of the static nature of UI, but I may be completely wrong.

An ultimate but important point is that I need to be able to draw each polygon texture procedurally, I would like to implement a biome system, with cells as sea and moutain among others.

If you have any idea, knowledge or advice, it would be very appreciated.
Thanks for reading :slight_smile:

post-scriptum : here is my project’s code so far, to give an idea:

I have no idea how to connect the input, because this newly generated RigidBody2D obviously doesn’t have a script.

You don’t have to use a standard class! You could as well prepare a custom scene including scripts, preload that and add instances of it to your tree instead of plain RigidBody2Ds. And if you add an func init(points_array) function to this custom scene, this function could not only take care of the signal connection, but also handle the creation of the Polygon2D and CollisionShape subnodes.

Thomas Karcher | 2020-11-27 16:40

Thanks for replying. If I understood correctly, that’s equivalent of what I said further in my post : creating a new scene.

I’m wondering about two things here:

  • does creating approximatively 200-300 scenes would be heavier than another 200-300 repeated process ? I don’t know if scene instantating is actually a big memory consumer, and if there is other lighter ways
  • how would I make these polygons clickable ? Within every scene’s
    script ? Would it work ? If yes, what node could I use,
    CollisionShape like we said or something else ?

Sorry in advance for all these intricate questions, and thanks again to whoever reach this far hahaha

edesse | 2020-11-27 18:21

:bust_in_silhouette: Reply From: Thomas Karcher

After all those questions in the comments, I decided it would be easier to just create a demo project than answering them individually. :slight_smile:

The demo creates a couple of clickable voronoi cells and connects a custom “region selected” signal from the region subnodes (triggered by mouse clicks) to the main script.

There’re only two small scripts:

  • MapRegion.gd takes care of setting up the shapes, colors and colliders for an individual region based on the input points. It also takes care of input handling.
  • Demo.gd creates instances of MapRegion and connects all of them to _on_MapRegion_selected

Delauntor.gd and VoronoiHelper.gd are not really relevant for the demo: I didn’t use the Voronoi module you mentioned but the Delaunator script by hiulit (https://github.com/hiulit/Delaunator-GDScript). That’s what these two scripts are for. But it should be easy to replace them with the module again if needed.

I just downloaded and loaded your work, it is awesome ! I will dig deeper to understand the whole thing, the Git repository is a great idea. I don’t know how to thank you as I would like to, be sure that your help was really useful to me !

I have some last thoughts :

  1. How much do you think a Voronoi module like the on I was talking
    about is faster than a complete GDScript project like you sent ?
  2. Which one would be the most easy to deal with when adding feature or updating Godot version ?


Thank you very much for your dedicated help !

edesse | 2020-11-28 14:44

I’m happy you like it! :slight_smile:

Regarding your questions:

  1. I have no idea. I guess the module should be faster, but seeing that GDScript is able to calculate 1000 points in 67ms on a 2015 MacBook Pro (see https://github.com/hiulit/Delaunator-GDScript#performance), I doubt that the difference really matters when calculating ~300 regions.

  2. Hard to tell. It really depends on your abilities (if you want to add features yourself) and the maintainers willingness to update their projects (if a future update of Godot breaks it). Personally, I’d go for GDScript whenever possible, because this makes it easier for others to use my code without the need to recompile their engines.

Thomas Karcher | 2020-11-28 20:16