How does the CollisionRay Work?

I,m not asking in the basic sense, like setting it up, but rather, since it is infinity, does it go through solids, and if so, does it hit multiple collisions at once to gain multiple entires, I was testing it today, and found I had to flip my surface normals inverted just to get the up vector to align correctly with the geometry.

My collision sphere does not have this issue, but the flipping technique does not fully work though as if my character is standing on it’s axis completely left (90 degrees), when the ray comes to detect collision it flips my character 90 degrees (because I,am using headsUp)

Information about the CollisionRay would be appreciated, many thanks to you guys.

A Collision ray does indeed go through solids, I believe, and thus a single collision-traversal with a ray can produce multiple collision-entries.

In short, you can think of it less as a ray of light, starting at one point and travelling towards another, potentially being stopped by opaque objects, than as a line that may happen to intersect multiple objects across its length.

If you do find yourself getting multiple collision entries, and you’re using a CollisionHandlerQueue, you may find it useful to have the queue sort its entries. This can allow you to get the entry that’s closest to the ray’s origin point, and thus ignore any collisions that may happen beyond that closest collision.

As to your flipped normals, I’m not entirely clear on what you’re doing with your ray and sphere, and thus what might be happening to cause that. (Presuming that you aren’t just getting a collision with the underside of some object.)

This is very well shown in the example, roaming-ralph, but you can use CollisionSegment if you want to limit the range of the beam, but note that it still passes through all the objects that fall under it.

1 Like

Yeah, from research it is confirmed, because the CollisionRay goes though everything, I would imagine it is having trouble deciding what direction it is hitting the surface from, if that is the case I may be stumped to solved this at this time :confused:

it could be maybe the CollisionRay is such an old feature, it seems to work best with older Handlers like the HandlerQueue and single plane surfaces?


The multiple entries issue may be solvable, but I,m not using a HandlerQueue, I,am using HandlerPusher which works as a HandlerEvent, so how would priority work with that? does the event handler shoot out everything that was collided at that moment?

Because if so, I already implemented code to check which collision was closest to the character, but I wondering if it works correctly, because it is based on the perception that the handler event produces multiple entries from the same solid and point at the same moment, you can check it out below if you want.

    def surface(self, entry):
        entdist = (max(self.pactor.getPos(self.render), entry.getSurfacePoint(self.render)) - min(self.pactor.getPos(self.render), entry.getSurfacePoint(self.render))).length()
        self.entsdist1.extend([abs(entdist)])
        if "gravdet" in str(entry.getFromNodePath().getName()):
            truesurf = entry.getSurfaceNormal(self.render) * -1
        else:
            truesurf = entry.getSurfaceNormal(self.render)
            self.contact = 2         
        headsUp(self.quat, self.render.getQuat().getForward(), truesurf)
        self.entsdist2.extend([self.quat.getUp()])

So I would have a this collision entry produce my upVector I need to position the character, then in my movement task if multiple entries are present (or believed to be present), it sorts out the closest one in the code block below. (though, this could be intensive to both the memory and cpu)

# - Gravity Dedection
        if len(self.entsdist1) > 0 and len(self.entsdist2) > 0:
            quatprio = self.entsdist1.index(min(self.entsdist1))
            upVec = self.entsdist2[quatprio]
            self.entsdist1 = []
            self.entsdist2 = []
        else:
            upVec = self.render.getQuat().getUp()

I tried CollisionSegment, but found it can shrink only so much, in some cases I need it be so short it needs be nearly nonsexist.

well, I think I found something regarding the flipping problem.

on rdb’s last post, he was suggesting creating a directional vector from the subtraction of the previous pos to the current pos, but I thought there is always distance between the collision ray origin point and collision point due the collision sphere’s presence and radius.

So I subtracted the player’s position from the surface point and normalize that result, it ended up producing directional vector, and pretty darn accurate one too. I,m testing right now what I can do with this vector, and I will post a result soon!


EDIT: it has been some time, hah hah, but I did not get anywhere, I did make box and plane near each other, during my tests, and found that the plane works fine without my flipping technique but it flips the character with the technique applied, and vice versa with the box!

So if I,am thinking about it correctly my guess is the opposite face is also being detected, not only that, but the closer face/collision is being ignore and the farthest is only being applied since my code setup would pick up on the nearer face being closer, that is why everything is opposite detected on the ray.

