逼真的 BOAT/SHIP 移动和旋转 (2d)
Realistic BOAT/SHIP movement and rotation (2d)
我想将我的船移动到我点击的位置,但要进行真实的移动和旋转:
(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;
}
}
}
经过一些研究和尝试,我没有找到一种方法来做我想做的事情。
感谢您的帮助
这个问题有两个部分,它们应该彼此完全分开,任何时候一个方程式都不会干扰另一个方程式。
首先是船的前移,可以通过两种方式实现:
如果你使用的是刚体
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));
注意事项:
这是伪代码,我还没有测试过其中的任何一个,所以只知道让它工作取决于你,我只是为你提供正确的路径。
方法开头的所有变量都是全局变量,所以在你喜欢的地方声明它们。
我在这里使用了一个名为 target 的 Transform,只需将其替换为鼠标单击的 Vector。
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 函数,并根据当前位置计算要在每一帧上查看的新向量。
如果您的船具有某种旋转速度统计数据,请修改名为 step 的浮点数以适应。如果他们有速度统计,则用一些乘数修改 transform.position += transform.forward * Time.deltaTime。
我猜你会想要设置一些条件来确定何时停止移动和旋转,也许使用协程。
声明
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 帮助我并花了很多时间试图找出解决方案。
我想将我的船移动到我点击的位置,但要进行真实的移动和旋转:
(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;
}
}
}
经过一些研究和尝试,我没有找到一种方法来做我想做的事情。
感谢您的帮助
这个问题有两个部分,它们应该彼此完全分开,任何时候一个方程式都不会干扰另一个方程式。
首先是船的前移,可以通过两种方式实现:
如果你使用的是刚体
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));
注意事项:
这是伪代码,我还没有测试过其中的任何一个,所以只知道让它工作取决于你,我只是为你提供正确的路径。
方法开头的所有变量都是全局变量,所以在你喜欢的地方声明它们。
我在这里使用了一个名为 target 的 Transform,只需将其替换为鼠标单击的 Vector。
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 函数,并根据当前位置计算要在每一帧上查看的新向量。
如果您的船具有某种旋转速度统计数据,请修改名为 step 的浮点数以适应。如果他们有速度统计,则用一些乘数修改 transform.position += transform.forward * Time.deltaTime。
我猜你会想要设置一些条件来确定何时停止移动和旋转,也许使用协程。
声明
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 帮助我并花了很多时间试图找出解决方案。