Я новичок в Unity, могу ли я получить помощь?
Итак, по сути, я создал маятник, но добавил некоторую функцию, в которой, если он достигнет максимально возможной высоты, ось Y маятника повернется на 180 градусов, но ось Y не вращается.
Вот код:
using UnityEngine;
public class PendulumScript : MonoBehaviour
{
[SerializeField] public float speed = 1.5f;
public float limit = 75f;
public bool randomStart = false;
private float random = 0;
private bool limitReached = false;
private Quaternion originalRotation;
void Awake()
{
if (randomStart)
{
random = Random.Range(0f, 1f);
}
// Save the original rotation
originalRotation = transform.localRotation;
}
void Update()
{
float angle = limit * Mathf.Sin(Time.time + random * speed);
transform.localRotation = Quaternion.Euler(0, 0, angle);
if (!limitReached && (angle == limit))
{
// Rotate around the Y-axis by 180 degrees
transform.Rotate(0, 180 * Time.time, 0);
limitReached = true;
limit *= -1; // turns limit into negative
}
else if (limitReached && (angle == -limit))
{
// Reset to original rotation which is Y = 0
transform.localRotation = originalRotation;
limitReached = false;
limit *= -1; // turns limit into positive
}
}
}
я пробовал вращать, используя if !limitreached and else if limitreached
, и он вращается, но мерцает, так как он вращается все время, поэтому я добавил еще одно условие, но, похоже, лучшее условие, о котором я мог подумать, не работает, я надеюсь выяснить это что не так с условием (angle == limit)
, что оно не удовлетворяется или, может быть, в чем на самом деле причина, почему оно не работает.
Используя Unity 3D, я создаю аттракцион в парке развлечений под названием «Викинги», который движется как маятник, и добавляю функцию, которая поворачивается на 180 градусов, если достигает максимально возможной высоты.
до сих пор не совсем понял, но попробую - у вас есть объект-маятник, который вращается вокруг другой оси (x или z), верно? И теперь каждый раз, когда он проходит самую верхнюю точку, нужно дополнительно выполнять поворот кабины вокруг Y?
Но как это должно произойти, если вы также перезаписываете каждый кадр с помощью transform.localRotation = Quaternion.Euler(0, 0, angle);
.. далее никогда не сравнивайте float
, используя ==
.. из-за точности это может никогда не стать правдой ... и тогда ваше условие будет справедливым только для одного кадра .. .ваше вращение скорее всего должно происходить во время разных кадров...
да, он будет вращать ось Y каждый раз, когда проходит самую верхнюю точку, Transform.localRotation = Quaternion.Euler(0, 0, angular); это маятниковое движение, которое движется только по оси Z.
понятно, попробую изменить условия, связанные с плавающей запятой
обновление: дело в том, что условие теперь выполняется, но проблема теперь в том, что после того, как условие выполнено, он вращается примерно 0,5 секунды, мерцая и телепортируясь на другую сторону.
Итак, если я правильно понял, то на самом деле вам нужно два оборота.
С вашим подходом связаны различные проблемы.
Этот
transform.localRotation = Quaternion.Euler(0, 0, angle);
НЕТ only rotate on the Z axis
! Это довольно жесткий сброс y = 0
.
Никогда не сравнивайте float
с помощью ==
!
Из-за ограничений точности этого может никогда не случиться true
Ваше состояние также составляет true
максимум в течение одного кадра.
Вы скорее хотите вызвать непрерывное вращение вокруг Y.
я также думаю, что
Time.time + random * speed
это не совсем то, что вы хотели использовать, а скорее, например.
(Time.time + random) * speed
И
transform.Rotate(0, 180 * Time.time, 0);
НЕ вращается на 180°... чем больше времени прошло тем больше он здесь будет вращаться!
На самом деле я бы рассматривал это как два отдельных вращения и обрабатывал их отдельно:
public class PendulumScript : MonoBehaviour
{
public float speed = 1.5f;
public float limit = 75f;
public bool randomStart = false;
public float yRotationSpeed = 45.0f; // degrees per second
private float rotationZ;
private float rotationY;
private bool performingYFlip;
private float time;
private float targetYRotation;
void Awake()
{
// instead of selecting a random sin value
// I would rather select a random start time
// This way you have a clear check when enough time has passed to
// perform the flip
if (randomStart)
{
// sinus range is in radians => full cycle every 2π
time = Random.Range(0f, 2 * Mathf.PI) * speed;
// if required could also adjust the initial targetYRotation based on the random time here
}
}
void Update()
{
// simply increase the timer by the time passed since last frame
time += Time.deltaTime * speed;
// calculate Z rotation as before
rotationZ = Mathf.Sin(time) * limit;
// Use approximate equality for angles
// note that due to the sinus even this might never be true within a frame
//if (Mathf.Approximately(rotationZ, limit))
// so you might even use a wider range like e.g.
if (!performingYFlip && Mathf.Abs(rotationZ - limit) <= /*Some Threshold in angles*/ 5f)
{
// initiate a flip
performingYFlip = true;
targetYRotation += 180f;
}
if (performingYFlip)
{
// continuous Y rotation as long as performingYFlip remains true
yRotation = Mathf.MoveTowards(yRotation, targetYRotation, yRotationSpeed * Time.deltaTime);
if (Mathf.Approximately(yRotation, targetYRotation))
{
performingYFlip = false;
}
}
// and finally apply both rotations together
transform.rotation = Quaternion.Euler(0, yRotation, zRotation);
}
}
Большое вам спасибо, сэр, ваше учение во многом просветило меня.
в моих математических расчетах поворот «оси» (т. е. линии) на 180° даст точно такую же линию, если центр вращения находится на линии. Не могли бы вы уточнить?