Compare commits

...

14 Commits

Author SHA1 Message Date
mob-sakai 174af4bf7b fix: UIParticleAttractor attracts the particles at wrong position when in RelativeMode
close #262
2023-08-15 09:40:11 +09:00
mob-sakai 65770cadda feat: add public properties for UIParticleAttractor
close #253
2023-08-15 09:40:11 +09:00
mob-sakai 12b5aacf1d refactor 2023-08-15 09:40:11 +09:00
mob-sakai fa8d7fa312 fix: assertion 'ps->array_size()' in UpdateMesh() when using trails of type ribbon
close #241
2023-08-15 09:40:11 +09:00
mob-sakai dc82e4074d fix: change AbsoluteMode default value to true 2023-08-15 09:40:11 +09:00
mob-sakai 924550b0fc fix: scaling ParticleSystem puts prewarmed particles in wrong location
close #235
2023-08-15 09:40:11 +09:00
mob-sakai c4e4fce26f fix: nullReferenceException after copy-n-paste
close #258
2023-08-15 09:40:11 +09:00
mob-sakai ab427e9b6a fix: mesh sharing not working 2023-08-15 09:40:11 +09:00
mob-sakai 5a21298c02 fix: sub-emitters option is not work in editor playing
close #231
2023-08-15 09:40:11 +09:00
mob-sakai 60932e92c1 fix: nullptr exceptions when using nested UIParticle components in hierarchy
close #246
2023-08-15 09:40:11 +09:00
mob-sakai c75ca8663f fix: crash occurs when too many vertices are rendered 2023-08-15 09:40:11 +09:00
mob-sakai 52f2ef1f24 fix: fix typos 2023-08-15 09:40:11 +09:00
Jake O'Connor e92b514624 fix: remove unnecessary per-frame allocation. 2023-08-15 09:40:11 +09:00
AndreevWezom a4bcf93022 feat: add particle system getter and setter for attractor
close #253
2023-08-15 09:40:11 +09:00
3 changed files with 135 additions and 54 deletions

View File

