PLEASE HELP IVE BEEN TRYNA FIX FOR 2 DAYS NOW

Character jitters when swimming out of water from the top and i want it to exit smoothly like it does from the sides . Idk why please help here is all my code .

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{

    public CharacterController controller;

    public float speed = 12f;
    public float gravity = -9.0f;
    public float groundDistance = 0.4f;
    public float jumpHeight = 3f;

    public LayerMask groundMask;
    public LayerMask waterMask;

    public Transform groundCheck;
    public Transform waterCheck;

    Vector3 velocity;

    bool isGrounded;
    bool isSwimming;

    // Start is called before the first frame update
    void Start()
    {
      
    }

    // Update is called once per frame
    void Update()
    {
        isSwimming = Physics.CheckSphere(waterCheck.position, groundDistance, waterMask);

        if (isSwimming)
        {
            Swim();
        }
        else
        {
            Walk();
        }

        //----------------------------------------------\\

        void Swim()
        {
            #region isSwimming
            float x = Input.GetAxis("Horizontal");
            float z = Input.GetAxis("Vertical");

            Vector3 move = transform.right * x + transform.forward * z;

            controller.Move(move * speed * Time.deltaTime);
            #endregion
        }

        void Walk()
        {
            #region isNotSwimming
            isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

            if (isGrounded && velocity.y < 0)
            {
                // Set vertical velocity to zero
                velocity.y = 0f;
            }

            float x = Input.GetAxis("Horizontal");
            float z = Input.GetAxis("Vertical");

            Vector3 move = transform.right * x + transform.forward * z;

            // Move player as move * speed value * Time.deltaTime for fps increase / decrease
            controller.Move(move * speed * Time.deltaTime);

            if (Input.GetButton("Jump") && isGrounded)
            {
                // Velocity = Jump height - 2 * gravity (Jumping physics calculation)
                velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
            }

            velocity.y += gravity * Time.deltaTime;

            controller.Move(velocity * Time.deltaTime);

            #endregion
        }

    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseLookSwimming : MonoBehaviour
{

    public float mouseSensitivity = 100f;
    public float groundDistance = 0.4f;

    public Transform playerBody;
    public Transform waterCheck;

    public LayerMask waterMask;

    float xRotation = 0f;
    float yRotation = 0f;

    bool isSwimming;
    bool outOfWater;
    bool isInWater;


    // Start is called before the first frame update
    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
    }

    // Update is called once per frame
    void Update()
    {
        float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -90, 90);

        yRotation -= mouseX;

        isSwimming = Physics.CheckSphere(waterCheck.position, groundDistance, waterMask);

        if (isSwimming)
        {
            Swim();
        }
        else
        {
            Walk();
        }



        void Swim()
        {
            #region isSwimming

            if (isInWater)
            {
                playerBody.localRotation = Quaternion.Euler(0, -yRotation, 0);
                transform.localRotation = Quaternion.Euler(0, 0, 0); //
                isInWater = false;
            }


            //transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
            playerBody.localRotation = Quaternion.Euler(xRotation, -yRotation, 0f);
            outOfWater = true;
            #endregion
        }

        void Walk()
        {
            #region isNotSwimming

            if (outOfWater)
            {
                playerBody.localRotation = Quaternion.Euler(0, -yRotation, 0);
                transform.localRotation = Quaternion.Euler(xRotation,0,0);
                outOfWater = false;
            }



            transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
            playerBody.Rotate(0, mouseX, 0);

            isInWater = true;
            #endregion
        }

    }
}

I believe you are exiting the water, in which case gravity pulls on you, pulls you back into the water, where you give the command to float upwards again, leaving the water and so on. You can test that by putting a Debug.Log message into both your swim and walk methods. You should see them being called alternatingly.

In a lot of games you can actually build enough speed to “jump out of the water”, in which case you become airborn and should be pulled back through gravity. So this may as well be a feature.

If it is entirely unintended, but you like your controller otherwise, you could just get the uppermost part of the body of water at your current location and lock any upwards movement to that coordinate. Thus, you couldnt shoot out of the water anymore whatsoever, preventing this from happening. For a more sophisticated solution youd either need to balance forces, or make sure you only apply force while a relevant part of your body is inside the water (like the arms), and balance it in a way that you wont overshoot.

Also please dont use inline functions. Is there any reason for why you have your swim and walk functions inside of Update? That is usually bad practice and imho may as well not even exist in C#, for how often it is useful.

3 Likes