【发布时间】: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的情况下生存,所以通过Instantiate、AddComponent或new GameObject("", typeof(XY))实例化 -
哇,你从来没有想过浮点精度错误?我的意思是,如果您统一移动 5000 个单位,您将立即遇到故障。 Ofc,如果您正在大规模制作小型游戏,那么您永远不需要了解它。无论如何,首先我需要创建一个足够大的数组来存储所有粒子,然后我需要访问它们。一旦我有了每一个粒子,我就可以将它移动一个偏移量,就像脚本对旧粒子系统所做的那样。我有点迷茫,因为新的 GPU 粒子系统的函数有不同的方法和属性。
-
伙计,我当然知道浮点问题是什么……但我之前从未听说过
floating origin或者该脚本到底有什么用处
标签: unity3d floating-point particles visual-effects