3

介绍

我目前正在尝试创建一个脚本(Unity 中的 C# 脚本)来控制 GameObject 的指向和单击行为。

从本质上讲,玩家最终将通过简单地点击屏幕来控制热气球,由此对象将开始加速并朝着点击位置移动。当在点击位置的特定距离处,热气球应该开始向相反方向加速(因此减速)并完全停止在点击位置。

我已经创建了一个功能齐全的注释脚本(在这篇文章的底部找到),它只是将一个游戏对象以恒定的速度移动到点击的位置,然后,当在特定距离内时,它开始减速直到停在该点。

我还创建了一个单独且功能齐全的脚本,该脚本在加速时向点击位置移动(获得那种小行星推力行为)。这也可以在帖子底部找到。

问题

现在我面临的问题是我已经工作了很长时间来找到一个解决方案,您可以将这两种行为作为一个工作脚本来实现,即热气球具有加速行为,而还减速并停在目标位置,就像在这里找到的这个视觉示例一样:

视觉到达行为演示

问题

然后我的问题变成:

你如何才能使到达行为不仅使用恒定速度,而且还包括方程中的加速度?我试图研究这个问题并尝试自己的解决方案,但我所做的一切似乎都没有按照应有的方式工作。

脚本附件

具有到达行为的恒定速度的指向和单击移动

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

2 回答 2

3

根据您希望运动出现的方式,您可能需要等速方程这些方程。恒速会更容易。

例如:您可以将起点和终点之间的距离除以 2。然后使用数学计算中途加速,然后减速。

于 2012-06-04T19:00:14.977 回答
3

改编第一个脚本:

velocity像第二个脚本一样引入一个变量。将其设置为movementSpeedin Start(),之后不要使用movementSpeed在完美运行之前不要继续。

现在介绍加速度:

if (distanceToEndPoint < slowingDistance)
{
   velocity *= distanceToEndPoint/slowingDistance;
}
else
{
   velocity += direction * 2.0f * Time.deltaTime;
}
于 2012-06-04T21:11:51.047 回答