@ -27,7 +27,7 @@ namespace Coffee.UIExtensions
Auto, Auto,
Primary, Primary,
PrimarySimulator, PrimarySimulator,
Reprica, Replica,
} }
[HideInInspector][SerializeField] internal bool m_IsTrail = false; [HideInInspector][SerializeField] internal bool m_IsTrail = false;
@ -44,7 +44,7 @@ namespace Coffee.UIExtensions
[SerializeField] [SerializeField]
private List<ParticleSystem> m_Particles = new List<ParticleSystem>(); private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
[Tooltip("Mesh sharing.None: disable mesh sharing.\nAuto: automatically select Primary/Reprica.\nPrimary: provides particle simulation results to the same group.\nPrimary Simulator: Primary, but do not render the particle (simulation only).\nReprica: render simulation results provided by the primary.")] [Tooltip("Mesh sharing.None: disable mesh sharing.\nAuto: automatically select Primary/Replica.\nPrimary: provides particle simulation results to the same group.\nPrimary Simulator: Primary, but do not render the particle (simulation only).\nReplica: render simulation results provided by the primary.")]
[SerializeField] [SerializeField]
private MeshSharing m_MeshSharing = MeshSharing.None; private MeshSharing m_MeshSharing = MeshSharing.None;
@ -57,7 +57,7 @@ namespace Coffee.UIExtensions
[SerializeField] [SerializeField]
[Tooltip("The particles will be emitted at the ParticleSystem position.\nMove the UIParticle/ParticleSystem to move the particle.")] [Tooltip("The particles will be emitted at the ParticleSystem position.\nMove the UIParticle/ParticleSystem to move the particle.")]
private bool m_AbsoluteMode = false; private bool m_AbsoluteMode = true;
private List<UIParticleRenderer> m_Renderers = new List<UIParticleRenderer>(); private List<UIParticleRenderer> m_Renderers = new List<UIParticleRenderer>();
@ -80,10 +80,10 @@ namespace Coffee.UIExtensions
/// <summary> /// <summary>
/// Mesh sharing.None: disable mesh sharing. /// Mesh sharing.None: disable mesh sharing.
/// Auto: automatically select Primary/Reprica. /// Auto: automatically select Primary/Replica.
/// Primary: provides particle simulation results to the same group. /// Primary: provides particle simulation results to the same group.
/// Primary Simulator: Primary, but do not render the particle (simulation only). /// Primary Simulator: Primary, but do not render the particle (simulation only).
/// Reprica: render simulation results provided by the primary. /// Replica: render simulation results provided by the primary.
/// </summary> /// </summary>
public MeshSharing meshSharing public MeshSharing meshSharing
{ {
@ -145,7 +145,7 @@ namespace Coffee.UIExtensions
internal bool canRender internal bool canRender
{ {
get { return m_MeshSharing == MeshSharing.None || m_MeshSharing == MeshSharing.Auto || m_MeshSharing == MeshSharing.Primary || m_MeshSharing == MeshSharing.Reprica; } get { return m_MeshSharing == MeshSharing.None || m_MeshSharing == MeshSharing.Auto || m_MeshSharing == MeshSharing.Primary || m_MeshSharing == MeshSharing.Replica; }
} }
/// <summary> /// <summary>
@ -286,7 +286,22 @@ namespace Coffee.UIExtensions
public void RefreshParticles(List<ParticleSystem> particles) public void RefreshParticles(List<ParticleSystem> particles)
{ {
GetComponentsInChildren(m_Renderers); // #246: Nullptr exceptions when using nested UIParticle components in hierarchy
m_Renderers.Clear();
foreach (Transform child in transform)
{
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
if (uiParticleRenderer != null)
{
m_Renderers.Add(uiParticleRenderer);
}
}
for (var i = 0; i < m_Renderers.Count; i++)
{
m_Renderers[i].Reset(i);
}
var j = 0; var j = 0;
for (var i = 0; i < particles.Count; i++) for (var i = 0; i < particles.Count; i++)
@ -298,11 +313,6 @@ namespace Coffee.UIExtensions
GetRenderer(j++).Set(this, particles[i], true); GetRenderer(j++).Set(this, particles[i], true);
} }
} }
for (; j < m_Renderers.Count; j++)
{
GetRenderer(j).Clear(j);
}
} }
internal void UpdateTransformScale() internal void UpdateTransformScale()
@ -323,9 +333,13 @@ namespace Coffee.UIExtensions
{ {
if (!isActiveAndEnabled) return; if (!isActiveAndEnabled) return;
if (m_Renderers.Any(x => !x)) foreach (var rend in m_Renderers)
{ {
RefreshParticles(particles); if (!rend)
{
RefreshParticles(particles);
break;
}
} }
var bakeCamera = GetBakeCamera(); var bakeCamera = GetBakeCamera();
@ -386,7 +400,7 @@ namespace Coffee.UIExtensions
{ {
_tracker.Clear(); _tracker.Clear();
UIParticleUpdater.Unregister(this); UIParticleUpdater.Unregister(this);
m_Renderers.ForEach(r => r.Clear()); m_Renderers.ForEach(r => r.Reset());
UnregisterDirtyMaterialCallback(UpdateRendererMaterial); UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
base.OnDisable(); base.OnDisable();
@ -437,9 +451,12 @@ namespace Coffee.UIExtensions
{ {
if (!canvas) return Camera.main; if (!canvas) return Camera.main;
// World camera. // Render mode is not ScreenSpaceOverlay, use world camera.
var root = canvas.rootCanvas; var root = canvas.rootCanvas;
if (root.renderMode != RenderMode.ScreenSpaceOverlay) return root.worldCamera ? root.worldCamera : Camera.main; if (root.renderMode != RenderMode.ScreenSpaceOverlay)
{
return root.worldCamera ? root.worldCamera : Camera.main;
}
// Create ortho-camera. // Create ortho-camera.
if (!_orthoCamera) if (!_orthoCamera)

View File

@ -36,6 +36,12 @@ namespace Coffee.UIExtensions
[SerializeField] [SerializeField]
private UnityEvent m_OnAttracted; private UnityEvent m_OnAttracted;
public float destinationRadius
{
get { return m_DestinationRadius; }
set { m_DestinationRadius = Mathf.Clamp(value, 0.1f, 10f); }
}
public float delay public float delay
{ {
get get
@ -72,22 +78,31 @@ namespace Coffee.UIExtensions
} }
} }
public UnityEvent onAttracted
{
get { return m_OnAttracted; }
set { m_OnAttracted = value; }
}
public ParticleSystem particleSystem
{
get
{
return m_ParticleSystem;
}
set
{
m_ParticleSystem = value;
if (!ApplyParticleSystem()) return;
enabled = true;
}
}
private UIParticle _uiParticle; private UIParticle _uiParticle;
private void OnEnable() private void OnEnable()
{ {
if (m_ParticleSystem == null) if (!ApplyParticleSystem()) return;
{
Debug.LogError("No particle system attached to particle attractor script", this);
enabled = false;
return;
}
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>();
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
{
_uiParticle = null;
}
UIParticleUpdater.Register(this); UIParticleUpdater.Register(this);
} }
@ -154,29 +169,32 @@ namespace Coffee.UIExtensions
var psPos = m_ParticleSystem.transform.position; var psPos = m_ParticleSystem.transform.position;
var attractorPos = transform.position; var attractorPos = transform.position;
var dstPos = attractorPos; var dstPos = attractorPos;
if (m_ParticleSystem.main.simulationSpace == ParticleSystemSimulationSpace.Local) var isLocalSpace = m_ParticleSystem.main.simulationSpace == ParticleSystemSimulationSpace.Local;
if (isLocalSpace)
{ {
dstPos = m_ParticleSystem.transform.InverseTransformPoint(dstPos); dstPos = m_ParticleSystem.transform.InverseTransformPoint(dstPos);
if (isUI)
{
dstPos = dstPos.GetScaled(_uiParticle.transform.localScale, _uiParticle.scale3D.Inverse());
}
} }
else
if (isUI)
{ {
#if UNITY_EDITOR dstPos = dstPos.GetScaled(_uiParticle.transform.localScale, _uiParticle.scale3D.Inverse());
if (!Application.isPlaying && isUI)
// Relative mode
if (!_uiParticle.absoluteMode)
{ {
var diff = dstPos - psPos; var diff = _uiParticle.transform.position - psPos;
diff = diff.GetScaled(_uiParticle.transform.localScale, _uiParticle.scale3D.Inverse()); diff.Scale(_uiParticle.scale3D - _uiParticle.transform.localScale);
return psPos + diff; diff.Scale(_uiParticle.scale3D.Inverse());
dstPos += diff;
}
#if UNITY_EDITOR
if (!Application.isPlaying && !isLocalSpace)
{
dstPos += psPos - psPos.GetScaled(_uiParticle.transform.localScale, _uiParticle.scale3D.Inverse());
} }
#endif #endif
if (isUI)
{
dstPos.Scale(_uiParticle.transform.localScale);
dstPos.Scale(_uiParticle.scale3D.Inverse());
}
} }
return dstPos; return dstPos;
} }
@ -200,5 +218,22 @@ namespace Coffee.UIExtensions
return Vector3.MoveTowards(current, target, speed); return Vector3.MoveTowards(current, target, speed);
} }
private bool ApplyParticleSystem()
{
if (m_ParticleSystem == null)
{
Debug.LogError("No particle system attached to particle attractor script", this);
enabled = false;
return false;
}
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>();
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
{
_uiParticle = null;
}
return true;
}
} }
} }

