在Unity中动态更改对象的速度 [英] Dynamically changing speed of object in 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.
有了该功能,您可以启动协程,在包含beatsTimer
的List
上循环.在每个循环内,您都应具有一个变量,该变量确定在每个循环之后是向上还是向下.在我的示例中,我将该变量命名为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屋!