3rd person swimming control system

OK This is a very basic & simple car driving & steering script I don’t remember where I got it but it works great for what it is & I like how it handles when used to swim on top of water…I call it SwimControl

var speed : float = 10.0;
var rotationSpeed : float = 20.0;

function Update () {
// Get the horizontal and vertical axis.
// By default they are mapped to the arrow keys.
// The value is in the range -1 to 1
var translation : float = Input.GetAxis (“Vertical”) * speed;
var rotation : float = Input.GetAxis (“Horizontal”) * rotationSpeed;

// Make it move 10 meters per second instead of 10 meters per frame…
translation *= Time.deltaTime;
rotation *= Time.deltaTime;

// Move translation along the object’s z-axis
transform.Translate (-0, 0, translation);
// Rotate around our y-axis
transform.Rotate (0, rotation, 0);
}


This is the very simple basic buoyancy script im using to float the player…I call it SwimFloat

public var force: float;
var rb: Rigidbody;
public var water: GameObject;
private var Player : GameObject;

function Update () {

Player = gameObject;
rb = GameObject.FindWithTag(“HitBox”).GetComponent(Rigidbody);
if(transform.position.y < water.transform.position.y)
rb.AddForce(transform.up * force * 10);

if(transform.position.y > water.transform.position.y)
rb.AddForce(-transform.up * force * 08);
}

I got it from a youtube tutorial , it works but it takes alittle tweaking with the numbers to get whatever object you want to float to float just right__.__


This is the script I use to tell all the control scripts when to turn off/on … I call it PlayerSwimCommand

private var Anim : Animation;
private var Player : GameObject;
private var TPC : ThirdPersonController;
private var CC : CharacterController;
private var SC : SwimControl;
private var Swim : SwimFloat;

function Update () {

Player = gameObject;
TPC = gameObject.GetComponent(ThirdPersonController);
CC = gameObject.GetComponent(CharacterController);
SC = gameObject.GetComponent(SwimControl);
Swim = gameObject.GetComponent(SwimFloat);
Anim = gameObject.GetComponent(Animation);
}
function OnTriggerEnter(collider : Collider) {

if(collider.gameObject.tag == “Water”)
Anim.Play(“PlayerSwim”);
if(collider.gameObject.tag == “Water”)
CC.enabled = false;
if(collider.gameObject.tag == “Water”)
TPC.enabled = false;
if(collider.gameObject.tag == “Water”)
Swim.enabled = true;
if(collider.gameObject.tag == “Water”)
SC.enabled = true;
}

This script also works fine no problems…


I have the player set up like with the 3rd Person Controller, Character Controller & Third Person Camera script that comes with unity. All 3 of those scripts are turned on , PlayerSwimCommand is turned on, SwimFloat & Swimcontrol are unchecked to be off at the enter of “Game Mode”. I have a " Hitbox " attached to the player for other actions. The hitbox is just an empty game object attached as a child to a bone in the players armature. This "hitbox " is tagged “Hitbox” it has a box collider & a rigidbody attached in its components but it doesn’t interfere withh the character controller because its on a different layer and it remains unactive untill a certain “buttun press” occurs. I dont want to change anything with the “hitbox” and everything includeing the 3 scripts above work fine. You can control the 3rd person playerno probs on land and then as soon as you enter the water 3rd person controller & character controller turn off & at the same time SwimFloat & SwimControl turn on and the player is now floating and swimming on top of the water. The 3rd person camera stays on and everything works fine untill you try to get out of the water and you swim right through the shore! I cant figure out how to do the reverse for all of this so the control scripts will switch back and the player willl be back to the normal 3rd person controls on land. can anyone help me complete this very simple basic 3rd person swimming control system and keep it real simple and basic ?
I am still fairly new to scripting and not that good at it.

please use [code ][/code ] tags when you paste code into the forums, really helps with readability… there is a sticky on them at the top of the scripting forum.

you can use {} after an if to control many lines:

if(collider.gameObject.tag == "Water")
{
   Anim.Play("PlayerSwim");
   CC.enabled = false;
   TPC.enabled = false;
   Swim.enabled = true;
   SC.enabled = true;
}

personally if you aren’t going to use the {} I would suggest putting it into one line to avoid mistakes, i.e.

if(collider.gameObject.tag == "Water") Anim.Play("PlayerSwim");

// rather than
if(collider.gameObject.tag == "Water")
Anim.Play("PlayerSwim");

that’s personal preference although I’ve seen plenty of people asking about errors which boil down to thinking two lines are controlled when not using {} :stuck_out_tongue:

if you want to switch again when the user leaves the collider I think you could just use OnTriggerExit

function OnTriggerExit(collider : Collider)
{
   if(collider.gameObject.tag == "Water")
   {
     Anim.Play("PlayerSwim");
     CC.enabled = true;
     TPC.enabled = true;
     Swim.enabled = false;
     SC.enabled = false;
   }
}

(I just copied the enter and flipped the booleans, use whichever on/off combination you need)

That doesn’t work. That is one of many things I have tried but I just tried it again real quick just to make sure.The character controller is turned off so the player never detects the ground to be able to lift out of the collision with the water so there is no trigger exit the player just swims through the shore…I didn’t know about the code tags I’ll use them from here out.

ah ok… how have you done the water collider? is it just a box collider the size of the play area that goes under/through everything?

