我在做一个团结项目。有一个汽车雨刷,我想旋转它的方式,当我预先“雨刷切换”雨刷开始旋转从0,0, 0 ,0,-45,并开始勒平。但是当我按下“雨刷开关”时,雨刷必须旋转回0,0,0。例如,如果当前的雨刷旋转为0,0,-20,并且我按下“雨刷切换关闭”键,它们必须是rotateTowards 0,0,0。另外,如果我再次按下“雨刷开关”,雨刷必须开始从0,0,0到0,0,-45旋转。现在,情况是雨刷是旋转的,但当我按下“雨刷开关关闭”,雨刷停止在相同的当前旋转点,例如(0,0,-30)。当我再一次按下“雨刷开关”时,雨刷就会从奇怪的不同的旋转点开始。这是我的代码:
using UnityEngine;
using System.Collections;
public class Wipers : MonoBehaviour
{
[SerializeField] protected Vector3 m_from = new Vector3(0.0F, 0.0F, 0.0F);
[SerializeField] protected Vector3 m_to = new Vector3(0.0F, -45.0F, 0.0F);
[SerializeField] protected float m_frequency = 1.0F;
protected virtual void Update()
{
if (ControlFreak2.CF2Input.GetAxis ("wipers") != 0)
{
Quaternion from = Quaternion.Euler(this.m_from);
Quaternion to = Quaternion.Euler(this.m_to);
float lerp = 0.5F * (1.0F + Mathf.Sin(Mathf.PI * Time.realtimeSinceStartup * this.m_frequency));
this.transform.localRotation = Quaternion.Lerp(from, to, lerp);
}
}
}
发布于 2020-02-21 07:03:42
Time.realtimeSinceStartup
,当然,在关闭例程时,它也继续运行!所以你永远不知道什么时候雨刷会被打开。
→,您更愿意使用的时间,因为雨刷,从哪里开始。与其在Update
中这样做,我建议使用一个柯鲁丁。与直接在Update
中进行操作相比,协同工作更容易控制和维护。实际上,它们就像小的临时更新,像例程一样,在真正的Update
完成后立即执行。
一个协同器,你可以让它继续和完成一个完整的周期,直到它实际完成。
在Update中,您将只检查用户输入并启动一个例程(如果没有一个已经在运行),并且该例程可以独立运行和终止一个完整的循环:
[SerializeField] protected Vector3 m_from = new Vector3(0.0F, 0.0F, 0.0F);
[SerializeField] protected Vector3 m_to = new Vector3(0.0F, -45.0F, 0.0F);
[SerializeField] protected float m_frequency = 1.0F;
// TODO only for debugging
[SerializeField] private bool ControlFreak2Dummy;
private bool wipersOn;
private Quaternion from;
private Quaternion to;
private void Awake()
{
// Store these once -> more efficient then recalculate them everytime
from = Quaternion.Euler(m_from);
to = Quaternion.Euler(m_to);
}
protected virtual void Update()
{
// TODO switch these back
//if (ControlFreak2.CF2Input.GetAxis ("wipers") != 0)
if (ControlFreak2Dummy)
{
if(!wipersOn)
{
StartCoroutine(Wipers());
}
}
}
// To make things easier for us this in itself closed routine is exactly ONE FULL wipers cycle
// so we can determine exactly when a full cycle is done or not
private IEnumerator Wipers()
{
// block concurrent routines
wipersOn = true;
var duration = 1f / m_frequency;
var timePassed = 0f;
while (timePassed <= duration)
{
// Note: Your sinus factor calculation was a bit strange
// (or maybe this early I'm way too stupid for maths lol ^^)
// It was always minimum 0.5 and maximum 1, you rather want to pingpong between 0 and 1
//
// This now moves forth and back exactly once between 0 and 1
var factor = Mathf.Sin(Mathf.PI * timePassed / duration);
transform.localRotation = Quaternion.Lerp(from, to, factor);
// increase timePassed by the time passed since last frame
timePassed += Time.deltaTime;
// allows Unity to "pause" here, render this frame and
// continue from here in the next frame
yield return null;
}
// make sur it really terminates in 0
transform.localRotation = from;
// tell others that this routine is done
wipersOn = false;
}
https://stackoverflow.com/questions/60333130
复制相似问题