Плавающее начало координат и график визуальных эффектов в Unity

#unity3d #floating-point #particles #visual-effects

#unity3d #с плавающей запятой #частицы #визуальные эффекты

Вопрос:

Я уверен, что все знают об этом скрипте,http://wiki.unity3d.com/index.php/Floating_Origin , это легко устраняет проблемы с плавающим началом координат.

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

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

Вот мой код:

 // Based on the Unity Wiki FloatingOrigin script by Peter Stirling
// URL: http://wiki.unity3d.com/index.php/Floating_Origin

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.VFX;
using UnityEngine.Experimental.VFX;

public class FloatingOrigin : MonoBehaviour
{
    [Tooltip("Point of reference from which to check the distance to origin.")]
    public Transform ReferenceObject = null;

    [Tooltip("Distance from the origin the reference object must be in order to trigger an origin shift.")]
    public float Threshold = 5000f;

    [Header("Options")]
    [Tooltip("When true, origin shifts are considered only from the horizontal distance to orign.")]
    public bool Use2DDistance = false;

    [Tooltip("When true, updates ALL open scenes. When false, updates only the active scene.")]
    public bool UpdateAllScenes = true;

    [Tooltip("Should ParticleSystems be moved with an origin shift.")]
    public bool UpdateParticles = true;

    [Tooltip("Should TrailRenderers be moved with an origin shift.")]
    public bool UpdateTrailRenderers = true;

    [Tooltip("Should LineRenderers be moved with an origin shift.")]
    public bool UpdateLineRenderers = true;

    private ParticleSystem.Particle[] parts = null;

    VisualEffect[] visualEffect = null;

    void LateUpdate()
    {
        if (ReferenceObject == null)
            return;

        Vector3 referencePosition = ReferenceObject.position;

        if (Use2DDistance)
            referencePosition.y = 0f;

        if (referencePosition.magnitude > Threshold)
        {
            MoveRootTransforms(referencePosition);

            if (UpdateParticles)
                MoveParticles(referencePosition);

            if (UpdateTrailRenderers)
                MoveTrailRenderers(referencePosition);

            if (UpdateLineRenderers)
                MoveLineRenderers(referencePosition);
        }
    }

    private void MoveRootTransforms(Vector3 offset)
    {
        if (UpdateAllScenes)
        {
            for (int z = 0; z < SceneManager.sceneCount; z  )
            {
                foreach (GameObject g in SceneManager.GetSceneAt(z).GetRootGameObjects())
                    g.transform.position -= offset;
            }
        }
        else
        {
            foreach (GameObject g in SceneManager.GetActiveScene().GetRootGameObjects())
                g.transform.position -= offset;
        }
    }

    private void MoveTrailRenderers(Vector3 offset)
    {
        var trails = FindObjectsOfType<TrailRenderer>() as TrailRenderer[];
        foreach (var trail in trails)
        {
            Vector3[] positions = new Vector3[trail.positionCount];

            int positionCount = trail.GetPositions(positions);
            for (int i = 0; i < positionCount;   i)
                positions[i] -= offset;

            trail.SetPositions(positions);
        }
    }

    private void MoveLineRenderers(Vector3 offset)
    {
        var lines = FindObjectsOfType<LineRenderer>() as LineRenderer[];
        foreach (var line in lines)
        {
            Vector3[] positions = new Vector3[line.positionCount];

            int positionCount = line.GetPositions(positions);
            for (int i = 0; i < positionCount;   i)
                positions[i] -= offset;

            line.SetPositions(positions);
        }
    }

