Climbing a pole or tree?

Hi i use a character controller and wanted to make my player be able to climb up a pole or shaft.

Basically once triggered that the player has hit a pole or climbable surface (i have just tagged it and use OnControllerColliderHit) i’d like the player to be stuck to the surface simular to Super Mario 64 or Prince of persia when climbing a tree, so that left or right will simply make the player move around the pole/tree as in rotating around it. And up and down will move the player up and down the surface.

Sorry for a basic question but i’m having some trouble with it.

Thanks

Something like this might do

void OnCollisionEnter(Collision collision)
{[INDENT]if (Input.GetKey(KeyCode.UpArrow))
[/INDENT][INDENT] {
[INDENT] if (collision.gameObject.tag == "Ladder")
{

this.transform.Translate(0, Vector3.up * Time.deltaTime, 0);

}
[/INDENT]}
[/INDENT]}

Well my main problem was making it stick to the pole while moving left or right, so that moving right will move anti-colockwise around a pole and make the player stick to it.

I thought maybe i’d need to raycast forward to find the normal of the pole and then rotate my player to match that as well as moving the forward to be attached to the pole but i couldn’t seem to figure it out,

Here’s one way…

  1. Decide where you’re going to be after you’ve moved right.
  2. Raycast from that position either forward or to the center of the object (if you don’t adjust rotation you’ll definately need to raycast to center of object but doing that will give you incorrect results).
  3. Detect the y normal of the triangle the raycast collided with, adjust the player rotation to be facing the normal.

Sooo… (doubt this works but you can play with it to see if it does)

Vector3 newPosition;
RaycastHit hit;

void Update()
{

    if (Input.GetKey(KeyCode.LeftArrow))
    {

       newPosition = transform.position + (Vector3.left * Time.deltaTime);

    if ([URL="http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html"]Physics.Raycast[/URL] (newPosition , fwd, out hit, 2))
    {
       this.transform.position = hit.point;
       this.transform.rotation = Quaternion.SetFromToRotation(this.transform.rotation.ToAngleAxis(), new       Vector3(this.transform.rotation.ToAngleAxis().x, -hit.normal.y, new Vector3(this.transform.rotation.ToAngleAxis().z);

}

The other way is to calculate the future location of the player and find the “ClosestPointOnBounds” from the object you are currently climbing:

Vector3 newPosition;
RaycastHit hit;

void Update()
{
[INDENT] if (Input.GetKey(KeyCode.LeftArrow))
{
[INDENT] newPosition = transform.position + (Vector3.left * Time.deltaTime);

newPosition = colliderOfObjectIAmClimbing.ClosestPointOnBounds(newPosition);

this.transform.position = newPosition;

this.transform.LookAt(colliderOfObjectIAmClimbing.transform);
[/INDENT]}

[/INDENT]}

The second method is working pretty well with only one problem, it tilts the player causing him to lean throught the pole.

Is there a way to make the LookAt not effect the tilt of the player?

Thank you for your time and help!

I thought something like would work but it didn’t it stops it from working all together

var lookAt = climbingCollider.transform.position;
lookAt.x = 0;
this.transform.LookAt(lookAt);

maybe something like this:

var rotate = Quaternion.LookRotation(Vector3(target.position.x, transform.position.y, target.position.z) - transform.position);

transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * damp);

Just making sure target in this case is climbingCollider.transform?

Sorry about the question but just wanting to be sure.

Thanks

Edit works lovely!

One very small this is that the character is sorta centered, in the pole so he is clipping the pole rather baddly sorta half his body is in it.

Thanks again guys really appreciate the help!

yeah, probably. this was taken from an AI script were the enemy would only rotate around the y axis

Thanks yeah got that going nice, but he appears to be clipping the pole rather baddly almost half his body is inside the pole at times? How should I handel that?

You need the player to be positioned away from the object so do something along the lines of this.

playerPosition.transform.position = playerPosition.transform.position + (new Vector3((climbingObject.transform.position - playerPosition.transform.position).normalized.x, 0, (climbingObject.transform.position - playerPosition.transform.position).normalized.z) * distance);

Would distance be the radius of the pole?

It seems to be shaking the whole scene around a lot each frame. Tired a few distances, nothing seems to be working to well.

You’d need to include the new player position inside your lerping function

Sorry i’m such a pain, could you post an example of that i’m still new to unity. You have been very helpful thankyou.

Make it easy, after you rotate your player just move it backward

player.transform.position = player.transform.position + (-player.transform.forward * 2);

Ok this is what i have now

if (Input.GetKey(KeyCode.LeftArrow))
		{ 
			newPosition = transform.position + (-transform.right * Time.deltaTime);
			newPosition = climbingCollider.ClosestPointOnBounds(newPosition);
			transform.position = newPosition;
			var rotate = Quaternion.LookRotation(Vector3(climbingCollider.transform.position.x, transform.position.y, climbingCollider.transform.position.z) - transform.position);
			transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * 10);
			transform.position = transform.position + (-transform.forward * 0.3);
		}

Unfortunatly it looks like its going to work (good distance in this case) but unfortunatly it won’t move anymore.

Could it be that if you are only moving left then your not ever moving up therefore not changing your closest point?

Edit:

Nevermind i’m an idot got it all working now, cheers guys!