Build #1123: physics.rayCast() "hit order" resolved.

Hello all Corona physics fans,

Good news! As of Daily Build #1123, the “hit order” issue of physics.rayCast() that’s inherent to Box2D has been fixed. Instead of supplying the maximum number of hits that you wish to detect (as the fifth argument), you now have three options to return exactly the hit(s) you need.

This property can be one of the following options:

  • “any” — The first valid result, but not necessarily the closest to the starting point (behaves like before).
  • “closest” — The closest result from the starting point (default return value if none is specified).
  • “sorted” — all of the results, sorted from closest to furthest from the starting point.

Here’s the Daily Build documentation on it.

http://docs.coronalabs.com/daily/api/library/physics/rayCast.html

The raycasting tutorial and demo project have also been updated accordingly.

http://www.coronalabs.com/blog/2013/05/07/physics-raycasting-and-reflection/

Hopefully this is useful for you!

Brent Sorrentino

Hmmm…

My question is, when you say “any” behaves like before, does it really? As now you say it only returns the first valid result, hence we wouldn’t be able to detect more then one hit this way?

For example if i have a target I wanna shoot and he’s behind a door, previously raycast would detect the door and the target (doesn’t matter in what order as I would check the distance). I would then be able to manually eliminate the door from the raycast hits list and be left with only the target, thereby confirming that the target can be hit.

So, with the new method, if there is an obstacle in the way of the final target you want to reach AND for example, it doesn’t matter if this obstacle is in front of the target, which new method is best to use with raycast now to make sure I can hit the target?

Hi Jacques,

I see your point, and it’s valid. I’ve put in an initial request to the engineers to add another filter called “unsorted” which will basically return ALL hits in the raycast, in no predictable order, which you can use to perform your own custom filtering on (i.e. ignore sensor objects between the source and your target).

Until that happens, you can use the “sorted” method in your game, and then swap it out later for “unsorted”.

Take care,

Brent

Brent thanks for this.  I used to use a workaround to get sorted results but as soon as the fix was released I implemented it and it works great.  Also @jacques1 point is very valid.

Deflect our new game using rayCasting just released yesterday on Google Play, and is in review on the other stores.

Here is a link to the free version of Deflect should anyone wish to try it out: https://play.google.com/store/apps/details?id=com.icyspark.deflect.lite

In this image for one of the levels, the white blocks are mirrors, the blue block is a splitter(splits laser in 2.  50% reflects, 50% goes through) and the red and green blocks are filters which change the colour of the laser beam.

By reflecting the main laser beam off the mirror, it goes into the splitter, giving 2 lasers.  One goes through, the other is reflected back, which hits the mirror and goes back into the splitter etc etc.  By slightly offsetting the splitters rotation from the mirror, you can create a focal point as shown to pass many laser beams through the small opening.  By rotating the splitter the other way you can create a fan effect to spread the lasers out.

Oh and there are also portals in the game, which are always fun which is in the level below.

Here you have to send the laser into the closed off area through the portal to turn on all the lights and get it to come back out, change it’s colour and send it back in.  Not quite as easy as it may seem.

I relied totally on Raycasting for this game.  There is no collision listeners at all.  50 sorted raycasts, each going through up to 10 objects runs smoothly on iPhone 4. 

Hmmm…

My question is, when you say “any” behaves like before, does it really? As now you say it only returns the first valid result, hence we wouldn’t be able to detect more then one hit this way?

For example if i have a target I wanna shoot and he’s behind a door, previously raycast would detect the door and the target (doesn’t matter in what order as I would check the distance). I would then be able to manually eliminate the door from the raycast hits list and be left with only the target, thereby confirming that the target can be hit.

So, with the new method, if there is an obstacle in the way of the final target you want to reach AND for example, it doesn’t matter if this obstacle is in front of the target, which new method is best to use with raycast now to make sure I can hit the target?

Hi Jacques,

I see your point, and it’s valid. I’ve put in an initial request to the engineers to add another filter called “unsorted” which will basically return ALL hits in the raycast, in no predictable order, which you can use to perform your own custom filtering on (i.e. ignore sensor objects between the source and your target).

Until that happens, you can use the “sorted” method in your game, and then swap it out later for “unsorted”.

Take care,

Brent

