如何统一减慢旋转物体
how to slow a rotating object in unity
我正在尝试写一个命运之轮类型的东西。我希望轮子旋转一段时间,然后在随机位置缓慢停止。
我目前所做的一切都有效,但停止太突然了。在某处使用 Slerp 可能会解决问题。但是我在确保轮子只顺时针旋转方面也遇到了麻烦!
public class WheelOptions : MonoBehaviour
{
[SerializeField] int spinDuration = 5;
[SerializeField] int seedValue = 5;
[SerializeField] SectionColors[] sectionColors;
Vector3 targetPosition;
bool isSpinning = false;
bool hasSpun = false;
int currentSpin = 0;
void Start()
{
targetPosition = new Vector3(Random.Range(-5, 5), 0f, Random.Range(-5, 5));
}
public void SpinWheel()
{
isSpinning = true;
hasSpun = false;
targetPosition = new Vector3(Random.Range(-5, 5), 0f, Random.Range(-5, 5));
StartCoroutine( StopTimer() );
}
void Update()
{
transform.position = new Vector3(0f, 0, 0f);
if (isSpinning == true)
{
if (currentSpin < 360)
{
currentSpin++;
}
else currentSpin = 0;
this.transform.rotation = Quaternion.Euler(0, currentSpin, 0);
}
else if(hasSpun == true)
{
Quaternion rotation = Quaternion.LookRotation(targetPosition - transform.position, transform.TransformDirection(Vector3.forward));
transform.rotation = new Quaternion(0, rotation.y, 0, rotation.w);
}
}
IEnumerator StopTimer()
{
yield return new WaitForSeconds(spinDuration);
isSpinning = false;
hasSpun = true;
}
}
public float speed = 1.0f;
public float forceRemain = 1.0f;
public bool isSpin = false;
private Quanternion lastRot;
private float rm = forceRemain;
void Update(){
if(isSpin){
this.transform.rotation = new Quanternion(o,
lastRot.y + (speed * Time.DeltaTime), 0, // rotate right while isSpin
lastRot.w);
}
else{
if(rm > 0){
rm -= Time.DeltaTime; //slowin down remain force
}
else{
rm = forceRemain; //reset remain force
}
}
}
抱歉我的代码不太准确
你的旋转想法让它无法顺利停止。将 isSpinning
设置为 false
将完全阻止平滑。您需要某种公式来根据时间计算所需的旋转。在某种程度上,即使计算机的 fps 很低,微调器仍会降落到相同的确定目的地。
此外,在 5x5 正方形内获得随机位置的逻辑给出了对角落的不均匀分布。旋转器会更频繁地停在角落。
我创建了一个 Rotator 脚本供您借鉴。 targetSpin
是微调器旋转的总度数。 spinDuration
是旋转的秒数。剩下的就是数学和物理了。
public class Rotater : MonoBehaviour
{
public float spinDuration = 3f;
public float targetSpin = 3600f;
float initSpin = 0f;
float initSpeed = 0f;
float acceleration = 0f;
float startRotTime = 0f;
private void CalcInitSpeedingConditions()
{
// Here we assume constant acceleration, and ending speed must be 0.
initSpeed = 2 * targetSpin / spinDuration;
acceleration = -initSpeed / spinDuration;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// targetSpin = Random.Range(1000f, 1360f); # Use this to spin random on each press
CalcInitSpeedingConditions();
startRotTime = Time.time;
initSpin = transform.localEulerAngles.y;
StartCoroutine(Rotate());
}
}
// This is fundamental physics formula
private float GetRotationByTime(float t) => initSpeed * t + acceleration * t * t / 2;
IEnumerator Rotate()
{
float t = Time.time - startRotTime;
while (t < spinDuration)
{
t = Time.time - startRotTime;
GetRotationByTime(t);
transform.localEulerAngles = Vector3.up * (initSpin + GetRotationByTime(t) % 360);
yield return null;
}
transform.localEulerAngles = Vector3.up * (initSpin + GetRotationByTime(t) % 360);
}
}
我正在尝试写一个命运之轮类型的东西。我希望轮子旋转一段时间,然后在随机位置缓慢停止。
我目前所做的一切都有效,但停止太突然了。在某处使用 Slerp 可能会解决问题。但是我在确保轮子只顺时针旋转方面也遇到了麻烦!
public class WheelOptions : MonoBehaviour
{
[SerializeField] int spinDuration = 5;
[SerializeField] int seedValue = 5;
[SerializeField] SectionColors[] sectionColors;
Vector3 targetPosition;
bool isSpinning = false;
bool hasSpun = false;
int currentSpin = 0;
void Start()
{
targetPosition = new Vector3(Random.Range(-5, 5), 0f, Random.Range(-5, 5));
}
public void SpinWheel()
{
isSpinning = true;
hasSpun = false;
targetPosition = new Vector3(Random.Range(-5, 5), 0f, Random.Range(-5, 5));
StartCoroutine( StopTimer() );
}
void Update()
{
transform.position = new Vector3(0f, 0, 0f);
if (isSpinning == true)
{
if (currentSpin < 360)
{
currentSpin++;
}
else currentSpin = 0;
this.transform.rotation = Quaternion.Euler(0, currentSpin, 0);
}
else if(hasSpun == true)
{
Quaternion rotation = Quaternion.LookRotation(targetPosition - transform.position, transform.TransformDirection(Vector3.forward));
transform.rotation = new Quaternion(0, rotation.y, 0, rotation.w);
}
}
IEnumerator StopTimer()
{
yield return new WaitForSeconds(spinDuration);
isSpinning = false;
hasSpun = true;
}
}
public float speed = 1.0f;
public float forceRemain = 1.0f;
public bool isSpin = false;
private Quanternion lastRot;
private float rm = forceRemain;
void Update(){
if(isSpin){
this.transform.rotation = new Quanternion(o,
lastRot.y + (speed * Time.DeltaTime), 0, // rotate right while isSpin
lastRot.w);
}
else{
if(rm > 0){
rm -= Time.DeltaTime; //slowin down remain force
}
else{
rm = forceRemain; //reset remain force
}
}
}
抱歉我的代码不太准确
你的旋转想法让它无法顺利停止。将 isSpinning
设置为 false
将完全阻止平滑。您需要某种公式来根据时间计算所需的旋转。在某种程度上,即使计算机的 fps 很低,微调器仍会降落到相同的确定目的地。
此外,在 5x5 正方形内获得随机位置的逻辑给出了对角落的不均匀分布。旋转器会更频繁地停在角落。
我创建了一个 Rotator 脚本供您借鉴。 targetSpin
是微调器旋转的总度数。 spinDuration
是旋转的秒数。剩下的就是数学和物理了。
public class Rotater : MonoBehaviour
{
public float spinDuration = 3f;
public float targetSpin = 3600f;
float initSpin = 0f;
float initSpeed = 0f;
float acceleration = 0f;
float startRotTime = 0f;
private void CalcInitSpeedingConditions()
{
// Here we assume constant acceleration, and ending speed must be 0.
initSpeed = 2 * targetSpin / spinDuration;
acceleration = -initSpeed / spinDuration;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// targetSpin = Random.Range(1000f, 1360f); # Use this to spin random on each press
CalcInitSpeedingConditions();
startRotTime = Time.time;
initSpin = transform.localEulerAngles.y;
StartCoroutine(Rotate());
}
}
// This is fundamental physics formula
private float GetRotationByTime(float t) => initSpeed * t + acceleration * t * t / 2;
IEnumerator Rotate()
{
float t = Time.time - startRotTime;
while (t < spinDuration)
{
t = Time.time - startRotTime;
GetRotationByTime(t);
transform.localEulerAngles = Vector3.up * (initSpin + GetRotationByTime(t) % 360);
yield return null;
}
transform.localEulerAngles = Vector3.up * (initSpin + GetRotationByTime(t) % 360);
}
}