How to resize a CollisionShape2D in game?

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

I wanted to change the size of CollisionShape2D during the game, for example: I have a character that can lower, so this causes your Shape2D in y to decrease a bit and the origin I believe has to go down too. How can I do this? If Shape2D shrinks is actually the correct way to do this, since it is as the child of a KinematicBody2D.

Up 1:

I thought of two ways to do this:

1 - Create a new “Shape” and transfer it to “CollisionShape2D”.

2 - Use “set_shape_transform” from my “KinematicBody2D” which asks me for two information “set_shape_transform (int shape_idx, Transform2D transform)”, I understood that “int shape_idx” in my case would have to be 0, since there is only one “CollisionShape2D”, so 0 would be the first one I would find, if there were two “CollisionShape2D” and I wanted to change the second of the order of the hierarchy, it would have to be 1, am I right?
As for the “Transform2D transform” I saw in the documentation that it is a Matrix32, so I thought of doing so:

Var m = Matrix32 ()
M [0] = Vector2 (0, 0) # X
M [1] = Vector2 (0, 0) # Y
M [2] = Vector2 (0, 0) # Origin

I do not quite understand how I would decrease here, I imagine I would have to use “get_shape_transform” to get the current “Transform2D”, and so change only the y where I want, am I right here?

And I see in the hierarchy the “CollisionShape2D”, has “Node2D”> “Transform”> {“Pos”, “Rot”, “Scale”}, is not there a way to directly change those? Example, something like:

Get_node ("CollisionShape2D") Node2D.Transform.Pos = Vector2D (0, 0)
Get_node ("CollisionShape2D") Node2D.Transform.Scale = Vector2D (0, 0)

Up 2:

I tried to do this:

var transform = get_node("CollisionShape2D").get_transform()
var oldScale = transform.get_scale()
transform.scaled(Vector2(oldScale.x, oldScale.y - 0.5))
get_node("CollisionShape2D").set_transform(transform)

But there is no change in Shape, where am I going wrong? And this is the best way to do this?

:bust_in_silhouette: Reply From: PerduGames

I’m an animal, I was doing it wrong, I could not get used to this syntax yet. The right thing would be to do this:

Var transform = get_node("CollisionShape2D").Get_transform()
Var oldScale = transform.get_scale()
Get_node("CollisionShape2D").Set_scale(Vector2(oldScale.x, oldScale.y - 0.5))

I understood that it was because the “set_transform” changes position and does not get a “Transform” as I was imagining.

But still I ask, is this the most efficient way to do this?

Here’s the correct way:

Var transform = get_node ("CollisionShape2D"). Get_shape ()
Var oldScale = transform.get_extents ()
Transform.set_extents (Vector2 (oldScale.x, oldScale.y - 40))

Scaling may not work well with Shape2D resources, changing shape values (radius, extents, polygon points) may be safer, do some tests to be sure.

eons | 2017-07-12 01:53

I got it, I updated the answer

And from what I read in the documentation, just change the scale of circles and ellipses that can not, the other shapes by what it says there it can.

PerduGames | 2017-07-12 11:38

Test with some little experiments with the way you are going to use it to be sure it works (may work for some things but not for all features).

Also remember that CollisionShape nodes are helpers, most shapes are added to the bodies by reference but some are made by the CS and added to the body (like convex polygons).

There may be cases where helpers are removed on runtime (maybe optional, not sure), so better try to work over the CollisionObject’s shapes directly (body/area.get_shape)

eons | 2017-07-12 12:57

So this is what I did right?

Var transform = get_node ("CollisionShape2D"). Get_shape ()
Var oldScale = transform.get_extents ()
Transform.set_extents (Vector2 (oldScale.x, oldScale.y - 40))

PerduGames | 2017-07-12 13:55

If works, do that, if not you may need to do get_shape on the body, not the CollisionShape node and maybe resize instead of scaling.

That is, set rectangle extents (RectangleShape2D extent, not Transform), radius (CircleShape2D), whatever capsule has and/or work on every PolygonShape2D made by the helper if using polygons (that may be a bit complex).
This only if physics start giving weird results on some specific use (some physics calculations do not take shape scale into account).

eons | 2017-07-12 21:35

:bust_in_silhouette: Reply From: rredesigns

Couldn’t you just get/set the extents property? That would be SO much easier. xD

I only saw after that there was a “.Set_scale”. xD

PerduGames | 2017-07-11 23:45

I wouldn’t scale a shape, it can make collisions less accurate and I think it might actually make the engine run a bit slower. Setting the extents is the way to go I guess.

rredesigns | 2017-07-12 05:26

How so “extends”, how would you do that?

I got it, I updated the answer

PerduGames | 2017-07-12 11:38

I just checked, and the help files says the Extents property is editor-only. So you can’t access that from a script.

Just make sure you scale uniformly and it should be good. :slight_smile:

rredesigns | 2017-07-12 13:08

But I got it perfectly here:

Var transform = get_node ("CollisionShape2D"). Get_shape ()
Var oldScale = transform.get_extents ()
Transform.set_extents (Vector2 (oldScale.x, oldScale.y - 40))

PerduGames | 2017-07-12 13:32