Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | yerbestpal |
Hi folks,
I’m having an issue where a LineShape2D with one-way collision enabled is ‘pulling’ or ‘warping’ the rigidBody2D from underneath (i.e. the side it is not meant to interact with) when I activate the associated layer bit.
The GIF isn’t as clear as I would like, but hopefully it demonstrates that I am trying to make the player header the ball on a button press, otherwise the ball should pass through. Collision is working fine, it’s just the warping issue.
The only code involved is used to set the relevant collision layer bit when in the ‘header’ state, and unset it when exiting that state.
Player node tree:
Ball node tree:
func _transition_state(_delta):
match state:
states.idle:
if !get_parent().is_on_floor():
return states.jump
if get_parent().velocity.x != 0:
return states.run
if get_parent() and Input.is_action_just_pressed('player_action'):
return states.header
states.run:
if !get_parent().is_on_floor():
return states.jump
if get_parent().velocity.x == 0:
return states.idle
if get_parent() and Input.is_action_just_pressed('player_action'):
return states.header
states.jump:
if Input.is_action_just_pressed('player_action'):
return states.spin
if get_parent().is_on_floor():
return states.idle
elif get_parent().velocity.y >= 0:
return states.fall
states.fall:
if get_parent().is_on_floor():
return states.idle
states.spin:
if get_parent().velocity.y > 0:
return states.fall
states.header:
if get_parent().anim_player.current_animation != 'header':
if get_parent().velocity.x != 0:
return states.run
else:
return states.idle
func _on_enter_state(_new_state, _old_state):
var anim = get_parent().anim_player
match state:
states.idle:
collision_shape_head.set_collision_layer_bit(1, false)
anim.playback_speed = 2.5
anim.play('idle')
states.run:
collision_shape_head.set_collision_layer_bit(1, false)
anim.playback_speed = 8
anim.play('run')
states.jump:
anim.stop()
get_parent().get_child(0).frame = 5
states.fall:
get_parent().set_collision_layer_bit(1, false)
get_parent().get_child(0).frame = 6
states.spin:
get_parent().set_collision_layer_bit(1, true)
anim.playback_speed = 2
anim.play('spin')
states.header:
collision_shape_head.set_collision_layer_bit(1, true)
anim.play('header')
The gif isn’t displaying, could you edit please? Also is there code / node setup you can share? There’s not enough to go on here, at least for me.
DaddyMonster | 2022-05-20 18:01
Apologies, the GIF should be viewable now. I’ll get some code and screenshots up in a sec.
yerbestpal | 2022-05-20 18:20
Done. Hopefully this is enough information, just let me know if it isn’t.
yerbestpal | 2022-05-20 18:36
Hmm. The gif still isn’t working for me. Obviously you’re getting some kind of stretching when you’re headering the ball but I’m not clear on what’s happening. I do have a couple of general observations which may or may not be helpful:
-
Is your animation moving the RigidBody? The RB is run by the physics engine. If you move it yourself you’re fighting with the engine (=bad). Try changing the
mode
to kinematic during the animation or only apply the animation to the Sprite - ensure you do not directly set the transform of the RB. -
You’re using the animation player for what is quite an elaborate set up. I advise against this, it becomes unmanageable very quickly. Add an animation tree - it’s one of the best features in Godot. You’ve got several options but the one that looks best for you is a StateMachine. This will allow you do add nodes and use XY coordinates to lerp between the states so you get smooth transitions between states and you can massively reduce / simplify the code. Docs:
Using AnimationTree — Godot Engine (stable) documentation in English
Sorry I can’t be more help.
DaddyMonster | 2022-05-20 18:51
Is your animation moving the RigidBody?
No, there is no interaction between the animation and RigidBody.
Add an animation tree - it’s one of the best features in Godot
I’ll need to look into this. for now, it all goes over my head. Thanks for the suggestion and help regardless.
yerbestpal | 2022-05-20 19:09
I’m annoyed that I couldn’t answer this one. Hopefully you’ll get someone else comment. If the gif had worked I might have stood a chance but your code and node setup you shared all look basically fine, I’ve read through it three times now (unless I missed something…) The major issue is I can’t picture in my head what’s happening.
For the collision obj, check where the origin is - it should be in the middle (or at the neck) - and make sure it has an identity basis matrix (Transform2D.x = Vector2(1, 0)
and Transform2D.y = Vector2(0, 1)
) - if that’s anything else there’s your problem). Check that the layer / mask indexes are correct. Run the collision without the animation. Then run it with an animation that does nothing. Usual debugging stuff, pressure and time solves these things.
Anyway, when you have some time look into AnimationTree
, there will be a “it does all that?!” moment when the penny drops.
Good luck!
DaddyMonster | 2022-05-20 21:21
and make sure it has an identity basis matrix
(Transform2D.x = Vector2(1, 0)
andTransform2D.y = Vector2(0, 1))
- if that’s anything else there’s your problem).
I don’t actually know what an identity basis matrix is and I’m not making use of Transform2D in my project to my knowledge.
With regards to AnimationTree, I’ve implemented an AnimationTreeStateMachine and that its self is really cool, although I’m a bit lost as to how to control animation speed now. I’m yet to research what else AnimationTree is capable of.
Thanks for all your advice.
yerbestpal | 2022-05-22 18:14
Honestly, I’m 99.9% sure your problem is not the basis. Quick explanation of what it is if you’re interested as on lunch and have a minute and it’s pretty fundamental:
Basis is part of an object’s “transform” (along with “origin” which states where the start point of the object is).
When a node has a vector, eg Vector2(3, 4)
, you’re saying it’s so far on the x and so far on the y. But which way is x and which way is y to this object? Well, you define this with a basis matrix. It’s like defining the graph paper your vectors are drawn on.
The standard/simplest way is the “identity”: Transform2D.x = Vector2(1, 0)
and Transform2D.y = Vector2(0, 1)
.
So any vector is multiplied by its basis matrix. If it’s “identity” (as above), nothing changes - just like multiplying by 1 with a float. This means local space is the same as world space.
If we changed the basis on the x to Transform2D.x = Vector2(2, 0)
then it’ll scale it on the x and it’ll be twice as wide. Transform2D.y = Vector2(0, -1)
and it’s upside down. With a bit more maths we can rotate the object and sheer it. In Godot the transform matrices of children are multiplied. So if you move an object, its children move, if you scale it, it’s children scale.
Meh, I thought maybe your object might be sheered, but I doubt it.
DaddyMonster | 2022-05-23 12:59