我正在编写一个游戏,其中每当节拍器敲打时立方体必须绕其自身旋转90度。
每次节拍器跳动时,我的方法都会调用一个协程:
IEnumerator moveCoroutine()
{
if (!isCollided && canRotate) {
for (float i = 0; i < 10; i++) {
transform.RotateAround(pivot, direction, 90 / 10);
yield return null;
}
}
}
并且立方体旋转相当平滑,但旋转在节拍器的下一个节拍之前很长时间完成,并且我希望它从开始到结束旋转,顺利移动。
我想我可以使用两个节拍器刻度之间的时间(这是var&#39; Metronome.manager.delay&#39;)但是我找不到如何。
感谢您的帮助
答案 0 :(得分:0)
您可以在Mathf中使用SmoothStep函数:http://docs.unity3d.com/ScriptReference/Mathf.SmoothStep.html
最小值是立方体的当前角度,最大值是当前角度+ 90,t类似于(currentTime - previousTick) / (nextTick - previousTick)
(根据您的数据结构进行修改)
答案 1 :(得分:0)
所以你的Unity c#脚本通常会在每个帧渲染时运行。为了使您的动画流畅,您需要根据文档将您的更改字段/变量乘以Time.DeltaTime
:
http://docs.unity3d.com/ScriptReference/Time-deltaTime.html
Time.DeltaTime
由统一游戏引擎计算,是从上次渲染帧开始经过的时间。
文档中的示例:
public class ExampleClass : MonoBehaviour {
void Update() {
float translation = Time.deltaTime * 10;
transform.Translate(0, 0, translation);
}
}
在该示例中,变换在z轴上被翻译了10个单位,由于Time.deltaTime
[校正因子]而正确地进行了动画处理。
如果你在每一帧中添加或减去一个值,你应该有机会 乘以Time.deltaTime。当你与Time.deltaTime相乘时 你基本上表达:我想把这个物体移动10米 而不是每帧10米。
使用协程的另一个例子:
using UnityEngine;
using System.Collections;
public class CoroutinesExample : MonoBehaviour
{
public float smoothing = 1f;
public Transform target;
void Start ()
{
StartCoroutine(MyCoroutine(target));
}
IEnumerator MyCoroutine (Transform target)
{
while(Vector3.Distance(transform.position, target.position) > 0.05f)
{
transform.position = Vector3.Lerp(transform.position, target.position, smoothing * Time.deltaTime);
yield return null;
}
print("Reached the target.");
yield return new WaitForSeconds(3f);
print("MyCoroutine is now finished.");
}
}
你想要的可能是这样的:
IEnumerator moveCoroutine()
{
if (!isCollided && canRotate) {
for (float i = 0; i < 10; i++) {
transform.RotateAround(pivot, direction, 9.0f * Time.deltaTime);
yield return null;
}
}
}
这可以修复动画的平滑度,并使其独立于每台计算机渲染帧(FPS)的能力。 - &GT;问题只有当你在自己以外的其他设备上进行测试时才会注意到。
现在解决动画长度的问题:
IEnumerator moveCoroutine()
{
int maxIterations = 10;
if (!isCollided && canRotate) {
for (float i = 0; i < maxIterations; i++) {
transform.RotateAround(pivot, direction, 9.0f * Time.deltaTime);
yield return new WaitForSeconds(Metronome.manager.delay / maxIterations);
}
}
}
WaitForSeconds(Metronome.manager.delay / maxIterations);
将确保您的动画在您想要的时间播放。 (请注意,Metronome.manager.delay
如果尚未转换为秒,则需要转换为秒。
答案 2 :(得分:0)
这是一个协程,你只需要为waitforseconds指定一个值。监控游戏并根据需要设置值。
IEnumerator moveCoroutine()
{
float time=0.5f;
if (!isCollided && canRotate) {
for (float i = 0; i < 10; i++) {
transform.RotateAround(pivot, direction, 9);
yield return new WaitForSeconds(time);
}
}
}
答案 3 :(得分:0)
其他答案可能有用..但是我使用此设置来实现Unity中的平滑协同程序,而不是取决于帧速率而是实际时间 (运动的必要变化应该是微不足道的):
touch million-subfolders-folder/package.json
通过这种方式,您可以更自如地控制动画所需的时间,并为旋转设置精确值,确保旋转时不会出现任何奇怪现象。
你可以称之为Coroutine而不是例如。
public IEnumerator RotateCoroutine(Vector3 rotationEulerAngles, float rotationDuration)
{
/* Set the current goal Rotation to animate between them */
Quaternion currentRotation = transform.localRotation;
Quaternion goalRotation = currentRotation * Quaternion.Euler(rotationEulerAngles);
/* Set control variables */
float timePassed = 0.0f;
float fracTime = 0.0f;
/* Begin the animation, end after rotationDuration seconds */
while (fracTime < 1)
{
/* Set Rotation between current and goal depending on fracTime */
transform.transform.localRotation = Quaternion.Lerp(currentRotation, goalRotation, fracTime);
/* Update timePassed and fracTime */
timePassed += Time.deltaTime;
/* On this way fracTime will always be a value between
* 0 - start of animation and
* 1 - end of animation after rotationDuration seconds */
fracTime = timePassed / rotationDuration;
/* yield return so the actual state gets printed */
yield return null;
}
/* Just to be sure after the animation set yourGameObject
* to exactly the tranformation value(s) you want */
transform.localRotation = goalRotation;
}
用于在当地的Y轴
中在2秒内旋转对象约90°