Маятник Unity C# с вращением

Я новичок в 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), что оно не удовлетворяется или, может быть, в чем на самом деле причина, почему оно не работает.

в моих математических расчетах поворот «оси» (т. е. линии) на 180° даст точно такую ​​же линию, если центр вращения находится на линии. Не могли бы вы уточнить?

Pac0 06.05.2024 15:26

Используя Unity 3D, я создаю аттракцион в парке развлечений под названием «Викинги», который движется как маятник, и добавляю функцию, которая поворачивается на 180 градусов, если достигает максимально возможной высоты.

Prince K 06.05.2024 15:33

до сих пор не совсем понял, но попробую - у вас есть объект-маятник, который вращается вокруг другой оси (x или z), верно? И теперь каждый раз, когда он проходит самую верхнюю точку, нужно дополнительно выполнять поворот кабины вокруг Y?

derHugo 06.05.2024 15:42

Но как это должно произойти, если вы также перезаписываете каждый кадр с помощью transform.localRotation = Quaternion.Euler(0, 0, angle); .. далее никогда не сравнивайте float, используя == .. из-за точности это может никогда не стать правдой ... и тогда ваше условие будет справедливым только для одного кадра .. .ваше вращение скорее всего должно происходить во время разных кадров...

derHugo 06.05.2024 15:43

да, он будет вращать ось Y каждый раз, когда проходит самую верхнюю точку, Transform.localRotation = Quaternion.Euler(0, 0, angular); это маятниковое движение, которое движется только по оси Z.

Prince K 06.05.2024 15:45

понятно, попробую изменить условия, связанные с плавающей запятой

Prince K 06.05.2024 15:47

обновление: дело в том, что условие теперь выполняется, но проблема теперь в том, что после того, как условие выполнено, он вращается примерно 0,5 секунды, мерцая и телепортируясь на другую сторону.

Prince K 06.05.2024 16:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, если я правильно понял, то на самом деле вам нужно два оборота.

  • Маятник непрерывно вращается вперед и назад по оси Z.
  • Кроме того, как только вы достигнете предела с обеих сторон, вам дополнительно понадобится поворот на 180 ° по оси Y.

С вашим подходом связаны различные проблемы.

  • Этот

    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);
    }
}

Большое вам спасибо, сэр, ваше учение во многом просветило меня.

Prince K 06.05.2024 16:58

Другие вопросы по теме