在Unity中动态更改对象的速度 [英] Dynamically changing speed of object in Unity

查看:796
本文介绍了在Unity中动态更改对象的速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个根据动态时序上下移动的对象.确切的位置存储在称为Timings的List()中.这将包含排序的条目,例如0.90 1.895 2.64 3.98 ...这些时间与音乐的播放有关,因此可以将它们与TheMusic.time进行比较. (TheMusic是我的AudioSource).

I need an object to move up and down according to a dynamic timing. The exact locations are stored in a List() called Timings. This will contain sorted entries such as 0.90 1.895 2.64 3.98... These timings are relative the playing of music, so they can be compared to TheMusic.time. (TheMusic is my AudioSource).

现在(请参见下面的代码),它使用moveSpeed静态地上下移动.我如何做到这一点,以便可以在预定义的时间到达最高点和最低点?当到达计时列表的末尾时,运动应停止.

Right now (see code below), it's moving statically up and down using moveSpeed. How can I make it so that alternatively, the top and bottom point are reached at predefined times? When it reaches the end of the list of timings the movement should stop.

public class Patrol : MonoBehaviour {

    public Transform[] patrolPoints;  //contains top and bottom position
    public float moveSpeed; //needs to be changed dynamically

    private int currentPoint; 

    // Initialization
    void Start () {
        transform.position = patrolPoints [0].position;
        currentPoint = 0;
    }

    // Update is called once per frame
    void Update () {

        print (currentPoint);
        if (currentPoint >= patrolPoints.Length) {
            currentPoint = 0;
        }

        if (transform.position == patrolPoints [currentPoint].position) {
            currentPoint++;
        }

        transform.position = Vector3.MoveTowards (transform.position, patrolPoints[currentPoint].position, moveSpeed * Time.deltaTime);

    }
}

重要的是,不要远离绝对时间点.例如.当计时达到较高的时间(例如1009)时,应该不会有太大的漂移.

It is important that there is no moving away from the absolute time point. E.g. when Timings reaches a high time such as 1009 there shouldn't be much drift.

还要注意,其他事情(例如更改颜色和检查用户行为)需要同时发生,请参阅我的

Also note that other things (such as changing color and checking user behaviour) need to happen at the same time, see my other question.

推荐答案

解决方案的路径为

The path to your solution is this answer which shows function to move GameObject over time.

有了该功能,您可以启动协程,在包含beatsTimerList上循环.在每个循环内,您都应具有一个变量,该变量确定在每个循环之后是向上还是向下.在我的示例中,我将该变量命名为upDownMoveDecider.该变量将决定要使用patrolPoints数组的哪个索引.(我假设只有两个点的索引为 0 1 ).

With that function in hand, you can start a coroutine, loop over the List that contains the beatsTimer. Inside each loop you should have a variable that determines if you should go up or down after each loop. In my example I named that variable upDownMoveDecider. This variable will decide which index of the patrolPoints array to use.(I assume there are only two points with index 0 and 1).

此外,您可以每次在for循环内调用moveToX函数.请确保将其按yield键,以便它将在等待下一个函数之前等待moveToX函数完成或返回.

Also, you can call the moveToX function inside that for loop each time. Make sure to yield it so that it will wait for the moveToX function to finish or return before going to the next function.

下面是应该显示的样子:

Below is what that should look like:

public Transform[] patrolPoints;  //contains top and bottom position
List<float> beatsTimer = new List<float>();
public Transform objectToMove;

void Start()
{
    //For testing purposes
    beatsTimer.Add(0.90f);
    beatsTimer.Add(1.895f);
    beatsTimer.Add(2.64f);
    beatsTimer.Add(3.98f);

    //Start the moveobject
    StartCoroutine(beginToMove());
}

IEnumerator beginToMove()
{
    // 0 = move up, 1 = move down
    int upDownMoveDecider = 0;

    //Loop through the timers
    for (int i = 0; i < beatsTimer.Count; i++)
    {
        if (upDownMoveDecider == 0)
        {
            //Move up
            Debug.Log("Moving Up with time: " + beatsTimer[i] + " in index: " + i);
            //Start Moving and wait here until move is complete(moveToX returns)
            yield return StartCoroutine(moveToX(objectToMove, patrolPoints[upDownMoveDecider].position, beatsTimer[i]));

            //Change direction to 1 for next move
            upDownMoveDecider = 1;
        }
        else
        {
            //Move down
            Debug.Log("Moving Down with time: " + beatsTimer[i] + " in index: " + i);
            //Start Moving and wait here until move is complete(moveToX returns)
            yield return StartCoroutine(moveToX(objectToMove, patrolPoints[upDownMoveDecider].position, beatsTimer[i]));

            //Change direction to 0 for next move
            upDownMoveDecider = 0;
        }
    }
}

IEnumerator moveToX(Transform fromPosition, Vector3 toPosition, float duration)
{
    float counter = 0;

    //Get the current position of the object to be moved
    Vector3 startPos = fromPosition.position;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        fromPosition.position = Vector3.Lerp(startPos, toPosition, counter / duration);
        yield return null;
    }
}

for循环中的代码很长,但更易于理解.这是没有if/else语句的简短版本.

The code inside that for loop is long but it is easier to understand. Here is the shorter version with no if/else statement.

//Loop through the timers
for (int i = 0; i < beatsTimer.Count; i++)
{
    //Move up/Down depening on the upDownMoveDecider variable
    string upDown = (upDownMoveDecider == 0) ? "Up" : "Down";
    Debug.Log("Moving " + upDown + " with time: " + beatsTimer[i] + " in index: " + i);

    //Start Moving and wait here until move is complete(moveToX returns)
    yield return StartCoroutine(moveToX(objectToMove, patrolPoints[upDownMoveDecider].position, beatsTimer[i]));

    //Change direction
    upDownMoveDecider = (upDownMoveDecider == 1) ? 0 : 1;
}

这篇关于在Unity中动态更改对象的速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