现实的船/船运动和旋转(2d)

时间:2017-01-10 19:05:19

标签: unity3d 2d unity5

我想把我的船移到我点击的位置但是有一个逼真的动作和旋转:

enter image description here

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

这是我的代码(附在我的游戏对象上):

基本上,当我点击某个地方时,它会移动船,直到它到达我点击的位置(我简化了我的代码)

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;
        }

    }
}

经过一番研究和尝试后,我找不到办法做我想做的事。

感谢您的帮助

3 个答案:

答案 0 :(得分:1)

这个问题有两个部分,应该保持彼此完全分离,并且一个方程式在任何时候都不会干扰另一个方程式。

首先是船的向前运动,可以通过两种方式实现:

如果您使用的是刚体

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
}

如果没有僵尸

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

现在第二个是船的转弯,这也可以通过两种方式实现:

使用刚体

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;
    }
}

没有刚体

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;
    }
}

然后,当然,IEnumerators被调用如下:

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

需要注意的事项:

  1. 这是伪代码,我还没有测试过它,所以只知道让它工作取决于你,我只是为你提供了正确的路径。

  2. 方法开头的所有变量都是全局变量,因此请在适当的地方声明。

答案 1 :(得分:0)

我在这里使用了一个名为target的Transform,只需用鼠标点击向量替换它。

public Transform target;

private void Update()
{

    transform.position += transform.forward * Time.deltaTime;
    Vector3 targetDir = target.position - transform.position;
    float step = Time.deltaTime / Mathf.PI;
    Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 0.0f);
    transform.rotation = Quaternion.LookRotation(newDir);

}

关键是RotateTowards函数并根据当前位置计算每个帧上的新向量。

如果您的船具有某种旋转速度属性,则修改称为步骤的浮动以适应。如果他们有速度属性,那么用一些乘数修改transform.position + = transform.forward * Time.deltaTime。

我想你会想要在什么时候停止运动和旋转,或者使用一个协程。

答案 2 :(得分:0)

声明

    private Vector3 targetPosition;
    private float targetDistance;

然后在移动开始时,执行:

    targetPosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
    targetDistance = Vector3.Distance(targetPosition, transform.position);

移动时调用:(例如在更新循环中)

    turnSpeed = 0.062f * targetDistance;
    moveSpeed = 35f * targetDistance;

    //Important /!\ : you need to add Linear drag on your rigidbody or it will keep adding
    RigidBody.AddForce(transform.up * moveSpeed * Time.deltaTime); 

    var newRotation = Quaternion.LookRotation (transform.position - targetPosition, Vector3.forward);
    newRotation.x = 0f;
    newRotation.y = 0f;
    transform.rotation = Quaternion.Slerp (transform.rotation, newRotation, Time.deltaTime * turnSpeed);

最后,向刚体添加一个线性拖动值(1可以)。

感谢maksymiuk帮助我,并花了很多时间试图找到解决方案。