Brent thanks for this.  I used to use a workaround to get sorted results but as soon as the fix was released I implemented it and it works great.  Also @jacques1 point is very valid.

Deflect our new game using rayCasting just released yesterday on Google Play, and is in review on the other stores.

Here is a link to the free version of Deflect should anyone wish to try it out: https://play.google.com/store/apps/details?id=com.icyspark.deflect.lite

In this image for one of the levels, the white blocks are mirrors, the blue block is a splitter(splits laser in 2.  50% reflects, 50% goes through) and the red and green blocks are filters which change the colour of the laser beam.

By reflecting the main laser beam off the mirror, it goes into the splitter, giving 2 lasers.  One goes through, the other is reflected back, which hits the mirror and goes back into the splitter etc etc.  By slightly offsetting the splitters rotation from the mirror, you can create a focal point as shown to pass many laser beams through the small opening.  By rotating the splitter the other way you can create a fan effect to spread the lasers out.

Oh and there are also portals in the game, which are always fun which is in the level below.

Here you have to send the laser into the closed off area through the portal to turn on all the lights and get it to come back out, change it’s colour and send it back in.  Not quite as easy as it may seem.

I relied totally on Raycasting for this game.  There is no collision listeners at all.  50 sorted raycasts, each going through up to 10 objects runs smoothly on iPhone 4. 

Hi guys,

Just a reminder that raycasting now has the “unsorted” filter, as of recent daily builds. This will return all of the raycast hits in no particular order, so you can use whatever conditional checks that you require for your game.

Best regards,

Brent

That’s great Brent, although i still have a question, which is faster;

returning back a ‘sorted’ hitlist then removing some of the objects that I don’t need to check

Or

returning back an ‘unsorted’ hitlist then removing some of the objects from the hitlist that I don’t need to check and then sorting out the remaining objects left in the hitlist?

Both ways would end up giving me a reduced list of only the objects i need to check, however the question is… which way would be faster :slight_smile:

Hi @jacques1,

The “unsorted” method will be slightly faster than “sorted” internally, so if you plan to use custom filtering (your code) in either case, you’re better off using the “unsorted” method.

And on that note, all of the internal filtering methods will be faster than anything you do in Lua… so if you want sorted results, use the API “sorted” filter (don’t use “sorted” and then sort them yourself in Lua). :slight_smile:

Take care,

Brent

Hi guys,

Just a reminder that raycasting now has the “unsorted” filter, as of recent daily builds. This will return all of the raycast hits in no particular order, so you can use whatever conditional checks that you require for your game.

Best regards,

Brent

That’s great Brent, although i still have a question, which is faster;

returning back a ‘sorted’ hitlist then removing some of the objects that I don’t need to check

Or

returning back an ‘unsorted’ hitlist then removing some of the objects from the hitlist that I don’t need to check and then sorting out the remaining objects left in the hitlist?

Both ways would end up giving me a reduced list of only the objects i need to check, however the question is… which way would be faster :slight_smile:

Hi @jacques1,

The “unsorted” method will be slightly faster than “sorted” internally, so if you plan to use custom filtering (your code) in either case, you’re better off using the “unsorted” method.

And on that note, all of the internal filtering methods will be faster than anything you do in Lua… so if you want sorted results, use the API “sorted” filter (don’t use “sorted” and then sort them yourself in Lua). :slight_smile:

Take care,

Brent

Hey guys,

I was curious as to how you are applying your own filters to the list of ‘hit’ objects?
I have two objects in my game I want the ray to ignore:

  • static barriers that my enemy tanks are able to shoot over/through, but their actual physical body cannot pass.
  • invisible radial-sensors (radars if you will)

The biggest problem is the radars; when an enemy casts a ray towards the user (to check if there is a clear path to fire) the ray registers a hit for any other radars that might either be overlapping ray’s parent tank object or if a radar is somewhere along the path between the enemy casting the ray and the user.

Any thoughts?

-Saer

Ok it’s quite simple actually, once you have the list of hits detected, do a check for the names of the objects in the check list (naturally you have to make sure you’ve given a name to each object, do this by simply creating an additional variable such as barrier.name=“barrier”, etc etc.)