View File

@ -112,7 +112,12 @@ namespace Coffee.UIExtensions
{ {
_currentMaterialForRendering = null; _currentMaterialForRendering = null;
if (!IsActive()) return baseMaterial; if (!IsActive() || !_parent)
{
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
return baseMaterial;
}
var modifiedMaterial = base.GetModifiedMaterial(baseMaterial); var modifiedMaterial = base.GetModifiedMaterial(baseMaterial);
@ -134,7 +139,7 @@ namespace Coffee.UIExtensions
return modifiedMaterial; return modifiedMaterial;
} }
public void Clear(int index = -1) public void Reset(int index = -1)
{ {
if (_renderer) if (_renderer)
{ {
@ -157,6 +162,12 @@ namespace Coffee.UIExtensions
_lastBounds = new Bounds(); _lastBounds = new Bounds();
enabled = false; enabled = false;
} }
else
{
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
_currentMaterialForRendering = null;
}
} }
public void Set(UIParticle parent, ParticleSystem particleSystem, bool isTrail) public void Set(UIParticle parent, ParticleSystem particleSystem, bool isTrail)
@ -167,15 +178,18 @@ namespace Coffee.UIExtensions
gameObject.layer = parent.gameObject.layer; gameObject.layer = parent.gameObject.layer;
_particleSystem = particleSystem; _particleSystem = particleSystem;
_prewarm = _particleSystem.main.prewarm;
#if UNITY_EDITOR #if UNITY_EDITOR
if (Application.isPlaying) if (Application.isPlaying)
#endif #endif
if (_particleSystem.isPlaying)
{ {
_particleSystem.Clear(); if (_particleSystem.isPlaying || _prewarm)
_particleSystem.Pause(); {
_particleSystem.Clear();
_particleSystem.Pause();
}
} }
_prewarm = _particleSystem.main.prewarm;
_renderer = particleSystem.GetComponent<ParticleSystemRenderer>(); _renderer = particleSystem.GetComponent<ParticleSystemRenderer>();
_renderer.enabled = false; _renderer.enabled = false;
@ -208,7 +222,7 @@ namespace Coffee.UIExtensions
// No particle to render: Clear mesh. // No particle to render: Clear mesh.
if ( if (
!isActiveAndEnabled || !_particleSystem || !_parent || !canvasRenderer || !canvas || !bakeCamera !isActiveAndEnabled || !_particleSystem || !_parent || !canvasRenderer || !canvas || !bakeCamera
|| _parent.meshSharing == UIParticle.MeshSharing.Reprica || _parent.meshSharing == UIParticle.MeshSharing.Replica
|| !transform.lossyScale.GetScaled(_parent.scale3D).IsVisible() // Scale is not visible. || !transform.lossyScale.GetScaled(_parent.scale3D).IsVisible() // Scale is not visible.
|| (!_particleSystem.IsAlive() && !_particleSystem.isPlaying) // No particle. || (!_particleSystem.IsAlive() && !_particleSystem.isPlaying) // No particle.
|| (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled. || (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled.
@ -264,7 +278,7 @@ namespace Coffee.UIExtensions
// Bake mesh. // Bake mesh.
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh"); Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
if (_isTrail && _parent.canSimulate) if (_isTrail && _parent.canSimulate && 0 < s_CombineInstances[0].mesh.vertices.Length)
{ {
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true); _renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
} }
@ -276,6 +290,18 @@ namespace Coffee.UIExtensions
{ {
s_CombineInstances[0].mesh.Clear(false); s_CombineInstances[0].mesh.Clear(false);
} }
// Too many vertices to render.
if (65535 <= s_CombineInstances[0].mesh.vertexCount)
{
s_CombineInstances[0].mesh.Clear(false);
UnityEngine.Debug.LogErrorFormat(this,
"Too many vertices to render. index={0}, isTrail={1}, vertexCount={2}(>=65535)",
_index,
_isTrail,
s_CombineInstances[0].mesh.vertexCount
);
}
Profiler.EndSample(); Profiler.EndSample();
// Combine mesh to transform. ([ParticleSystem local ->] world -> renderer local) // Combine mesh to transform. ([ParticleSystem local ->] world -> renderer local)
@ -507,7 +533,9 @@ namespace Coffee.UIExtensions
_prewarm = false; _prewarm = false;
} }
// Emitted particles found. // (COMMENT OUT) #231: Sub Emitters option is not work in editor playing
/*
// Emitted particles found.
if (_prevParticleCount != _particleSystem.particleCount) if (_prevParticleCount != _particleSystem.particleCount)
{ {
var size = _particleSystem.particleCount; var size = _particleSystem.particleCount;
@ -522,6 +550,7 @@ namespace Coffee.UIExtensions
_particleSystem.SetParticles(particles, size); _particleSystem.SetParticles(particles, size);
} }
*/
// get world position. // get world position.
var psTransform = _particleSystem.transform; var psTransform = _particleSystem.transform;