    private void MoveParticles(Vector3 offset)
    {
        var particles = FindObjectsOfType<ParticleSystem>() as ParticleSystem[];
        foreach (ParticleSystem system in particles)
        {
            if (system.main.simulationSpace != ParticleSystemSimulationSpace.World)
                continue;

            int particlesNeeded = system.main.maxParticles;

            if (particlesNeeded <= 0)
                continue;

            bool wasPaused = system.isPaused;
            bool wasPlaying = system.isPlaying;

            if (!wasPaused)
                system.Pause();

            // ensure a sufficiently large array in which to store the particles
            if (parts == null || parts.Length < particlesNeeded)
            {
                parts = new ParticleSystem.Particle[particlesNeeded];
            }

            // now get the particles
            int num = system.GetParticles(parts);

            for (int i = 0; i < num; i  )
            {
                parts[i].position -= offset;
            }

            system.SetParticles(parts, num);

            if (wasPlaying)
                system.Play();
        }
        
        var particles2 = FindObjectsOfType<VisualEffect>() as VisualEffect[];
        foreach (VisualEffect system in particles2)
        {
            int particlesNeeded = system.aliveParticleCount;

            if (particlesNeeded <= 0)
                continue;

            bool wasPaused = !system.isActiveAndEnabled;
            bool wasPlaying = system.isActiveAndEnabled;

            if (!wasPaused)
                system.Stop();
            // ensure a sufficiently large array in which to store the particles
            if (visualEffect == null || visualEffect.Length < particlesNeeded)
            {
                visualEffect = new VisualEffect().visualEffectAsset[particlesNeeded];
            }

            // now get the particles
            int num = system.GetParticles(parts);

            for (int i = 0; i < num; i  )
            {
                parts[i].position -= offset;
            }

            system.SetParticles(parts, num);

            if (wasPlaying)
                system.Play();
            
        }
    } 
}
  

В строке (это неправильная строка и все, что под ней тоже)

 visualEffect = new VisualEffect().visualEffectAsset[particlesNeeded];
  

Мне нужно создать массив, аналогичный строке (правильный, но для старой системы частиц)

 parts = new ParticleSystem.Particle[particlesNeeded];
  

это создает массив, полный частиц (но с классом VisualEffect).

Если я смогу исправить это, с остальным проблем быть не должно. Я думаю, что решение этой проблемы поможет буквально тысячам людей сейчас и в будущем, поскольку ограничения для плавающего origin в unity ужасны, и большинству людей, работающих в Unity, понадобится плавающий origin для их игровых миров с частицами графа VFX.

Спасибо за помощь.

Комментарии:

1. Просто общее замечание: I am sure that everybody knows about this script, http://wiki.unity3d.com/index.php/Floating_Origin, that fixes problems with floating origin easily. .. ошибка нет.. никогда не слышал об этом раньше и даже не слышал об этой «проблеме», о которой вы говорите раньше 😉 .. немного неясно, что вы пытаетесь сделать… VisualEffect.visualEffectAsset это не массив, поэтому вы не можете просто рассматривать его как один

2. Может быть, вы пытаетесь вместо этого создать массив Experimental.VFX.VisualEffectAsset[] ? или массив VisualEffect[] , чтобы каждый из них содержал свой собственный visualEffectAsset ? Обратите особое внимание, что VisualEffect имеет тип Behaviour -> Вы не можете создавать экземпляры, используя new ключевое слово! A Behaviour не может существовать без привязки к GameObject , поэтому либо создается через Instantiate , AddComponent либо new GameObject("", typeof(XY))

3. Вау, вы никогда не задумывались об ошибке точности с плавающей запятой? Я имею в виду, что если вы переместите 5000 единиц в Unity, вы сразу же почувствуете сбои. Ofc, если вы создаете небольшие по масштабу игры, то вам никогда не нужно было знать об этом. В любом случае, сначала мне нужно создать массив, достаточно большой, чтобы хранить все частицы, затем мне нужно получить к ним доступ. Как только у меня будет каждая отдельная частица, я смогу переместить ее со смещением, точно так же, как это делает скрипт для старой системы частиц. Я немного растерялся, потому что функции для новой системы частиц GPU имеют разные методы и свойства.

4. Чувак, конечно, я знаю, что такое проблема с плавающей запятой… но я никогда не слышал floating origin раньше или для чего именно этот скрипт хорош

Ответ №1: