Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realistic BOAT/SHIP movement and rotation (2d)

Tags:

unity3d

2d

I want to move my boat to the position where i clicked BUT with a realistic movement and rotation :

enter image description here

(http://i.imgur.com/Pk8DOYP.gif)

Here is my code (attached to my boat gameobject) :

Basically, when i click somewhere, it move the boat until it reach the point that i clicked in the first place (i simplified my code for you)

using UnityEngine;
using System.Collections;


public class BoatMovement : MonoBehaviour {

    private Vector3 targetPosition;

    private float speed = 10f;
    private bool isMoving;


    void Update(){

        if (!isMoving && Input.GetMouseButton (0)) {

            targetPosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
            isMoving = true;
        } 


        if (isMoving) {
            moveToPosition ();
        }
    }

    void  moveToPosition() {


        transform.position = Vector3.MoveTowards (transform.position, new Vector3(targetPosition.x, targetPosition.y, 0f), speed * Time.deltaTime);

        if (transform.position.x == targetPosition.x && transform.position.y == targetPosition.y) {
            isMoving = false;
        }

    }
}

After some research and tries, i didn't find a way to do what i want.

Thanks for your help

like image 607
Owow Avatar asked Nov 08 '22 03:11

Owow


1 Answers

There's two parts to this problem, which should be kept completely separate from each other and at no time does the equation of one interfere with the equation of the other.

The first is the forward movement of the ship, which can be achieved in two ways:

If you are using a rigidbody

void Propel()
{
    float speed = 150f;
    RigidBody rb = GetComponent<RigidBody>();
    Transform transform = GetComponent<Transform>();
    rb.AddForce(transform.forward * speed * Time.deltaTime); // <--- I always forget if its better to use transform.forward or Vector3.forward. Try both
}

If no rigidbody

void Propel()
{
    float speed = 150f;
    Transform transform = GetComponent<Transform>();
    transform.Translate(transform.forward * speed * Time.deltaTime, Space.World);
}

Now the second would be the turning of the ship, which also can be achieved in two ways:

With rigidbody

IEnumerator TurnShip(Vector3 endAngle)
{
    float threshold = Single.Epsilon;
    float turnSpeed = 150f;
    RigidBody rb = GetComponent<RigidBody>();
    while (Vecotr3.Angle(transform.forward, endAngle) > threshold)
    {
        rb.AddTorque(transform.up * turnSpeed * Time.deltaTime);
        yield return null;
    }
}

Without rigidbody

IEnumerator TurnShip(Vector3 endAngle)
{
    float threshold = Single.Epsilon;
    float turnSpeed = 150f;
    float step = turnSpeed * Time.deltaTime;
    while (Vector3.Angle(transform.forward, endAngle) > threshold)
    {
        newDir = Vector3.RotateTowards(transform.forward, endAngle, step);
        transform.rotation = Quaternion.LookRotation(newDir);
        yield return null;
    }
}

Then of course, the IEnumerators are called like so:

StartCoroutine(TurnShip(new Vector3(12f, 1f, 23f));

Couple things to note:

  1. This is pseudo code, i haven't tested any of it so just know that making it work is up to you, i'm only providing you with the correct path to follow.

  2. All the variables in the beginnings of the methods are meant to be global variables, so declare them where you please.

like image 114
maksymiuk Avatar answered Dec 10 '22 03:12

maksymiuk