Page 1 of 1

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

Posted: Wed Mar 21, 2018 11:41 am
by Brotato
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

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

Posted: Thu Mar 22, 2018 1:03 pm
by sunfluxgames
Landscape Baked Collision with vertex collisions then just dynamically cast it to check if your on the ground with a boolean.


Blender or Maya.. or whatever 3d software can do most of the work for you. Should be a check box for your landscape.

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

Posted: Fri Mar 23, 2018 5:43 am
by Brotato
@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

Posted: Fri Mar 30, 2018 1:15 pm
by sunfluxgames
@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.

error in creating in opening c # script inside editor

Posted: Sat Mar 31, 2018 9:36 pm
by sportspereira
when I create the C # script to be able to implement some logic at a level of this error. Can someone help me with this situation?

[url]file:///C:/Users/Filipe/Desktop/Cryengine.PNG[/url]

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

Posted: Thu Apr 05, 2018 4:29 pm
by Cry-Flare
Hey sportspereira,

You cannot link to files directly from your computer, but you can attach the images to the post. When posting, there is the "Attachments" link under the editing box. Click this, and you can upload your image.

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

Posted: Fri Apr 06, 2018 2:26 pm
by cry-miron
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

Posted: Mon Apr 09, 2018 4:48 am
by Brotato
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 :)