#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
ключевое слово! ABehaviour
не может существовать без привязки кGameObject
, поэтому либо создается черезInstantiate
,AddComponent
либоnew GameObject("", typeof(XY))
3. Вау, вы никогда не задумывались об ошибке точности с плавающей запятой? Я имею в виду, что если вы переместите 5000 единиц в Unity, вы сразу же почувствуете сбои. Ofc, если вы создаете небольшие по масштабу игры, то вам никогда не нужно было знать об этом. В любом случае, сначала мне нужно создать массив, достаточно большой, чтобы хранить все частицы, затем мне нужно получить к ним доступ. Как только у меня будет каждая отдельная частица, я смогу переместить ее со смещением, точно так же, как это делает скрипт для старой системы частиц. Я немного растерялся, потому что функции для новой системы частиц GPU имеют разные методы и свойства.
4. Чувак, конечно, я знаю, что такое проблема с плавающей запятой… но я никогда не слышал
floating origin
раньше или для чего именно этот скрипт хорош
Ответ №1:
Здесь дан ответ на мой вопрос:https://forum.unity.com/threads/floating-origin-and-visual-effect-graph.962646/#post-6270837