Как заставить объект вращаться вокруг цели со случайной высотой и с возможностью изменения радиуса вращения?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotateAroundTarget : MonoBehaviour
{
    public Transform target;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.RotateAround(target.transform.position, new Vector3(0,1,0), 20 * Time.deltaTime);
        transform.position = new Vector3(0,Random.Range(0,5f),0);
    }
}

RotateAround работал нормально, но как только я добавил часть Random.Range, объект не просто прыгал очень быстро.

Я думаю, мне нужно как-то добавить задержку между случайными пикапами? но не уверен, как сделать его плавным, чтобы объект вращался вокруг цели и время от времени случайным образом менял высоту плавно вверх и вниз.

а как добавить возможность изменения поворота по радиусу вокруг цели?

попробовал код выше, но он все еще далек от того, что я хотел.

Я попытался использовать InvokeRepeating, но преобразование больше не вращается.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotateAroundTarget : MonoBehaviour
{
    public Transform target;

    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("ChangePosition", 0, 2);
    }

    // Update is called once per frame
    void Update()
    {
        transform.RotateAround(target.transform.position, new Vector3(0,1,0), 20 * Time.deltaTime); 
    }

    private void ChangePosition()
    {
        transform.position = new Vector3(0, Random.Range(0, 5f), 0);
    }
}
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Есть пара проблем с вашим кодом. Во-первых, установка позиции с помощью:

transform.position = new Vector3(0,Random.Range(0,5f),0);

полностью перезапишет любое изменение X/Z, вызванное предыдущим RotateAround. Вот почему ваша ротация остановилась, как только вы ввели этот код. Чтобы установить положение без потери значений X/Z, вы можете использовать:

transform.position = new Vector3(
    transform.position.x,
    Random.Range(0,5f),
    transform.position.z);

Итак, теперь ротация снова работает. Но изменения высоты все еще неустойчивы, потому что ваш код устанавливает новую случайную высоту в каждом кадре. Что мы можем сделать вместо этого?

Давайте попробуем ограничить максимальное изменение высоты определенной скоростью и установить новую цель высоты только тогда, когда предыдущая достигнута. Таким образом, ваш код может выглядеть так:

public class RotateAroundTarget : MonoBehaviour
{
    public Transform target;
    public float verticalSpeed = 20;
    public float radius = 10;

    private float targetHeight;

    // Start is called before the first frame update
    void Start()
    {
        // Initialize with a height to start moving toward
        targetHeight = GetNewTargetHeight();

        // If we start at a given distance away from the target, then this
        // will become our radius when we RotateAround it
        transform.position = new Vector3(0, 0, radius);
    }

    // Update is called once per frame
    void Update()
    {
        transform.RotateAround(target.transform.position,
            new Vector3(0,1,0), 20 * Time.deltaTime);

        // Just like your rotation rate, we scale this based on game time
        float maxHeightChange = verticalSpeed * Time.deltaTime;
        float targetHeightDelta = targetHeight - transform.position.y;

        if (maxHeightChange >= Mathf.Abs(targetHeightDelta)){
            // If the current height is close enough to the target, we can move it
            // there and then generate a new height to go towards
            transform.position = new Vector3(
                transform.position.x,
                targetHeight,
                transform.position.z);
            targetHeight = GetNewTargetHeight();
        }
        else{
            // Otherwise, limit the magnitude of the height change by the speed and
            // apply it to the current height
            float allowedHeightChange = Mathf.Clamp(
                targetHeightDelta,
                -maxHeightChange,
                maxHeightChange);
            transform.position = new Vector3(
                transform.position.x,
                transform.position.y + allowedHeightChange,
                transform.position.z);
        }
    }

    private float GetNewTargetHeight()
    {
        return Random.Range(0,5f);
    }
}

как я могу заставить преобразование вращаться вокруг цели по вертикали? теперь он вращается по горизонтали. я пытался изменить ось внутри RotateAround нового Vector3 (0,1,0) на 1,0,0 или на 0,0,1, играл с ним, но он не вращался по вертикали.

daniel zedek 14.02.2023 20:32

если я изменяю ось, например, 0,0,1, она будет вращаться вокруг вертикали, но только если я не изменяю высоту преобразования случайным образом. если я оставлю код с высотой, он также слишком сильно изменит позицию преобразования, а не как когда ось была 0,1,0, когда она вращалась вокруг цели.

daniel zedek 14.02.2023 20:47

@danielzedek Вы правы, это решение предназначено только для вращения вокруг вертикальной оси при изменении высоты. Но для адаптации к оси X или Z для горизонтального вращения не требуется больших изменений. Вам нужно будет изменить 3 вещи: начальное положение объекта, ось вращения и компонент преобразования, который вы устанавливаете случайным образом. Например, если вы хотите вращаться вокруг оси X, вы можете начать с начальной позиции (0, радиус, 0), оси вращения (1, 0, 0) и сосредоточиться на рандомизации преобразования. .position.x вместо y.

Serlite 15.02.2023 00:46

Попробуйте, и если у вас возникнут трудности с адаптацией этого к более общему решению, подумайте о том, чтобы задать новый вопрос. Комментарии не очень хороши для этого, так как они не очень видны большинству пользователей.

Serlite 15.02.2023 00:48

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