two options spring to mind.

Altering the swimming controller script to detect “shore” and handle that.
Alter the “water” collider so it only represents the body of water so it can be exited.

yea I forgot to mention I do have a rigidbody set as a trigger and a box collider stretched to the size and shape of the water placed just under its surface in the components of the water. I can’t alter the the shape of the water collider because the body of water isn’t even close to the shape of a square, rectangle or circle. So that leaves detecting shore somehow…

I just figured it out

private var Player : GameObject;
private var TPC : ThirdPersonController;
private var CC : CharacterController;
private var SC : SwimControl;
private var Swim : SwimFloat;
private var WC : Collider;


function Update () {
Player = GameObject.FindWithTag("Player");

TPC = Player.GetComponent(ThirdPersonController);
CC = Player.GetComponent(CharacterController);
SC = Player.GetComponent(SwimControl);
Swim = Player.GetComponent(SwimFloat);
WC = gameObject.GetComponent(BoxCollider);
}

function OnTriggerEnter(collider : Collider) {
   if(collider.gameObject.tag == "Ground")
      WC.enabled = false;
      CC.enabled = true;
      TPC.enabled = true;
      Swim.enabled = false;
      SC.enabled = false;
}

I created another empty gameObject called & tagged Waterbox. I added a box collider & rigidboby to it and made the “waterbox” child of the player with the collider unchecked to be off. Then I wrote that script and attached it to the waterbox. I added the WC reference to the PlayerSwimCommand. I tagged the terrain as "Ground " and put it and the WaterBox on a layer called “Ground” and it worked!

1 Like

Here are the scripts updated for anyone that wants to use them…
I call this one DetectShore…

Attach to and empty gameobject with a rigidbody and a box collider resized to be bigger than your player. Tag the empty gameobject as “WaterBox” and put it on a layer called “Ground” . Change the terrains layer to ground as welll and then make the waterbox gameobject a child of the player

private var Player : GameObject;
private var TPC : ThirdPersonController;
private var CC : CharacterController;
private var SC : SwimControl;
private var Swim : SwimFloat;
private var WC : Collider;


function Update () {
Player = GameObject.FindWithTag("Player");

TPC = Player.GetComponent(ThirdPersonController);
CC = Player.GetComponent(CharacterController);
SC = Player.GetComponent(SwimControl);
Swim = Player.GetComponent(SwimFloat);
WC = gameObject.GetComponent(BoxCollider);
}

function OnTriggerEnter(collider : Collider) {
   if(collider.gameObject.tag == "Ground")
      WC.enabled = false;
      CC.enabled = true;
      TPC.enabled = true;
      Swim.enabled = false;
      SC.enabled = false;
}

I call this script SwimControl…
It is a simple car steering script I use as the swimming controls for swimming on top of the water. Attach this to the player unchecked to be off at start of gamemode.

var speed : float = 10.0;
    var rotationSpeed : float = 20.0;

    function Update () {
        // Get the horizontal and vertical axis.
        // By default they are mapped to the arrow keys.
        // The value is in the range -1 to 1
        var translation : float = Input.GetAxis ("Vertical") * speed;
        var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
     
        // Make it move 10 meters per second instead of 10 meters per frame...
        translation *= Time.deltaTime;
        rotation *= Time.deltaTime;
     
        // Move translation along the object's z-axis
        transform.Translate (-0, 0, translation);
        // Rotate around our y-axis
        transform.Rotate (0, rotation, 0);
    }

I call this one SwimFloat…
This script is the buoyancy script that makes the player float. Attach this to the player unchecked to be off at start of gamemode.

public var force: float;
var rb: Rigidbody;
public var water: GameObject;
private var Player : GameObject;

function Update () {

  

    Player = gameObject;
    rb = GameObject.FindWithTag("BiteBox").GetComponent(Rigidbody);
    if(transform.position.y < water.transform.position.y)
       rb.AddForce(transform.up * force * 10);

    if(transform.position.y > water.transform.position.y)
       rb.AddForce(-transform.up * force * 08);

}

I call this one PlayerSwimCommand…
It gives orders to all the components that apply when to turn on/off. It tell the player when he enters the water to change from 3rd person character controller to swiming on top of the water controls.

private var Anim : Animation;
private var Player : GameObject;
private var TPC : ThirdPersonController;
private var CC : CharacterController;
private var SC : SwimControl;
private var Swim : SwimFloat;
private var WC : BoxCollider;

function Update () {

Player = gameObject;
TPC = gameObject.GetComponent(ThirdPersonController);
CC = gameObject.GetComponent(CharacterController);
SC = gameObject.GetComponent(SwimControl);
Swim = gameObject.GetComponent(SwimFloat);
Anim = gameObject.GetComponent(Animation);
WC = GameObject.FindWithTag("WaterBox").GetComponent(BoxCollider);
}
function OnTriggerEnter(collider : Collider) {

   if(collider.gameObject.tag == "Water")
      Anim.Play("PlayerSwim");
      CC.enabled = false;
      TPC.enabled = false;
      Swim.enabled = true;
      SC.enabled = true;
      WC.enabled = true;
}

If they are all attached and set up right you should be able to attach these to any player that has the basic 3rd person character control set up already applied and the player will be able to run into the water, automatically start swimming on top of it and the go back to wlking or running when it reaches the shore.__ __

1 Like