【问题标题】:Floating origin and visual effect graph in UnityUnity中的浮动原点和视觉效果图
【发布时间】:2020-09-02 08:23:25
【问题描述】:

我相信每个人都知道这个脚本,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 类)。

如果我能解决这个问题,其余的应该不会有任何问题。 我认为解决这个问题将在现在和将来帮助成千上万的人,因为统一中浮动原点的限制是可怕的,并且大多数在统一中工作的人将需要使用 VFX 图形粒子的游戏世界的浮动原点。

感谢您的帮助。

【问题讨论】:

  • 只是一个一般说明:I am sure that everybody knows about this script, http://wiki.unity3d.com/index.php/Floating_Origin, that fixes problems with floating origin easily. .. errr nope .. 以前从未听说过,甚至从未听说过你之前所说的那个“问题”;) .. 有点不清楚你在说什么正在尝试做...VisualEffect.visualEffectAsset 不是数组,所以你不能把它当作一个数组来对待
  • 您是否尝试创建一个 Experimental.VFX.VisualEffectAsset[] 数组来代替?或VisualEffect[] 的数组,以便每个人都拥有自己的visualEffectAsset?特别注意VisualEffect 的类型为Behaviour -> 您不能使用new 关键字创建实例! Behaviour 不能在没有附加到GameObject 的情况下生存,所以通过InstantiateAddComponentnew GameObject("", typeof(XY)) 实例化
  • 哇,你从来没有想过浮点精度错误?我的意思是,如果您统一移动 5000 个单位,您将立即遇到故障。 Ofc,如果您正在大规模制作小型游戏,那么您永远不需要了解它。无论如何,首先我需要创建一个足够大的数组来存储所有粒子,然后我需要访问它们。一旦我有了每一个粒子,我就可以将它移动一个偏移量,就像脚本对旧粒子系统所做的那样。我有点迷茫,因为新的 GPU 粒子系统的函数有不同的方法和属性。
  • 伙计,我当然知道浮点问题是什么……但我之前从未听说过 floating origin 或者该脚本到底有什么用处

标签: unity3d floating-point particles visual-effects


【解决方案1】:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
  • 2022-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多