# Simulate the player floating in the water

I am creating my first game in Unity and now I have a problem.

I created a waterpool (a blue quad) and I want to simulate the floating of the player, so when the player is in the water, its Y position would be equal to that of water.

I think a picture is clearer: the water is blue, the player is blue.

I tried to do it this way but it does not work:

public float myYpos;

void OnTriggerEnter(Collider other) {
if(other.tag == "Water") {
walkSpeed = walkSpeed - deltaWaterSpeed;
jumpHeight = jumpHeight - deltaWaterJump;

// DOESN'T WORK
//myYpos = transform.position.y;
//myYpos = myYpos + 1;
//transform.position = new Vector3(transform.position.x, myYpos, transform.position.z);
}
}


This is a gif of my game:

I also do not know why sometimes the player is hidden in the water (I see only water), why?

Thanks to anyone who wants to help me.

Thanks for the answers. It is a 2D game but I stupidly followed a tutorial for 3D and so now I go ahead with 3D.

I dont' have a rigidBody on the Player. I added the OnTriggerStay as recommended but the result is this:

   void OnTriggerStay(Collider other) {
if(transform.position.y < other.transform.position.y) {
transform.position = new Vector3(transform.position.x, other.transform.position.y, transform.position.z);
}
}


I deleted the OnTriggerEnter() and OnTriggerExit() methods.

Why the player jumps up and down? Why it doesn't float (a few mm below the surface), but quite a bit below?

Ok, now actually it does what it should have done, but I realized that was not what I wanted.

It behaves in this way:

The water quad has Y position = 8 and when the player is inside water its Y position is rightly 8. However, this generates this first effect while I prefer the second: the player is on the surface or nearly so, regardless of the height of the water.

How can I get this?

I know I have asked one thing and I got the correct answer but only now I realized that I didn't know what I wanted. Sorry...

In any case, why the player does not jump in the water? It jumps only if it is attached to a gray wall. If it is in the water it doesn't jump but parameters for the jump are setup...

Your code doesn't work because you use OnTriggerEnter, which is only called once. If you want to call a function for as long as the collider is in the trigger zone you should use OnTriggerStay

PS: You should not change the position of the blue box directly but manipulate Rigidbody.velocity or use Rigidbody.AddForce to move it, otherwise the box may "teleport" inside other objects and cause odd behaviour.

PS2: You seem to be creating a 2D game. Are you using the 2D or the 3D physics components? If you are using the 2D components, you should use OnTriggerStay2D.

EDIT: I don't quite understand the third part of your question, but your second problem is exactly why you should not modify the transform directly. The problem you have now is that your box moves down and is "teleported" back up, but it keeps it downwards velocity. It's downwards velocity is also increasing due to gravity, which causes this odd behaviour. To fix this, you should use Rigidbody.AddForce (or manipulate Rigidbody.velocity) instead.

eg:

void OnTriggerStay(Collider col){
// 'rigid' is the Rigidbody component.
}


or

void OnTriggerStay(Collider col){
rigid.velocity = Vector3.up;
}

– beth
Commented Apr 19, 2017 at 15:30
• Have you made any progress? Commented Apr 22, 2017 at 19:32
• No, I don't understand what I have to do and I feel a little stupid...
– beth
Commented Apr 22, 2017 at 19:37
• I added two examples. Tell me if it works and/or if you understand how it works. Commented Apr 22, 2017 at 19:59
• Hi, thanks. I added the rigidbody to the player and the code you wrote but when I walk into the water nothing happens, the player's behavior doesn't change
– beth
Commented Apr 24, 2017 at 9:46

Simply variant if you have RigidBody2D on player

this variant also can modify for RigidBody

private void OnTriggerStay2D(Collider2D collision)
{
if(other.tag == "Water") {
if (transform.position.y < collision.transform.position.y)
{
GetComponent<Rigidbody2D>()
transform.position.y - Physics2D.gravity.y));
}
}
}


You can replace

collision.transform.position.y - transform.position.y


On

(collision.transform.position.y - transform.position.y)*floatspeed;


and change speed of floating (floatspeed)

if you don't usee RigidBody for fixation y in OnTriggerStay2D:

if (transform.position.y < collision.transform.position.y){
transform.position(new Vector3(transform.position.x, collision.transform.position.y));
}


Also you can modify this script to floating player.

For fix twitching: Use bool for check if player and water and run this script in LateUpdate if player in water:

Declaration

bool inWater;
float waterSurface;//y coordinate of water surface


OnTriggerEnter()

if(other.tag == "Water") {
inWater = true;//player in water
waterSurface = other.transform.position.y;//set y coord of water surface as center of water
//you also can get Rect rect of the water sprite for find y coord of water surface
}


OnTriggerExit()

if(other.tag == "Water") {
inWater = false;
}


LateUpdate()

if(inWater){
//script for change position in water
}


script for change position in water may be different:

so when the player is in the water, its Y position would be equal to that of water.

if (transform.position.y < waterSurface){
transform.position(new Vector3(transform.position.x,waterSurface));
}