Climb Wall character controller

Hey guys, i have this simple script i found for my charater and would like to know how can i make it climb a wall up down sideways on controller collision. Something like function

OnControllerColliderHit (hit : ControllerColliderHit) {
if(hit.transform.tag == "wall1" && Input.GetAxis("Vertical") > .1) {
transform.LookAt(Vector3(hit.transform.position.x, transform.position.y, hit.transform.position.z));
do stuff change gravity, vector3..

And then when enters a trigger the controls reset to the initial state

Any help would be appreciated since im new to programming and really need this to finish my project

var  animation1: String = "idle";
var  animation2: String = "walk";
var  animation3: String = "run";
var  animation4: String = "rotateAround";

var walk : float = 1.0;
var run : float = 4.0;
private var walkSpeed : float = 1.0;
private var gravity  = 100.0;
private var moveDirection : Vector3 = Vector3.zero;
private var charController : CharacterController;

function Start()
{
    charController = GetComponent(CharacterController);
    animation.wrapMode = WrapMode.Loop;
}

function Update () 
{
    if(charController.isGrounded == true)
    {
        if(Input.GetAxis("Vertical") > .1)
        {
            if(Input.GetButton("Fire1"))
            {
                animation.CrossFade(animation3);
                walkSpeed = run;
            }
            else
            {
                animation[animation2].speed = 1;
                animation.CrossFade(animation2);
                walkSpeed = walk;
            }
        }
        else if(Input.GetAxis("Vertical") < -.1)
        {
            animation[animation2].speed = -1;
            animation.CrossFade(animation2);
            walkSpeed = walk;
        }
        else
        {
        // Plays Idle
            animation.CrossFade(animation1);
        }

        // Create an animation cycle for when the character is turning on the spot
        if(Input.GetAxis("Horizontal") > .1 && !Input.GetAxis("Vertical"))
        {
            animation[animation4].speed = 1;
            animation.CrossFade(animation4);
        }
        // Nota esta a inverter animacao fica melhor uma nova animacao
        if(Input.GetAxis("Horizontal") < -.1 && !Input.GetAxis("Vertical"))
        {
            animation[animation4].speed = -1;
            animation.CrossFade(animation4);
        }

        transform.eulerAngles.y += Input.GetAxis("Horizontal");
        // Calculate the movement direction (forward motion)
        moveDirection = Vector3(0,0, Input.GetAxis("Vertical"));
        moveDirection = transform.TransformDirection(moveDirection);

    }

    moveDirection.y -= gravity * Time.deltaTime;
    charController.Move(moveDirection * (Time.deltaTime * walkSpeed));
}

What you could do is give the climbable walls or areas a box collider which set as a trigger. Then you could have on your character

var climbing = false;
OnTriggerEnter(){
    climbing = true;
    //whatever other changes you want
}
OnTriggerExit(){
    climbing = false;
}

Then in your Update() function, you could have an if statement to check if we are climbing, and if we are, move in one way, and if not, then move as you already have it moving. Probably the only changes we want to what you have are to ignore gravity (remove the line `moveDirection.y -= gravity * Time.deltaTime;`) and to map forward movement (`Input.GetAxis("Vertical")`) to upward movement:

moveDirection = Vector3(0, Input.GetAxis("Vertical"), 0);

It's not perfect by a long shot, but as a quick and dirty way of climbing a wall, it should be sufficient.

EDIT:

Ok, here is the full script that I came up with, based on your original script. It is commented heavily, which I used to explain the whys of what I did, so that if you need to change it you can understand what each part does.

This script requires a kinematic rigidbody, but it will automatically attach one to your gameObject, so don't worry about that. It also requires a box collider set to act as a trigger that is just slightly in front of the walls which are climbable. The trigger needs to have the tag set to "climbableWall" and it is very important. Without it, this won't be any different from what you have now.

I also cleaned a few things up which were unrelated to climbing, but I commented all of them, and tried to explain my reasoning.

So without further rambling, here it is:

//require the CharacterController and a Rigidbody (for trigger)
@script RequireComponent(CharacterController)
@script RequireComponent(Rigidbody)

//not how I would have done the animation assignment, but perfectly functional
var  animation1: String = "idle";
var  animation2: String = "walk";
var  animation3: String = "run";
var  animation4: String = "rotateAround";

//renamed walkSpeed to moveSpeed for clarity
//also added our rigidbody var which is required to trigger OnTriggerEnter events
var walk : float = 1.0;
var run : float = 4.0;
private var moveSpeed : float = 1.0;
private var gravity  = 100.0;
private var moveDirection : Vector3 = Vector3.zero;
private var charController : CharacterController;
private var body : Rigidbody;
private var climbing : boolean;

function Start()
{
    //assign our variables which link to other components, and set animation mode
    charController = GetComponent(CharacterController);
    body = GetComponent(Rigidbody);
    body.isKinematic=true;
    animation.wrapMode = WrapMode.Loop;
}

function Update () 
{
    //We call Input.GetAxis a lot, so let's just call them once, and store the answer
    var h : float = Input.GetAxis("Horizontal");
    var v : float = Input.GetAxis("Vertical");

    //reset our moveDirection variable each time, just to be safe
    moveDirection = Vector3.zero;
    if(climbing)
    {
        //we are climbing, so we use different movement rules
        //we shall use much of the same structure that is laid out below, because it is a fundamentally good structure
        //this is not really optimized, and there is probably a more compact way of accomplishing the same goal, but this is easy to follow. 

        //always use the walk speed
        moveSpeed = walk;

        if(v > .1)
        {
            //pushing forward
            moveDirection.y = v * moveSpeed;

            //in addition to moving updwards, let's push forwards
            //if we are still on the wall, the wall will push back and this will not matter
            //if we reach the top of the wall, this will allow us to move to standing on top of it, instead of getting stuck hovering over the trigger
            moveDirection.z = v * moveSpeed;

            //perhaps also a climbing animation?
        }
        else if(v < -.1)
        {
            //pushing backwards
            //this is actually the case when we care if we are grounded
            if(charController.isGrounded)//shorthand for == true, it's a boolean itself, after all
            {
                //we are already at the bottom of the wall, and should move backwards, away from the wall
                moveDirection.z = v * moveSpeed;
            }
            else
            {
                //we are not at the bottom, and should move downwards
                moveDirection.y = v * moveSpeed;
            }
        }
        //now we do the same thing (more or less) with the horizontal axis, so that we can move sideways. 
        if(h > .1)
        {
            //we are pushing to the right nontrivially
            moveDirection.x = h * moveSpeed;
        }
        else if(h < -.1)
        {
            //we are pushing left nontrivially
            moveDirection.x = h * moveSpeed;
            //we have these two separate instead of just comparing Mathf.Abs(h) > .1 in case you want to change the animation for right vs left
            //if you don't add anything else, you might as well replace this if else with a single if(Mathf.Abs(h) > .1){ moveDirection.x = h * moveSpeed}
        }
        //it is actually possible to get here without triggering any of the above movement conditions. 
        //But if that is the case, then we are on a climbable wall and should not do anything
        //if you do want to do something if we aren't moving, like play a wall idle animation, then let's use:
        //if(moveDirection == Vector3.zero)
        //{
        //
        //}
    }
    else
    {
        //we are not climbing, so see if we are on the ground or in the air
        if(charController.isGrounded == true)
        {
            //if we are grounded, we process input
            if(v > .1)
            {
                //if we are pushing forward in a nontrivial manner
                if(Input.GetButton("Fire1"))
                {
                    //if we are pressing the Fire1 button, which is apparently the run button
                    animation.CrossFade(animation3);
                    moveSpeed = run;
                }
                else
                {
                    //we are not pressing the run button, so just walk (forward)
                    animation[animation2].speed = 1;
                    animation.CrossFade(animation2);
                    moveSpeed = walk;
                }
            }
            else if(v < -.1)
            {
                //we are not pushing forward, so look if we are pushing backwards in a nontrivial manner
                //we don't care about the run button, just walk
                animation[animation2].speed = -1;
                animation.CrossFade(animation2);
                moveSpeed = walk;
            }
            else
            {
            // Plays Idle
                //we were not pushing significantly in either direction
                animation.CrossFade(animation1);
            }

            // Create an animation cycle for when the character is turning on the spot
            //I restructured this collection of if statements. There wasn't anything wrong with how you had it, but changes I have made necessitated a change
            //and I think it's prettier this way. 
            if(Mathf.Abs(v) < .1)
            {
                //if we are inside of our deadzone:
                if(h > .1)
                {
                    animation[animation4].speed = 1;
                    animation.CrossFade(animation4);
                }
                // Nota esta a inverter animacao fica melhor uma nova animacao
                //the above comment means nothing to me :)
                if(h < -.1)
                {
                    animation[animation4].speed = -1;
                    animation.CrossFade(animation4);
                }
            }
            //transform.eulerAngles.y += Input.GetAxis("Horizontal");
            //I took out the above line because, from the script reference:
            //Don't increment them, as it will fail when the angle exceeds 360 degrees. Use Transform.Rotate instead.
            transform.Rotate(0, h ,0);
            //we rotate around the y axis, but with less failure when we cross from 360 to 0

            // Calculate the movement direction (forward motion)
            //Let's apply the movement scalar here instead of after gravity, so that gravity is not effected by it. 
            moveDirection = Vector3(0,0, v * moveSpeed);
            moveDirection = transform.TransformDirection(moveDirection);

            //now on to apply gravity (obey gravity, it's the law)
        }
        //we just exited the if(grounded) loop, so if we are not grounded, then all we do is apply gravity
        //and then apply the motion to the controller

        //gravity is here because we only want to apply it if we are not climbing, 
        //but we don't care if we are grounded or not
        moveDirection.y -= gravity * Time.deltaTime;
    }
    //we have just left the if(climbing) else structure, so all possible conditions will execute this next line, as it should be
    charController.Move(moveDirection * Time.deltaTime);
}

function OnTriggerEnter(other : Collider)
{
    //check to see what trigger we just set off. It is possible that we want to use other triggers than just our wall climbing one
    //Triggers are useful, after all. 
    //we obviously need to match the tag on the climbable wall triggers to what we have here. 
    if (other.tag == "climbableWall")
    {
        //ok, so we hit our climbable wall trigger
        climbing = true;
        //we should face the wall directly, to make sideways movement work properly. 
        //this finds the point on the trigger that is closest to us and looks at it. 
        transform.LookAt(other.ClosestPointOnBounds(transform.position));
        //we will then level it out, leaving only the y rotation. the x shouldn't be necessary, but it doesn't hurt. 
        transform.rotation.eulerAngles.z = 0;
        transform.rotation.eulerAngles.x = 0;
    }
}

function OnTriggerExit(other : Collider)
{
    //again, check which trigger we just left
    if(other.tag == "climbableWall")
    {
        climbing = false;
    }
}

One thing that may solve your problem is looking into hit normals.

I recently applied some code to my own game that tracked the hit normals of my charactercontroller's collisions, and realized that by simply tracking the hit normals you can easily detect when you're pushing against a wall, which will eliminate the need to create specially tagged wall colliders and allow the character to climb up any valid, perfectly vertical (or whatever angle you want) wall. If you link the hit normals to a GUIText, you can easily debug them and learn what values to track.

I have no code for you to work off of, but I thought I would offer you the theory and see if you can do anything with it.

Once the hit normals detect you're pressing against a wall, you could then have your character mount the wall (and be in perhaps a "mounted" state). And one thought I had from there is that while "mounted" you can cast rays from 4 points above/below/left/right of the character aimed at the wall you're on to constantly check when there's no longer a climbable surface around you, and restricting movement in the corresponding fashion.

Sorry if that makes no sense, I tried to explain it the best I could. And also remember that this is primarily for a "climb anything" system that purely reacts to geometry, similar to something like Assassin's Creed, and may not be what you were after.

Thank you for the help. Removing the gravity line won't do the trick seems that it doesn't ignore it just by removing this line so i made a separate script and thought of using the gravity to climb up. The character goes up but pressing the opposite vertical axis he goes on the z axis and not the y. Also pressing the horizontal makes him rotate around because of the transform.eulerAngles.y. Also i had to remove the if(charController.isGrounded == true) witch is not good either. So using the gravity won't do the trick. Can you please make a sample code im really new to scripting

OnControllerColliderHit (hit : ControllerColliderHit) {
    if(hit.transform.tag == "ClimbWall" && Input.GetAxis("Vertical") > .1) {
    climbingWall = true;
    transform.LookAt(Vector3(hit.transform.position.x, transform.position.y, hit.transform.position.z));
    transform.eulerAngles.y += hit.transform.position.y;
    someScript.moveDirection = Vector3(0,Input.GetAxis("Vertical"),0);
    someScript.gravity = -5;
    someScript.moveDirection.y = someScript.gravity * Time.deltaTime;
    }
    else if (hit.transform.tag == "ClimbWall" && Input.GetAxis("Vertical") < -.1) {
    someScript.gravity = 5;
    }
    else {
    someScript.gravity = 0;
    }
    }

    function OnTriggerEnter (other : Collider) {
    someScript.moveDirection = Vector3(0,0, Input.GetAxis("Vertical"));
    someScript.gravity = 10;
    someScript.moveDirection.y -= someScript.gravity * Time.deltaTime;
    }