Procedural ledge grab and wall run ect ect ect...

Hi
So I had a look around and everybody seems to be insisting on using triggers on the ledge.
This method is all well and good for a linear game or a platformer, but my project is an fps on a much larger scale so setting up Litteraly hundreds of thousands of triggers is simply not an option.

My best guess is to use raycasts to find a viable ledge and apply the correct action but I cannot work out the method for finding a viable ledge.from a raycast.

As for the wall run I have a good idea how i might handle that but if anybody has any suggestions on that then they are welcome and much appreciated.

Ultimately i need the player to grab before they can wall run.

Can anybody help me out here?

If I can get this to work I will post a complete solution of the working script for everybody to use. :sunglasses:

1 Like

A single raycast would probably miss the object often. How about you create an invisible cone extends from the player and if it touches a ledge object and the conditions are correct your char can grab it? It would be good to stream all ledge objects in so the look-up function isn’t called all the time as I hear, can’t confirm, that it is slow.

Either that or use multiple raycasts and interpolate a shape based on where their ends finish. If the shape is greater than your test volume then you have a grabable (?) ledge.

Manually setting up all those trigger boxes would indeed be a bit crazy. However, assuming that your scenery is properly built from prefabs, you would just need to add the triggers to those.

Parkour games primarily use trigger-like setups for two very good reasons:
1: Calculating ledge grabs etc. at runtime is expensive.
2: Runtime systems can produce undesirable results. An editor time system can be inspected and tweaked.

1 Like

I think triggers are still the way forward.

In my game, for ledge grabbing/sidling/jumping, the triggers are just a hierarchy of empty game nodes placed along the route I want the ledge to take (which can be vertex snapped into position) and I have a script applied to the parent node which goes through the hierarchy aligning the parent to it’s child and applying a ledge trigger box that spans the gap between the two. The script component deletes itself and I’m left with a nice series of ledge trigger boxes exactly where I wanted them.

The advantage being that so long as they’re a hierarchy, I don’t have to align them or set up each trigger box - all that’s handled in code. I just need to put the nodes in the right place.

Also, I’m using a spherecast limited to the ledge node’s layer. Raycast is far too accurate and often misses the little triggerboxes as the player moves each frame.

Here’s the generateLedgesFromChildren.js script I wrote.

The hierarchy I use runs like;

LedgeGroup (this is the empty gameobject with the script below on it)
…|- LedgeNode (these are all empty game objects with no scripts on them, the gap between them will be filled with a ledge trigger)
…|- LedgeNode
…|- LedgeNode

#pragma strict

function Awake () {

	gameObject.layer = LayerMask.NameToLayer ( "Ledge_Grab" );

	var child = transform.Find ( "LedgeNode" );
	
	if ( child != null ) {
		// Store child transform.
		var childPosition : Vector3 = child.position;
		var childRotation : Quaternion = child.rotation;
		
		// Distance between this and child.
		var distance : float = Vector3.Distance ( transform.position, child.position );
	
		// Move this object into place.
		transform.LookAt ( child );
		transform.Rotate ( 0, -90, 0 );
		transform.Translate ( Vector3 ( distance / 2, -0.05, -0.05 ) );
		
		// Restore child transform.
		child.position = childPosition;
		child.rotation = childRotation;
		
		// Add and set up collider.
		var ledgeCollider : BoxCollider = gameObject.AddComponent ( "BoxCollider" ) as BoxCollider;
		ledgeCollider.size = Vector3 ( distance, 0.1, 0.1 );
		
		// Add this component to the child.
		child.gameObject.AddComponent ( "generateLedgesFromChildren" );
	}
	
	// Destroy this component. It's work is done.
	Destroy ( this );
}

function OnDrawGizmos () {

	var childrenTransforms : Transform[] = gameObject.GetComponentsInChildren.<Transform> ();
	
	var parentTransformPos : Vector3 = transform.position;
	for ( var childTransform : Transform in childrenTransforms ) {
		Gizmos.color = Color.yellow;
		Gizmos.DrawLine ( childTransform.position, parentTransformPos );
		parentTransformPos = childTransform.position;
	}
}

Just to clarify a bit: What most parkour games do is they still have an automated system detecting ledges, trenches, doors etc, but this is just run at editor time and places markup data not too dissimilar to trigger boxes.

The level designer can then go in and inspect the result, removing unwanted markers and adding extras.

I like this Idea but it still requires me to place all the nodes which is alot of work believe me. Imagine an open urban ruin the size of the Island demo and that is a fraction of the environment. You can call me lazy if you like.

But still I went over your code and it seems pretty solid and I reckon its in the right direction. It has inspired me though. Could the node data be replaced with vertex data and search for viable ledges based on the normals that connect along the edge between the vertices?

Even if it was run on level load or in the editor that would be fine. Obviously vertex/node spacing would then be a factor to consider. The length of a normal would also have to be worked out but then it would be a very flexible and reusable.

If this could be run in the editor I could go back and clean it up after as AngryAnt mentioned.

Yeah, if you’re going to have to be messing with ‘realtime ledge detection,’ you may as well just build an editor script to parse your level data and automatically set up triggers for you before runtime. That way, you can have the benefits of triggers, and you can also tweak it by hand if need be.

