如何使对象在指定位置精确地寻找和减速到停止

本文关键字:寻找 对象 何使 定位 位置 | 更新日期: 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。然后用数学加速到一半,然后减速。