Clear all movement on collision with certain object and moving towards mouse look

Hello Everyone,

I need help with coding. It is FPS game. I have made so when I collide with water I turn off my regular controls and I start using new ones because when in water I want to be ale to float freely. I don’t need any force and fancy things like that. Just floating in the direction of the mouse look and use the movement keys for forward, left, right and back.

Well it sounds easy but it is not.

My questions are:

  1. How to make so when I collide with water I will loose all previous movement modifications. I am asking this because When I jump right into the water object I still have my gravity but I lose it in the collision. However I still have it if I press the jump key which should not work underwater.

  2. How to make so when I am in water and press FORWARD (the “W” key) I will move in the direction of the mouse but UP and DOWN included. Just like in ALL FPS games with swimming.

Here is the code in C# for movement and collisions it is modified FPSWalker Enhanced:

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(CharacterController))]
public class FPSWalkerEnhanced : MonoBehaviour
{

    public float walkSpeed = 6.0f;

    public float runSpeed = 11.0f;

    // If true, diagonal speed (when strafing + moving forward or back) can't exceed normal move speed; otherwise it's about 1.4 times faster
    public bool limitDiagonalSpeed = true;

    // If checked, the run key toggles between running and walking. Otherwise player runs if the key is held down and walks otherwise
    // There must be a button set up in the Input Manager called "Run"
    public bool toggleRun = false;

    public float jumpSpeed = 8.0f;
    public float gravity = 20.0f;

    // Units that player can fall before a falling damage function is run. To disable, type "infinity" in the inspector
    public float fallingDamageThreshold = 10.0f;

    // If the player ends up on a slope which is at least the Slope Limit as set on the character controller, then he will slide down
    public bool slideWhenOverSlopeLimit = false;

    // If checked and the player is on an object tagged "Slide", he will slide down it regardless of the slope limit
    public bool slideOnTaggedObjects = false;

    public float slideSpeed = 12.0f;

    // If checked, then the player can change direction while in the air
    public bool airControl = false;

    // Small amounts of this results in bumping when walking down slopes, but large amounts results in falling too fast
    public float antiBumpFactor = .75f;

    // Player must be grounded for at least this many physics frames before being able to jump again; set to 0 to allow bunny hopping
    public int antiBunnyHopFactor = 1;

