Why does changing the radius of a collision shape makes ALL the collision shapes change?

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

My goal is to generate a solar system with a random number of planets and a sun. Planets are rigid bodies, the sun is a static body. I managed to make planets spawn by code. The radious of a planet should be 1024 * scale, where scale is a float between 0 and 1. I managed to do that too for the Sprite child node of the planets. The problem is that whenever i change the radius of the collision shape of a planet, the collision shape of the planets i modified before changes too in the same way. The result is that only the last planet i make spawn has the right collision shape radius. I cant see why is that, i think i’m doing something wrong but i really can’t see what.

This is how i generate systems in the mainScene:

func generateSystem():
#add sun
var sun = sun_class.instance()
sun.set_pos(get_global_mouse_pos())
gravity_objects.push_back(sun)
add_child(sun)

#add planets
var last_size = 0
var nplanets = randi() % 8 + 3
for i in range(nplanets):
	var planet = planet_class.instance()
	var scale = i + 1
	planet.init(gravity_objects, scale)
	var ang = randf() * 360
	planet.set_pos(Vector2(cos(ang), -sin(ang)) * 4000 * (i + 1))
	add_child(planet, true)
	
pass

This is the init function inside the planet scene:

func init(Gravity_objects, scale):
gravity_objects = Gravity_objects
set_mass(get_mass() * scale)
    
#I tried this way too, the result is the same
#var shape = CollisionShape2D.new().set_shape(CircleShape2D.new().set_radius(1024 * scale))
#add_child(shape)

var shape = get_node("CollisionShape2D").get_shape(); shape.set_radius(1024 * scale)
get_node("Sprite").set_scale(Vector2(1, 1) * scale)
print(scale)
pass

This is the planet scene:

This is the mainScene:

This is the result, the blue circles rapresents the actual collision shape, the black circles with white ring are the sprite of the planets:

Thanks in advance.

:bust_in_silhouette: Reply From: kidscancode

FYI, CollisionShape2D is a “helper” object that can only be used in the editor. You can’t use it from code. CollisionShape2D — Godot Engine (stable) documentation in English

Because of this, when you’re instancing the planets, they’re sharing the same collision shape resource. In the inspector, you can choose “make unique”, but you can also do it in code. I solved a similar problem by adding the collision shape after selecting the object’s size. Leave off the collision shape from your scene, and then In your init:

var shape = CircleShape2D.new()
shape.set_radius(1024 * scale)
add_shape(shape)

EDIT: missing word: “resource”. Clarifying that it’s a shared resource between all the instances.

“Because of this, when you’re instancing the planets, they’re sharing the same collision shape”
I don’t think so. They won’t share the same shape if they are instanced multiple times, unless I missed something?

Zylann | 2017-03-01 23:24

Yes, they share the same resources from the PackedScene, there is no way to instance without sharing the resource, it need to be replaced after instancing, even duplicate on the PackedScene won’t break the relation.


You can do this too:

planet_instance.set_shape(0,planet_instance.get_shape(0).duplicate(true))
planet_instance.get_shape(0).set_radius(new_radius)

If you want use the visual debug from the CollisionShape2D node, you need to add this (because that node will be drawing the original shape on screen).

planet_instance.get_node("CollisionShape2D").set_shape(planet_instance.get_shape(0))

ps: you can do all this on the planet script, so they manage their own shapes on ready/init.

eons | 2017-03-02 00:08

Thank you so much, it worked like a charm.

Censacrof | 2017-03-02 14:15

I don’t see a “Make unique” option in the editor in 3.0, am I just missing it?

Edit: Made an issue about this on Github and someone pointed it out to me! Changing the radius of a collision shape makes ALL the collision shapes change · Issue #16737 · godotengine/godot · GitHub

jarlowrey | 2018-02-16 04:12

Make unique is in 3 too, second top right button on the inspector, also on dropdown.

May be a bit harder to duplicate shapes on 3 by code because of the shape owner thing, I have not tried yet.

eons | 2018-02-17 11:32