C# - Figuring out if player is on road [SOLVED]

#1
Hello everyone,

I've made a very simple game in which you navigate a ball around (like the template). I have now constructed some roads through my level. To further experiment, I know want to reduce the velocity of my player, if it is rolling offroad.
I first thought, I'd use a Raycast via Physics.Raycast(), but there are no EntityRaycastFlags for "Road". And when I use EntityRaycastFlags.All it hits the terrain under the road instead (at least I think that's what happens, I can't get information about the hit in the out RaycastHit because it's not an entity that's being hit). Since my Road is using a unique material, is it possible to get the currently colliding material?

Does anyone has some ideas for this? Surely, there must be a way, it seems like a really simple functionality of a road to know if the character is walking on it.
C++ function names are also welcome, I can often find a wrapper around them in C# :)

kind regards,
Brotato
Last edited by Brotato on Mon Apr 09, 2018 6:26 am, edited 1 time in total.

Re: C# - Figuring out if player is on road

#3
@Sunfluxgames:
I'm pretty new to Game engines, so I didn't really understand what you were trying to tell me :D

I finally solved it programmatically though:

The Physics.Raycast() method returns a RaycastHit struct, that doesn't contain all the information that the c++ ray_hit struct contains. So I had to use the native c++ wrapper directly:

Code: Select all

private bool IsPlayerOnRoad() { var pos = Entity.Position; //The C++ bitfield containing the RayFlags uint s_rayFlags = unchecked((uint)((int)geom_flags.geom_colltype_ray << (int)rwi_flags.rwi_colltype_bit) | (int)rwi_flags.rwi_colltype_any | (10 & (int)rwi_flags.rwi_pierceability_mask) | ((int)geom_flags.geom_colltype14 << (int)rwi_flags.rwi_colltype_bit)); var rayParams = new IPhysicalWorld.SRWIParams { org = pos, dir = Vector3.Down * 2, objtypes = (int)EntityRaycastFlags.All, flags = s_rayFlags, hits = new ray_hit() }; //Since we're raycasting from inside our player, we need to add it to the skiplist //so it doesn't hit itself. rayParams.SetSkipEnt() expects the native IPhysicalEntity //instead of the C# PhysicsEntity, so we have to go an extra mile to get it. rayParams.AllocateSkipEnts(1); var nativeEntity = Global.gEnv.pEntitySystem.GetEntity(Entity.Id); var nativePhysics = nativeEntity.GetPhysics(); rayParams.SetSkipEnt(0, nativePhysics); //the actual raycast var numberOfHits = Global.gEnv.pPhysicalWorld.RayWorldIntersection(rayParams); try { if (numberOfHits > 0) { var _hit = rayParams.hits; Global.CryLog("surface_idx: " + _hit.surface_idx); //This surface_idx will be different, depending on the SurfaceType. var surfaceType = Global.gEnv.p3DEngine.GetMaterialManager().GetSurfaceTypeManager().GetSurfaceType(_hit.surface_idx); var surfaceName = surfaceType.GetName(); Global.CryLog(surfaceName); return surfaceName == "mat_road"; } else { Global.CryLog("No Hits."); return false; // Player probably jumping } } finally { rayParams.DeleteSkipEnts(); } }
So now, one can go under Assets/libs/materialEffects/SurfaceTypes.xml and define a new SurfaceType named Road.

Code: Select all

<SurfaceType name="mat_road"> <Physics friction="1" elasticity="0.2" pierceability="3" sound_obstruction="0.5" /> </SurfaceType>
This STILL doesn't detect the Road drawn with the road tool. it will cast through it and detect the ground terrain below it. So what I did is paint the area of the road with a new material (with SurfaceType Road) . You can't see it, because the Road is drawn on top. But when you go ingame and check the Log, you'll see the Raycast detects it as a road

Re: C# - Figuring out if player is on road

#4
@Brotato

Yep that is how its done.

Some people will use a player in capsule and move it base on ray cast and and the ground.

Other method is after you build your terrain is to build another solid layered component and just ray cast it.

For server side make sure you check it every frame and that only you can move the player to the correct location. Or hackers will use this to clip through objects.

Re: C# - Figuring out if player is on road

#7
The Physics.Raycast() method returns a RaycastHit struct, that doesn't contain all the information that the c++ ray_hit struct contains. So I had to use the native c++ wrapper directly:
Sorry, that was my bad. I forgot to expose the Surface ID value in the RaycastHit. I'll see if I can add it to 5.5 before it releases, otherwise it will show up in a later version of the engine.

And for what concerns being able to hit the road, did you make sure the road is physicalized? You can quickly check it by enabling the physics helpers by typing "p_draw_helpers 1" in the console. If the road is physicalized it will show a fully opaque collider over the geometry of the road. If it's half transparent it might not be caught by the raycasts because it's missing a surface type in the material.

Re: C# - Figuring out if player is on road

#8
The Physics.Raycast() method returns a RaycastHit struct, that doesn't contain all the information that the c++ ray_hit struct contains. So I had to use the native c++ wrapper directly:
Sorry, that was my bad. I forgot to expose the Surface ID value in the RaycastHit. I'll see if I can add it to 5.5 before it releases, otherwise it will show up in a later version of the engine.

And for what concerns being able to hit the road, did you make sure the road is physicalized? You can quickly check it by enabling the physics helpers by typing "p_draw_helpers 1" in the console. If the road is physicalized it will show a fully opaque collider over the geometry of the road. If it's half transparent it might not be caught by the raycasts because it's missing a surface type in the material.

Thanks for the reply! Of course, you were right in your guess and the road was not physicalized. I didn't realise this is necessary for a raycast detection.
As for the update of the RaycastHit struct - it's really cool to see you guys browse the community, looking for things to fix in the engine :)

Who is online

Users browsing this forum: No registered users and 3 guests