    private Vector3 moveDirection = Vector3.zero;
    private bool grounded = false;
    private bool swimming = false;
    private CharacterController controller;
    private Transform myTransform;
    private float speed;
    private RaycastHit hit;
    private float fallStartLevel;
    private bool falling;
    private float slideLimit;
    private float rayDistance;
    private Vector3 contactPoint;
    private bool playerControl = false;
    private int jumpTimer;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        myTransform = transform;
        speed = walkSpeed;
        rayDistance = controller.height * .5f + controller.radius;
        slideLimit = controller.slopeLimit - .1f;
        jumpTimer = antiBunnyHopFactor;
    }

    void FixedUpdate()
    {
        float inputX = Input.GetAxisRaw("Horizontal");
        float inputY = Input.GetAxisRaw("Vertical");
        // If both horizontal and vertical are used simultaneously, limit speed (if allowed), so the total doesn't exceed normal move speed
        float inputModifyFactor = (inputX != 0.0f && inputY != 0.0f && limitDiagonalSpeed) ? .7071f : 1.0f;

        if (grounded)
        {
            bool sliding = false;
            // See if surface immediately below should be slid down. We use this normally rather than a ControllerColliderHit point,
            // because that interferes with step climbing amongst other annoyances
            if (Physics.Raycast(myTransform.position, -Vector3.up, out hit, rayDistance))
            {
                if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
                    sliding = true;
            }
            // However, just raycasting straight down from the center can fail when on steep slopes
            // So if the above raycast didn't catch anything, raycast down from the stored ControllerColliderHit point instead
            else
            {
                Physics.Raycast(contactPoint + Vector3.up, -Vector3.up, out hit);
                if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
                    sliding = true;
            }

            // If we were falling, and we fell a vertical distance greater than the threshold, run a falling damage routine
            if (falling)
            {
                falling = false;
                if (myTransform.position.y < fallStartLevel - fallingDamageThreshold)
                    FallingDamageAlert(fallStartLevel - myTransform.position.y);
            }

            // If running isn't on a toggle, then use the appropriate speed depending on whether the run button is down


            // If sliding (and it's allowed), or if we're on an object tagged "Slide", get a vector pointing down the slope we're on
            if ((sliding && slideWhenOverSlopeLimit) || (slideOnTaggedObjects && hit.collider.tag == "Slide"))
            {
                Vector3 hitNormal = hit.normal;
                moveDirection = new Vector3(hitNormal.x, -hitNormal.y, hitNormal.z);
                Vector3.OrthoNormalize(ref hitNormal, ref moveDirection);
                moveDirection *= slideSpeed;
                playerControl = false;
            }
            // Otherwise recalculate moveDirection directly from axes, adding a bit of -y to avoid bumping down inclines
            else
            {
                moveDirection = new Vector3(inputX * inputModifyFactor, -antiBumpFactor, inputY * inputModifyFactor);
                moveDirection = myTransform.TransformDirection(moveDirection) * speed;
                playerControl = true;
            }

            // Jump! But only if the jump button has been released and player has been grounded for a given number of frames
            if (!Input.GetButton("Jump"))
                jumpTimer++;
            else if (jumpTimer >= antiBunnyHopFactor)
            {
                moveDirection.y = jumpSpeed;
                jumpTimer = 0;
            }
        }
        else
        {
            // If we stepped over a cliff or something, set the height at which we started falling
            if (!falling)
            {
                falling = true;
                fallStartLevel = myTransform.position.y;
            }

            // If air control is allowed, check movement but don't touch the y component
            if (airControl && playerControl)
            {
                moveDirection.x = inputX * speed * inputModifyFactor;
                moveDirection.z = inputY * speed * inputModifyFactor;
                moveDirection = myTransform.TransformDirection(moveDirection);
            }
        }

       
            moveDirection.y -= gravity * Time.deltaTime;
       
       

        if (swimming == true)
        {
            gravity = 0;
            grounded = false;
         
        }
        else if (swimming == false)
        {
            // Apply gravity
            gravity = 20.0f;
        }
       
        ///SWIMMING
        if (swimming)
        {
           
            if (Input.GetKey(KeyCode.W)) // if what ever button you have "Fire1" linked to in Edit>>Project Settings>>Input is held down, then move
            {
              
                controller.Move(moveDirection * Time.deltaTime);
                //This does the moving
            }

            if (Input.GetKey(KeyCode.S)) // if what ever button you have "Fire1" linked to in Edit>>Project Settings>>Input is held down, then move
            {
               
                controller.Move(moveDirection * Time.deltaTime);
                //This does the moving
            }

            if (Input.GetKey(KeyCode.A)) // if what ever button you have "Fire1" linked to in Edit>>Project Settings>>Input is held down, then move
            {
               
                controller.Move(moveDirection * Time.deltaTime);
                //This does the moving
            }

            if (Input.GetKey(KeyCode.D)) // if what ever button you have "Fire1" linked to in Edit>>Project Settings>>Input is held down, then move
            {
               
                controller.Move(moveDirection * Time.deltaTime);
                //This does the moving
            }

            if (Input.GetKey(KeyCode.Space)) // if what ever button you have "Fire1" linked to in Edit>>Project Settings>>Input is held down, then move
            {
               
                controller.Move(moveDirection * Time.deltaTime);
                //This does the moving
            }


        }

        // Move the controller, and set grounded true or false depending on whether we're standing on something
       if (!swimming) {
        grounded = (controller.Move(moveDirection * Time.deltaTime) & CollisionFlags.Below) != 0;
         }




    }



    // Store point that we're in contact with for use in FixedUpdate if needed
    void OnControllerColliderHit(ControllerColliderHit hit)
    {
        contactPoint = hit.point;
    }

    // If falling damage occured, this is the place to do something about it. You can make the player
    // have hitpoints and remove some of them based on the distance fallen, add sound effects, etc.
    void FallingDamageAlert(float fallDistance)
    {
        print("Ouch! Fell " + fallDistance + " units!");
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.name == "Cube")
        { if (swimming == false)
            {
                print("ENTER");
                swimming = true;
                moveDirection = Vector3.zero;
            }
        }
      
  

        }

    void OnTriggerExit(Collider other)
    {
        if (other.name == "Cube")
        { if (swimming == true)
            {
                print("EXIT");
                swimming = false;
            }
        }



    }

}

And here is the mouse look code:

using UnityEngine;
using System.Collections;

public class camMouseLook : MonoBehaviour
{
    public bool lockCursor = true;
    private bool m_cursorIsLocked = true;
    Vector2 mouseLook;
    Vector2 smoothV;
    public float sensitivity = 5.0f;
    public float smoothing = 2.0f;

    GameObject character;

    public void SetCursorLock(bool value)
    {
        lockCursor = value;
        if (!lockCursor)
        {//we force unlock the cursor if the user disable the cursor locking helper
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;
        }
    }


    void Start()
    {
        character = this.transform.parent.gameObject;
        Cursor.lockState = CursorLockMode.Locked;
    }

    void Update()
    {
       
        var md = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));

        md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
        smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
        smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
        mouseLook += smoothV;
        mouseLook.y = Mathf.Clamp(mouseLook.y, -90, 90);

        transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
        character.transform.localRotation = Quaternion.AngleAxis(mouseLook.x, character.transform.up);
    }
}

Please any help is appreciated!

I have managed to get the mouse look working but yet again I face another issue! When I touch an object in the war that I should slide when moving. I get slammed into the ground. Really really fast.

The code when swimming is the following:

 if (swimming)
        {
           
            if (Input.GetKey(KeyCode.W))             {

                transform.position = transform.position + Camera.main.transform.forward * distance * Time.deltaTime;
                controller.Move(moveDirection * Time.deltaTime);
               
            }
}

All I want is free moving in the water and the code above achieves that but if I collide with a solid object and press the forward button I will go down extremely quickly. If anyone is willing to help I will also post a clip of my issue.