It is giving priority to the last entry detected in the moment and ignoring the rest, the last entry on the box happens to be the bottom face which is opposite to the face that the character is on, so unless I misjudged something, this cannot be fixed. but I will wait for more opinions to see if a solution can be found, thanks for listening.

As you seem to have found, this is likely not quite the issue; rather, the issue is likely that the ray is intersecting with multiple polygons, and the intersection that happens to be selected is one that involves a polygon that faces the wrong direction.

Not really; this is just how ray-collisions tend to work, I believe.

If I may ask, why are you not just using a HandlerEvent? I imagine that you’re not using it as a Pusher as applied to the ray–to do so feels like it could potentially cause some issues, with the Pusher attempting to push the ray in response to multiple intersections.

I believe so, yes.

I don’t intend to suggest that you switch to CollisionSegment, but let me here note that it may be a good idea to offset your ray a little bit. That way even when the character is standing on the ground there should be a little distance between the ray’s origin and its expected first intersection. This also gives you a little leeway for cases in which the character might dip slightly lower than its intended standing height.

(And it occurs to me that the lack of this offset might be one reason that your code is “missing” that expected nearest intersection: the surface is ending up too close to the origin-point of the ray–and indeed, perhaps that origin-point is dipping just very slightly below the surface!)

I’d suggest reworking your code to use a CollisionHandlerQueue: you may find that it’s much simpler and more reliable.

(You can still use the Pusher for colliders other than your ray, after all.)

Furthermore, as I mentioned above, I’d suggest offsetting your ray’s origin such that, when the character is on a surface, the ray is placed a little bit above that surface.

thanks for tip, I,m testing the HandlerQueue right now, I did not know pusher and queue can co-exist, I was always told not to use multiple handlers, at the moment from my first test, it is even more jittery though.

You can’t use more than one handler for a single collision object, if I recall correctly. You can have multiple handlers each operating on different sets of collision objects, however.

It’s hard to say why that might be without seeing your code. It may be that something in your old version was masking whatever issue you’ve now uncovered, or that some assumption from the previous approach is still inaccurately in place in this approach–or something else again.

(… Is your Pusher acting on any collision-objects that might affect whatever object your ray is positioning, and that might be colliding with your “floor”? If so, that might cause some jittering as the two collision-responses “fight”.)

they both feed the same information, that is the surfacePoint and surfaceNormal to my code block that spits out a up vector to change the hpr, I,m looking over my code now to see what needs to be changed.

EDIT: so reapplied the flip trick the ray feed and everything seems okay right, but I need to test more.

Perhaps instead of a Pusher–which is likely going to move your object in addition to whatever movements you apply–your sphere might use a CollisionHandlerEvent–or even another CollisionHandlerQueue?

1 Like

the ray is still going opposite what the sphere is spitting out, however this time, when the flip trick is applied, it seems to be working at all angles.

Edit: does the queue not record the surfacePoint?, all I’am getting is the position of my node.

EDIT2: okay, it was picking up on my collision sphere! hah hah hah, I think this might be solved though, I need to run a couple more tests

Edit3: yes! it works, now a bit confused on the bitmasks but I got it to work, thanks Thaumaturge, I marked the relevant post as the solution, also thanks serega-kkz, for your tips.

1 Like

Just posting a update, I found out why the CollisionRay was flipping, it was because it’s origin point was slightly lower then the collision sphere’s center, therefore going though and past the surface producing a opposite vector, I guess the PusherHandler is slightly slower then the HandlerQueue.

So I fixed the collision ray’s point to be always above my collision sphere’s center by it’s radius and no more flipping, sadly though I couldn’t get the bitmasks to work, but I found a alternate way to filter out the collision sphere, it is this code block I created below.

            if self.queue.getNumEntries() > 0:
                self.queue.sortEntries()
                collflt = 0
                while collflt < self.queue.getNumEntries():
                    if self.queue.getEntry(collflt).hasInto():
                        if "CollisionSphere" in str(self.queue.getEntry(collflt).getInto().getClassType()):
                            collflt += 1
                        else:    
                            self.Point = self.queue.getEntry(collflt).getSurfacePoint(self.render)
                            self.Normal = self.queue.getEntry(collflt).getSurfaceNormal(self.render)
                            collflt = int(self.queue.getNumEntries())
                    else:
                        collflt += 1
                self.queue.clearEntries()

A little messy, but it gets the job done, oh, and the post I marked as the solution is the wrong one, it was the 7th one of this thread that was from Thaumaturge that was the solution, anyway, have a good day everyone.

1 Like