+2 votes

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:
enter image description here
This is the mainScene:
enter image description here
This is the result, the blue circles rapresents the actual collision shape, the black circles with white ring are the sprite of the planets:
enter image description here

Thanks in advance.

in Engine by (17 points)

1 Answer

+5 votes
Best answer

FYI, CollisionShape2D is a "helper" object that can only be used in the editor. You can't use it from code. http://docs.godotengine.org/en/stable/classes/class_collisionshape2d.html

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.

by (21,714 points)
selected by

"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?

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.

Thank you so much, it worked like a charm.

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! https://github.com/godotengine/godot/issues/16737#issuecomment-366146621

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.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.