Yeah, you could write a script that’ll crawl the mesh data and give you all the edges that are viable ledges and set up triggers for them.

I think I will create something like this but first of all I found a better solution by mistake here by Wolfire Games.

The developer here uses a sphere to detect a nearby wall and creates a cylinder above the player that checks for a surface above the player.
If the player is close enough to the cylinder it creates a node at the ledge and that becomes the players anchor instead of usng a trigger.
As far as i can see this should have minimal overhead and maintains a procedural process as and when its needed. this could save me weeks.

1 Like

Ok so I managed to start working on this today and I thought i could use OverlapSphere since triggers won’t detect colisions with static objects but after looking over the documents i found that OverlapSphere checks against the bounding volume and not the collider.

I would prefer not to use a dirty method of rotating the scene back and foreward .00001 or something every frame so that i can use triggers. taking into consideration that this would cause larger anomalies the further away from the centre of the levels mesh you get. I was thinking of cycling a raycast one per frame (this is to reduce the overhead of raycasting) in a curcular pattern around the player at 2 - 3 different heights to detect nearby walls when the character is airborn and then reducing its raycast cycle to the raycasts only in the walls direction based on where it contacts the wall. This is all for the purpose of the wall check part of the system.

Does anybody know of another method i could use for wall checks that would require a less processor heavy method than raycast.
Reducing overhead is obviosly Important here. because I will be layering in a ledge check the instant that a wall check returns true, both of these will be updated whenever the player moves. Again this is to lower overhead they only need to update if the players position/rotation updates.

Sorry for the long description I just want everybody to get an idea of the logic to avoid confused replys.

Edit: I forgot to mention that more than one player may be making wall checks simultaniosly including AI. This Is why overhead Is a problem when more than one player or npc jumps near a wall.

I did parkour coding when I used UDK. I used many traces(Raycast in Unity) and placed them at particular areas of the body. I’d have a trace at the torso, feet aiming forward, feet aiming 45 degree angle down, the head, etc. They worked great, but the team I was working on it with went bleh…so I stopped working on it. A guy that used to help with the code(because he was doing the same in his team) used WAY more traces(again, Raycasts) for better effects.
You can use the method shown in the video.

Erm sorry but, what video is this?

The one you posted earlier in the thread. I think that was a good idea. Actually, I was thinking of doing something likewhat was show in the video (http://www.youtube.com/watch?v=GFu44...el_video_title)when I was working my parkour.

yes that was the plan but unfortunately If i use a solid collider it will hit the wall causing unrealistic collision for the player If i change it to a Trigger Collider then it wont register collisions with static objects and overlap sphere only registers the bounds of the collider which is no good either. Unity just doesn’t support trigger collision the way udk or the Overgrowth engine does.

Edit: My point being is unless i can find a workaround that isnt as dirty as moving the level geometry every frame so that the trigger can register the collision then I will have to go with raycasts though I’d prefer to use something with less overhead

Why not make it a kinematic rigidbody collider?

I’ve been thinking about this for fun… might be a dumb idea but… what if you did raycast chain to empty nodes parented to the player, one basically directly in front of his head, and one a few meters above? Sort of like an angler fish? The first raycast would hit the top empty node to see if there is an open space above, the second would cast downward from the first to check for the climbable surface? Epic diagram:

1 Like

would that work?
and would it need to be set as a trigger or colider?
I just finnished a rig using linecast and nodes that are set in a cartwheel kinda way with 8 nodes that the linecast send to and it gives a good response to wall collisions but I’m still not happy with it.

this is sort of where we are going with this but I want the ledge detection to have a radial response to the environment so that it checks ledges in front, behind and too the side with as little relyance on nodes and triggers as possible. also preferably little or no raycasting but i seem to be failing to that end.
nice epic drawing by the way, I like the idea and may use the down check which i’ve been thinking of.

Thanks, haha. But yeah, kinematic rigidbody + collider do not need to be triggers… they basically function similarly to triggers (in that don’t actually respond to collisions, get pushed around or anything), but they still send collision messages with hit data.

I’ve been messing with it trying to get a collision to display a debug when it hits something but it still gives no readout.
this is what i’m using to register the collision throught the debuger

function OnCollisionEnter (collision : Collision) 
{
	Debug.Log ("I see a wall in your future");
}

this on the other hand registers but requires 8 nodes and 8 linecasts on a rig to work

var node1 : Transform;
var node2 : Transform;
var node3 : Transform;
var node4 : Transform;
var node5 : Transform;
var node6 : Transform;
var node7 : Transform;
var node8 : Transform;

function Update () 
{
	var hit : RaycastHit; 
	
	if (Physics.Linecast(transform.position, node1.position) || Physics.Linecast(transform.position, node2.position) || Physics.Linecast(transform.position, node3.position) || Physics.Linecast(transform.position, node4.position) || Physics.Linecast(transform.position, node5.position) || Physics.Linecast(transform.position, node6.position) || Physics.Linecast(transform.position, node7.position) || Physics.Linecast(transform.position, node8.position))
	{
		Debug.Log ("Lookout For That Ohhhh!!");
	}
}

plus its messy

Edit: Ok sorry I added a rigidbody to the level geometry and it registered the collision but launched the level into space kryptonian prison system style :frowning: