phaser
phaser copied to clipboard
Matter.Query.ray returns the ray itself, but only a few times
Version
-
Phaser Version: 3.60.0
-
Operating system: Windows 11
Description
I am directly using the Matter.Query.ray function in a Phaser scene, as I am trying to write common code that can also run on my Matter instance on a server.
What I found is that, at first, the ray function returns a collision with a new body that is not in the scene nor in the Matter world (with a label of "Rectangle body") instead of the only object I am trying to raycast (labelled "player"). This happens a dozen times or so, and then the player is correctly found by the next raycasts.
After some testing, I believe this new rectangle is actually the ray itself, as I understand Matter creates a thin rectangle for its basic raycasting features, and its position and angle match where I am shooting. I have also noticed that this rectangle is created with an incrementing id, starting from 0. The ray returns this rectangle while its id is lower than the object it is actually colliding with.
Additional Information
This behavior only happens when using the Matter function inside Phaser, it does not happen within the Matter instance.
I can try to reproduce this in an example if needed.
I have found more info on this, I guess I should have done more printing. This simply appears to be an inconsistency in how rays are created. The reason why it works better in Matter is simply because the ray that is created always has a higher id, it does not start at 0. It is then always assigned to parentB in the collision data, and the other object is parentA (which is also body, bodyA and bodyB).
That means the weird behavior comes from the ray id starting at 0 instead of incrementing with the objects in the world.
TL;DR : My best guess is that scene.matter.add does not increment Matter.Common.nextId. The ray is created using nextId, so it's not in sync with the other object ids.
Every single Matter object, no matter if created via matter.add or directly, invokes Body.create and the first thing that does is id: Common.nextId() - so sadly, I don't think the issue is id related, at least not with newly created objects. If you modify a body, or create a Matter body and add it to a Phaser object, then internally that will use setExistingBody and that won't assign a new ID.
Also, the id isn't used when running a collide check anyway, so I think it's a red herring, sorry.
All ray does is make a rectangle and pass it to Query.collides - and all that does is iterate every single body and check for an overlap with it. So I can see this would fail if the bodies are not in their final positions, or this ray is created at some point in the game step prior to the Matter bodies being synced with the Phaser Game Objects. Or, perhaps the constant rects it's colliding with are the world bounds that Phaser creates? Because the collides method will reject a comparison of a body against itself. The Phaser version of Matter is not the same as the official Matter one, we merged in lots of additional fixes and changes that aren't present upstream yet, so be sure your server version matches your local version, too.