来回旋转游戏对象
Rotate GameObject back and forth
我想在 Y 轴上来回旋转 90,-90 之间的对象。问题是我可以在编辑器中将对象设置为 -90,但是当我 运行 项目时 -90 突然变成 270。无论如何,这是我正在使用的代码:
void Update()
{
if (transform.eulerAngles.y >= 270)
{
transform.Rotate(Vector3.up * speed * Time.deltaTime);
}
else if (transform.eulerAngles.y <= 90)
{
transform.Rotate(Vector3.up * -speed * Time.deltaTime);
}
}
它总是卡在中间 360 度左右。有帮助吗?
首先你应该始终确保角度保持在0
和359
之间,也就是说0 == 360
:
float angle = transform.eulerAngles.y % 360.00f;
之后你可以检查它是否介于你的最小值和最大值之间:
if ( angle >= 270.00f && angle <= 90.00f )
{
// do your logic here ...
}
您的代码的另一个问题是它会卡在 350
和 10
度之间的某个位置。为了更详细地解释这一点,我们假设您的速度是 10
,Time.deltaTime
也将是 1
,起始角度是 300
,现在帧步长:
Frame | Angle | Condition
----- | ----- | :-----------:
1 | 300 | angle >= 270
2 | 310 | angle >= 270
3 | 320 | angle >= 270
6 | 350 | angle >= 270
7 | 360 | angle >= 270
8 | 10 | angle <= 90
9 | 0 | angle <= 90
10 | 350 | angle >= 270
...这将永远持续下去。
要解决这个问题,您必须根据用户输入设置一些条件,或者如果您希望相机在这两个角度之间 "bounce",那么您可以尝试这样的操作:
// make private field in that object :
float currentlyRotated = 0;
bool shouldAdd = true;
void Update()
{
var d = Vector3.up * (shouldAdd ? speed : -speed) * Time.deltaTime;
var angle = transform.eulerAngles.y + (shouldAdd ? speed : -speed);
angle %= 360.00f;
transform.Rotate(d);
if ( angle > 90 && angle < 270 )
{
shouldAdd = !shouldAdd;
}
}
就像 GameObject back and forth, you can rotate GameObject back and forth with Mathf.PingPong
一样。这就是它的用途。它的 return 值介于 0 和 1 之间。您可以将该值传递给 Vector3.Lerp
并生成执行旋转所需的 eulerAngle。
这也可以通过协程完成,但如果您不需要知道何时到达目的地,则应使用 Mathf.PingPong
。如果您想知道何时到达旋转目的地,则应使用协程。
public float speed = 0.36f;
Vector3 pointA;
Vector3 pointB;
void Start()
{
//Get current position then add 90 to its Y axis
pointA = transform.eulerAngles + new Vector3(0f, 90f, 0f);
//Get current position then substract -90 to its Y axis
pointB = transform.eulerAngles + new Vector3(0f, -90f, 0f);
}
void Update()
{
//PingPong between 0 and 1
float time = Mathf.PingPong(Time.time * speed, 1);
transform.eulerAngles = Vector3.Lerp(pointA, pointB, time);
}
编辑:
使用 方法可以确定每次旋转的结束。
public GameObject objectToRotate;
public float speed = 0.36f;
Vector3 pointA;
Vector3 pointB;
void Start()
{
//Get current position then add 90 to its Y axis
pointA = transform.eulerAngles + new Vector3(0f, 90f, 0f);
//Get current position then substract -90 to its Y axis
pointB = transform.eulerAngles + new Vector3(0f, -90f, 0f);
objectToRotate = this.gameObject;
StartCoroutine(rotate());
}
IEnumerator rotate()
{
while (true)
{
//Rotate 90
yield return rotateObject(objectToRotate, pointA, 3f);
//Rotate -90
yield return rotateObject(objectToRotate, pointB, 3f);
//Wait?
//yield return new WaitForSeconds(3);
}
}
bool rotating = false;
IEnumerator rotateObject(GameObject gameObjectToMove, Vector3 eulerAngles, float duration)
{
if (rotating)
{
yield break;
}
rotating = true;
Vector3 newRot = gameObjectToMove.transform.eulerAngles + eulerAngles;
Vector3 currentRot = gameObjectToMove.transform.eulerAngles;
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
gameObjectToMove.transform.eulerAngles = Vector3.Lerp(currentRot, newRot, counter / duration);
yield return null;
}
rotating = false;
}
我想在 Y 轴上来回旋转 90,-90 之间的对象。问题是我可以在编辑器中将对象设置为 -90,但是当我 运行 项目时 -90 突然变成 270。无论如何,这是我正在使用的代码:
void Update()
{
if (transform.eulerAngles.y >= 270)
{
transform.Rotate(Vector3.up * speed * Time.deltaTime);
}
else if (transform.eulerAngles.y <= 90)
{
transform.Rotate(Vector3.up * -speed * Time.deltaTime);
}
}
它总是卡在中间 360 度左右。有帮助吗?
首先你应该始终确保角度保持在0
和359
之间,也就是说0 == 360
:
float angle = transform.eulerAngles.y % 360.00f;
之后你可以检查它是否介于你的最小值和最大值之间:
if ( angle >= 270.00f && angle <= 90.00f )
{
// do your logic here ...
}
您的代码的另一个问题是它会卡在 350
和 10
度之间的某个位置。为了更详细地解释这一点,我们假设您的速度是 10
,Time.deltaTime
也将是 1
,起始角度是 300
,现在帧步长:
Frame | Angle | Condition
----- | ----- | :-----------:
1 | 300 | angle >= 270
2 | 310 | angle >= 270
3 | 320 | angle >= 270
6 | 350 | angle >= 270
7 | 360 | angle >= 270
8 | 10 | angle <= 90
9 | 0 | angle <= 90
10 | 350 | angle >= 270
...这将永远持续下去。
要解决这个问题,您必须根据用户输入设置一些条件,或者如果您希望相机在这两个角度之间 "bounce",那么您可以尝试这样的操作:
// make private field in that object :
float currentlyRotated = 0;
bool shouldAdd = true;
void Update()
{
var d = Vector3.up * (shouldAdd ? speed : -speed) * Time.deltaTime;
var angle = transform.eulerAngles.y + (shouldAdd ? speed : -speed);
angle %= 360.00f;
transform.Rotate(d);
if ( angle > 90 && angle < 270 )
{
shouldAdd = !shouldAdd;
}
}
就像Mathf.PingPong
一样。这就是它的用途。它的 return 值介于 0 和 1 之间。您可以将该值传递给 Vector3.Lerp
并生成执行旋转所需的 eulerAngle。
这也可以通过协程完成,但如果您不需要知道何时到达目的地,则应使用 Mathf.PingPong
。如果您想知道何时到达旋转目的地,则应使用协程。
public float speed = 0.36f;
Vector3 pointA;
Vector3 pointB;
void Start()
{
//Get current position then add 90 to its Y axis
pointA = transform.eulerAngles + new Vector3(0f, 90f, 0f);
//Get current position then substract -90 to its Y axis
pointB = transform.eulerAngles + new Vector3(0f, -90f, 0f);
}
void Update()
{
//PingPong between 0 and 1
float time = Mathf.PingPong(Time.time * speed, 1);
transform.eulerAngles = Vector3.Lerp(pointA, pointB, time);
}
编辑:
使用
public GameObject objectToRotate;
public float speed = 0.36f;
Vector3 pointA;
Vector3 pointB;
void Start()
{
//Get current position then add 90 to its Y axis
pointA = transform.eulerAngles + new Vector3(0f, 90f, 0f);
//Get current position then substract -90 to its Y axis
pointB = transform.eulerAngles + new Vector3(0f, -90f, 0f);
objectToRotate = this.gameObject;
StartCoroutine(rotate());
}
IEnumerator rotate()
{
while (true)
{
//Rotate 90
yield return rotateObject(objectToRotate, pointA, 3f);
//Rotate -90
yield return rotateObject(objectToRotate, pointB, 3f);
//Wait?
//yield return new WaitForSeconds(3);
}
}
bool rotating = false;
IEnumerator rotateObject(GameObject gameObjectToMove, Vector3 eulerAngles, float duration)
{
if (rotating)
{
yield break;
}
rotating = true;
Vector3 newRot = gameObjectToMove.transform.eulerAngles + eulerAngles;
Vector3 currentRot = gameObjectToMove.transform.eulerAngles;
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
gameObjectToMove.transform.eulerAngles = Vector3.Lerp(currentRot, newRot, counter / duration);
yield return null;
}
rotating = false;
}