Swimming and RigidBody Problem! Big Script but need help with one part!

In my water script, space is to float up, and Q is the float down. I also limit movement speed so it portrays water conditions. The problem is when i float to the surface of the water, if i move a certain way, my characters swims out of the water into the air. So to fix this, i made a variable where if he is at the surface, it locks his y position so he stays on the surface until the player presses Q to go underwater. The problem is that when i press Q again. The y constraint on the rigid body goes haywire and launches me into the air. I dont know why this happens! Please help!

I have a underwater variable and and inwater variable, inWater means i am on the surface of the water.

Scroll down to where it says: if(inWater)

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class MovementStamina : MonoBehaviour
{
    CharacterMotor chMotor;
    CharacterController controller;

    bool canJump = false;
    float jumpTimer = 1f;

    public Image staminaBar;
    GameObject StaminaStamina;
    staminaGUI staminaInfo;

    public bool inWater = true;
    underwater water;
    GameObject fps;
    GameObject fps1;
    ConstantForce force;
    MovementStamina movementstamina;

    private bool locked = false;

   
    // Use this for initialization
    void Start ()
    {
        chMotor = this.GetComponent<CharacterMotor> ();
        controller = this.GetComponent<CharacterController>();

        StaminaStamina = GameObject.Find ("StaminaStamina");      
        staminaInfo = StaminaStamina.GetComponent<staminaGUI> ();

        fps = GameObject.Find ("Main Camera");
        water = fps.GetComponent<underwater> ();

        fps1 = GameObject.Find ("First Person Controller");

    }
   
    // Update is called once per frame
    void Update ()
    {

        RaycastHit hit;   
        Vector3 down = transform.TransformDirection(Vector3.down);



    if(!water.isUnderwater )
    {
            inWater = false;

           
            if(Physics.Raycast(transform.position, down, out hit,6))
            {
                if(hit.collider.gameObject.tag == "water")
                {
   
                    inWater = true;
                    chMotor.jumping.enabled = false;
                   
                }
               
            }


        if(controller.velocity.magnitude > 0 && Input.GetKey(KeyCode.LeftShift))
        {
            chMotor.movement.maxForwardSpeed = 10;
            chMotor.movement.maxSidewaysSpeed = 10;
            staminaInfo.staminaBar.fillAmount -= 0.001f;

        }
       
        else
        {
            chMotor.movement.maxForwardSpeed = 6;
            chMotor.movement.maxSidewaysSpeed = 6;
        }


        if (Input.GetKeyDown(KeyCode.Space) && canJump == true)
        {
            staminaInfo.staminaBar.fillAmount -= 0.09f;
            StartCoroutine ("MyMethod");

        }

        if(canJump == false)
        {
            jumpTimer -= Time.deltaTime;
            chMotor.jumping.enabled = false;
        }
       
        if(jumpTimer <= 0)
        {

            canJump = true;
            chMotor.jumping.enabled = true;
            jumpTimer = 1f;

        }
        if(staminaInfo.staminaBar.fillAmount < 0.1f)
        {
            canJump = false;
            chMotor.jumping.enabled = false;
            chMotor.movement.maxForwardSpeed = 6;
            chMotor.movement.maxSidewaysSpeed = 6;
        }

    }
        else
        {
            inWater = true;

            //rigidbody.isKinematic = false;
            chMotor.movement.gravity = 2;

            chMotor.movement.maxFallSpeed = 4;
            chMotor.movement.maxForwardSpeed = 4;
            chMotor.movement.maxSidewaysSpeed = 4;
            chMotor.movement.maxBackwardsSpeed = 4;

            if(controller.velocity.magnitude > 0 && Input.GetKey(KeyCode.LeftShift))
                {
                chMotor.movement.maxForwardSpeed = 7;
                chMotor.movement.maxSidewaysSpeed = 7;
                staminaInfo.staminaBar.fillAmount -= 0.001f;
                }
                else
                {
                    chMotor.movement.maxForwardSpeed = 4;
                    chMotor.movement.maxSidewaysSpeed = 4;
                }
        }

        if(inWater == true)
        {
            Debug.Log (locked);
            chMotor.jumping.enabled = false;

            if(Input.GetKey("q"))
            {
                locked = false;
                rigidbody.constraints &= ~RigidbodyConstraints.FreezePositionY;
                transform.position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
                rigidbody.AddForce(Vector3.down * 5, ForceMode.VelocityChange);
               
                if(Physics.Raycast(transform.position, down, out hit,3))
                {
                    if(hit.collider.gameObject.tag == "ground")
                    {
                        rigidbody.isKinematic = true;
                    }
                   
                }
            }
            else
            {
                rigidbody.isKinematic = false;   
            }

       
            if(transform.position.y < 45.6)
            {
                if(Input.GetKey("space"))
                {
                rigidbody.AddForce(Vector3.up * 5, ForceMode.VelocityChange);
                }
            }

            if(!locked && transform.position.y > 45.6)
            {
                locked = true;
            }

            if(locked)
            {
                rigidbody.constraints = RigidbodyConstraints.FreezePositionY;
                transform.position = new Vector3(transform.position.x, 45.6f, transform.position.z);

            }



               

        }
    }   
           

    IEnumerator MyMethod() {

        yield return new WaitForSeconds(.05f);
        canJump = false;

        chMotor.jumping.enabled = false;
    }
    
}

Too complicated to debug like this.

What you need is a state machine that changes the way that movement is handled entirely based on the current state. The states could be “swimming”, “floating”, and “walking” in this case. When you’re swimming, control is passed off to some WhileSwimming function and the rest doesn’t get used at all. When floating (on surface of water), it’s all handled by WhileFloating. Using this, it would be much easier to narrow down your issue, and you wouldn’t be so tempted to re-use physics for multiple states, each would have their own control and their own responses to those controls, and you could set up ChangeState conditions for switching between one state and another.

1 Like

I see what you are saying thank you! That way will make the code nicer and simpler to read :slight_smile: