如何使对象在指定位置精确地寻找和减速到停止
本文关键字:寻找 对象 何使 定位 位置 | 更新日期: 2023-09-27 18:36:17
简介
我目前正在尝试创建一个脚本(Unity 中的 C# 脚本),用于控制游戏对象的指向和单击行为。
从本质上讲,玩家最终将通过简单地单击屏幕来控制热气球,对象将开始加速并向单击位置移动。当在点击位置的特定距离处时,热气球应开始向相反方向加速(从而减速),并正好在点击位置完全停止。
我已经创建了一个功能齐全且带有注释的脚本(位于本文底部),它只是以恒定的速度将游戏对象移动到单击位置,然后在特定距离内开始减速,直到停止在该点。
我还创建了一个单独且功能齐全的脚本,该脚本在加速时向点击位置移动(获得那种小行星推力行为)。这也可以在帖子底部找到。
问题所在
现在我面临的问题是,我已经工作了很长时间,以找到一个解决方案,您可以将这两种行为实现为一个工作脚本,也就是说,热气球具有加速行为,同时还减速并停止在目标位置,就像这里发现的这个视觉示例一样:
视觉到达行为演示
问题
然后我的问题变成了:
如何不仅使用恒定速度,而且在等式中包含加速度的情况下使到达行为?我试图研究这个问题,并尝试我自己的解决方案,但我所做的一切似乎都没有按照应有的方式工作。
脚本附件
以恒定速度进行指向和点击移动,具有到达行为
using UnityEngine;
using System.Collections;
public class PlayerControl : MonoBehaviour
{
// Fields
Transform cachedTransform;
Vector3 currentMovementVector;
Vector3 lastMovementVector;
Vector3 currentPointToMoveTo;
Vector3 velocity;
int movementSpeed;
Vector3 clickScreenPosition;
Vector3 clickWorldPosition;
float slowingDistance = 8.0f;
Vector3 desiredVelocity;
float maxSpeed = 1000.0f;
// Use this for initialization
void Start ()
{
cachedTransform = transform;
currentMovementVector = new Vector3(0, 0);
movementSpeed = 50;
currentPointToMoveTo = new Vector3(0, 0);
velocity = new Vector3(0, 0, 0);
}
// Update is called once per frame
void Update ()
{
// Retrive left click input
if (Input.GetMouseButtonDown(0))
{
// Retrive the click of the mouse in the game world
clickScreenPosition = Input.mousePosition;
clickWorldPosition = Camera.main.ScreenToWorldPoint(new Vector3(clickScreenPosition.x, clickScreenPosition.y, 0));
currentPointToMoveTo = clickWorldPosition;
currentPointToMoveTo.z = 0;
// Calculate the current vector between the player position and the click
Vector3 currentPlayerPosition = cachedTransform.position;
// Find the angle (in radians) between the two positions (player position and click position)
float angle = Mathf.Atan2(clickWorldPosition.y - currentPlayerPosition.y, clickWorldPosition.x - currentPlayerPosition.x);
// Find the distance between the two points
float distance = Vector3.Distance(currentPlayerPosition, clickWorldPosition);
// Calculate the components of the new movemevent vector
float xComponent = Mathf.Cos(angle) * distance;
float yComponent = Mathf.Sin(angle) * distance;
// Create the new movement vector
Vector3 newMovementVector = new Vector3(xComponent, yComponent, 0);
newMovementVector.Normalize();
currentMovementVector = newMovementVector;
}
float distanceToEndPoint = Vector3.Distance(cachedTransform.position, currentPointToMoveTo);
Vector3 desiredVelocity = currentPointToMoveTo - cachedTransform.position;
desiredVelocity.Normalize();
if (distanceToEndPoint < slowingDistance)
{
desiredVelocity *= movementSpeed * distanceToEndPoint/slowingDistance;
}
else
{
desiredVelocity *= movementSpeed;
}
Vector3 force = (desiredVelocity - currentMovementVector);
currentMovementVector += force;
cachedTransform.position += currentMovementVector * Time.deltaTime;
}
}
使用加速但无到达行为的指向和单击移动
using UnityEngine;
using System.Collections;
public class SimpleAcceleration : MonoBehaviour
{
Vector3 velocity;
Vector3 currentMovementVector;
Vector3 clickScreenPosition;
Vector3 clickWorldPosition;
Vector3 currentPointToMoveTo;
Transform cachedTransform;
float maxSpeed;
// Use this for initialization
void Start ()
{
velocity = Vector3.zero;
currentMovementVector = Vector3.zero;
cachedTransform = transform;
maxSpeed = 100.0f;
}
// Update is called once per frame
void Update ()
{
// Retrive left click input
if (Input.GetMouseButtonDown(0))
{
// Retrive the click of the mouse in the game world
clickScreenPosition = Input.mousePosition;
clickWorldPosition = Camera.main.ScreenToWorldPoint(new Vector3(clickScreenPosition.x, clickScreenPosition.y, 0));
currentPointToMoveTo = clickWorldPosition;
// Reset the z position of the clicking point to 0
currentPointToMoveTo.z = 0;
// Calculate the current vector between the player position and the click
Vector3 currentPlayerPosition = cachedTransform.position;
// Find the angle (in radians) between the two positions (player position and click position)
float angle = Mathf.Atan2(clickWorldPosition.y - currentPlayerPosition.y, clickWorldPosition.x - currentPlayerPosition.x);
// Find the distance between the two points
float distance = Vector3.Distance(currentPlayerPosition, clickWorldPosition);
// Calculate the components of the new movemevent vector
float xComponent = Mathf.Cos(angle) * distance;
float yComponent = Mathf.Sin(angle) * distance;
// Create the new movement vector
Vector3 newMovementVector = new Vector3(xComponent, yComponent, 0);
newMovementVector.Normalize();
currentMovementVector = newMovementVector;
}
// Calculate velocity
velocity += currentMovementVector * 2.0f * Time.deltaTime;
// If the velocity is above the allowed limit, normalize it and keep it at a constant max speed when moving (instead of uniformly accelerating)
if (velocity.magnitude >= (maxSpeed * Time.deltaTime))
{
velocity.Normalize();
velocity *= maxSpeed * Time.deltaTime;
}
// Apply velocity to gameobject position
cachedTransform.position += velocity;
}
}
改编第一个脚本:
引入变量velocity
,如第二个脚本所示。在 Start()
中将其设置为等于 movementSpeed
,之后不要使用movementSpeed
。在完美运行之前不要继续。
现在介绍加速:
if (distanceToEndPoint < slowingDistance)
{
velocity *= distanceToEndPoint/slowingDistance;
}
else
{
velocity += direction * 2.0f * Time.deltaTime;
}
根据您希望运动的显示方式,您需要恒定速度方程或这些方程。恒定速度会更容易。
例如:您可以将起点和目的地之间的距离除以 2。然后用数学加速到一半,然后减速。