Then when checking the hit list, if the barrier name is in that list, simply remove it from the hit list table. If the hit list array is still greater then 0 then you can be sure your ‘bullet’ hit something (other then the barrier) and it simply ‘passes over/through’ the barrier.

I have a large number of objects i don’t want detected through raycast in different situations. So either you can have a bunch of checks based on your situation or you can have different function each with their own raycast hit test that have different checks.

Hope this helps in some way :wink:

Would you mind elaborating a bit?

This is my function (the raycast bit anyways)

-- Casts a ray to check whether or not the enemy tanks have a clear firing path function ETfire( self, user\_tank )          EDray = physics.rayCast( self.x, self.y, user\_tank.x, user\_tank.y, "sorted" )              local hitFirst = EDray[1]     local hitX, hitY = hitFirst.position.x, hitFirst.position.y          if EDray then         -- There's at least one hit.         print( "Hit count: " .. tostring( #EDray ) )         -- Output all the results.          for i,v in ipairs(EDray)  do             print( "Hit: ", i, v.object.class, " Position: ", v.position.x, v.position.y )     end         print( "The first object hit is: ", EDray[1].object.class )         else         -- There's no hit.     end     if ( EDray[1].object.class == "PlayerTank" or EDray[1].object.class == "Uturret" or EDray[1].object.class == "bullet") then              print("PlayerTank in range! Fire!")             timer.performWithDelay(40, function() ShootEnemyBullet( self, user\_tank ) end, 1) --- ShootEnemyBullet function and bullet code --- end  

I guess I’m just confused on how to remove an object from the hit list…
According to the docs, when a ray is cast it returns an array of the objects hit - which in my case I’m assuming is EDray - and I’m guessing I’d just do something like if EDray.object.class == “Radar” then – remove object from hit list –
Would I just use table.remove(EDray, 1) or is there a different way I should do it?

– Sorry for my lack of knowledge, I’ve only just recently optimized my code to make use of tables. –

-Saer

 

-- Casts a ray to check whether or not the enemy tanks have a clear firing path function ETfire( self, user\_tank ) EDray = physics.rayCast( self.x, self.y, user\_tank.x, user\_tank.y, "sorted" ) local hitFirst = EDray[1] local hitX, hitY = hitFirst.position.x, hitFirst.position.y if EDray then for i =#EDray,1,-1 do if EDray[i].object.class == "radar" then table.remove(EDray,i) end end if #EDray~=0 then -- hit something so do your magic if ( EDray[1].object.class == "PlayerTank" or EDray[1].object.class == "Uturret" or EDray[1].object.class == "bullet") then print("PlayerTank in range! Fire!") timer.performWithDelay(40, function() ShootEnemyBullet( self, user\_tank ) end, 1) end end end end

Man I hate this forum’s formatting, anyway the above would remove ALL radars in the hitlist and only leave the stuff you wanna hit.

haha yeah, it can be a pain sometimes.

Thank you for your help, jacques1. :slight_smile:

It works perfectly!
Adding the ray’s overall hit count as an additional condition in the ‘if’ statement was what I could not figure out.

Cheers!

-Saer

Hey guys,

I was curious as to how you are applying your own filters to the list of ‘hit’ objects?
I have two objects in my game I want the ray to ignore:

  • static barriers that my enemy tanks are able to shoot over/through, but their actual physical body cannot pass.
  • invisible radial-sensors (radars if you will)

The biggest problem is the radars; when an enemy casts a ray towards the user (to check if there is a clear path to fire) the ray registers a hit for any other radars that might either be overlapping ray’s parent tank object or if a radar is somewhere along the path between the enemy casting the ray and the user.

Any thoughts?

-Saer

Ok it’s quite simple actually, once you have the list of hits detected, do a check for the names of the objects in the check list (naturally you have to make sure you’ve given a name to each object, do this by simply creating an additional variable such as barrier.name=“barrier”, etc etc.)

Then when checking the hit list, if the barrier name is in that list, simply remove it from the hit list table. If the hit list array is still greater then 0 then you can be sure your ‘bullet’ hit something (other then the barrier) and it simply ‘passes over/through’ the barrier.

I have a large number of objects i don’t want detected through raycast in different situations. So either you can have a bunch of checks based on your situation or you can have different function each with their own raycast hit test that have different checks.

Hope this helps in some way :wink: