Compare commits

..

21 Commits

Author SHA1 Message Date
mob-sakai f1d12c3b04 fix compile error on Unity 2021.1 2023-08-18 15:08:49 +09:00
mob-sakai db28f171f7 docs: update docs 2023-08-18 15:08:24 +09:00
mob-sakai 410304125f feat: 'AutoScaling' option will be imported from 'IgnoreCanvasScale' (for v3.x) 2023-08-18 13:17:09 +09:00
mob-sakai 67eff61073 feat: 'AbsoluteMode' option is renamed to 'PositionMode'
AbsoluteMode property is obsolete
2023-08-18 13:17:09 +09:00
mob-sakai 4851a1880e fix: inactive ParticleSystems are removed from the list on refresh 2023-08-18 13:17:09 +09:00
mob-sakai 2fe0bde422 fix: excessive particle emitted on move ParticleSystem for local space simulation and emission over distance
close #265
2023-08-18 13:17:09 +09:00
mob-sakai c2119c171a fix: built-in shaders are no longer supported
close #233, close #257

Use UI shaders instead.
If built-in non-UI shaders are used, an error is displayed in the inspector.
2023-08-18 13:17:09 +09:00
mob-sakai 3df190382a resharp 2023-08-18 13:17:09 +09:00
mob-sakai 35325c8899 feat: add 'AutoScaling' option for UIParticle
Transform.lossyScale (=world scale) is automatically set to (1, 1, 1).
It prevents the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.
This option works in reverse of ’IgnoreCanvasScaler’ option in v3.x.
2023-08-18 11:48:05 +09:00
mob-sakai 903f702d7b feat: add 'UpdateMode' option for UIParticleAttractor
close #250
2023-08-18 11:48:05 +09:00
mob-sakai e93051603e fix: error: SerializedObject target has been destroyed
close #267
2023-08-18 11:48:05 +09:00
mob-sakai e4998365c9 feat: add Start/StopEmission API for UIParticle
close #240
2023-08-18 11:48:05 +09:00
mob-sakai 68d9925a16 fix: UIParticleAttractor attracts the particles at wrong position when in RelativeMode
close #262
2023-08-18 11:48:05 +09:00
mob-sakai 392ab6dd76 feat: add public properties for UIParticleAttractor
close #253
2023-08-18 11:48:05 +09:00
mob-sakai f75fcce0da fix: assertion 'ps->array_size()' in UpdateMesh() when using trails of type ribbon
close #241
2023-08-18 11:48:05 +09:00
mob-sakai fb31db47f2 fix: scaling ParticleSystem puts prewarmed particles in wrong location
close #235
2023-08-18 11:47:40 +09:00
mob-sakai 425aad0cba fix: nullReferenceException after copy-n-paste
close #258
2023-08-18 11:47:40 +09:00
mob-sakai 8b4ca1add5 fix: mesh sharing not working
close #236
2023-08-18 11:47:40 +09:00
mob-sakai b308b26833 fix: sub-emitters option is not work in editor playing
close #231
2023-08-18 11:47:40 +09:00
mob-sakai e67e9482e2 fix: nullptr exceptions when using nested UIParticle components in hierarchy
close #246
2023-08-18 11:47:11 +09:00
mob-sakai 723a04d0cf fix: crash occurs when too many vertices are rendered 2023-08-18 11:47:11 +09:00
11 changed files with 239 additions and 150 deletions

View File

@ -10,26 +10,39 @@ assignees: mob-sakai
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- Version [e.g. 1.0.0]
**Environment (please complete the following)**
- Package version [e.g. 4.2.0, 3.3.14]
- Platform: [e.g. Editor(Windows/Mac), Standalone(Windows/Mac), iOS, Android, WebGL]
- Unity version: [e.g. 2018.2.8f1]
- Build options: [e.g. IL2CPP, .Net 4.x, LWRP]
- Unity version: [e.g. 2021.3.7f1]
- Project options: [e.g. Mono/IL2CPP, .Net Standard 2.1/.Net 4.x, URP/HDRP, GraphicAPIs]
**Additional context**
Add any other context about the problem here.
Please add any other context about the issue here.
It will help us resolve the issue.
- Error messages and crash dump
- Screenshots, gif animations and movie files
- Reproducible minimal project
- The entire project (zipped Assets, Packages, ProjectSettings) is preferred over `.unitypackage`

View File

@ -10,13 +10,17 @@ assignees: mob-sakai
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
A clear and concise description of what the issue is. (e.g. I'm always frustrated when [...])
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -1,4 +1,4 @@
Copyright 2018-2022 mob-sakai
Copyright 2018-2023 mob-sakai
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -4,14 +4,12 @@ Particle Effect For UGUI (UI Particle)
This plugin provide a component to render particle effect for uGUI in Unity 2018.2 or later.
The particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.
![](https://img.shields.io/badge/Editor-2018.2+-4796F2?logo=unity)
[![](https://img.shields.io/npm/v/com.coffee.ui-particle?label=openupm&registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.coffee.ui-particle/)
[![](https://img.shields.io/github/v/release/mob-sakai/ParticleEffectForUGUI?include_prereleases)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
[![](https://img.shields.io/github/v/release/mob-sakai/ParticleEffectForUGUI?include_prereleases&sort=semver)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
[![](https://img.shields.io/github/v/release/mob-sakai/ParticleEffectForUGUI?include_prereleases&sort=semver&filter=3.%2A&label=release(3.x))](https://github.com/mob-sakai/ParticleEffectForUGUI/releases)
[![](https://img.shields.io/github/release-date/mob-sakai/ParticleEffectForUGUI.svg)](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) [![](https://img.shields.io/github/license/mob-sakai/ParticleEffectForUGUI.svg)](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/master/LICENSE.txt)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-orange.svg)](http://makeapullrequest.com)
![](https://img.shields.io/badge/Unity%202018.2+-supported-blue.svg)
![](https://img.shields.io/badge/Unity%202019.x-supported-blue.svg)
![](https://img.shields.io/badge/Unity%202020.x-supported-blue.svg)
![](https://img.shields.io/badge/Universal%20Rendering%20Pipeline-supported-blue.svg)
<< [Description](#Description) | [Demo](#demo) | [Installation](#installation) | [Usage](#usage) | [Development Note](#development-note) | [Change log](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md) >>
@ -58,6 +56,8 @@ Compares this "Baking mesh" approach with the conventional approach:
* Support CanvasGroup alpha
* No allocations
* Support overlay, camera space and world space
* Support Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP)
* Support disabling `Enter Play Mode Options > Reload Domain`
* Support changing material property with AnimationClip (AnimatableProperty)
![](https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif)
* [4.0.0+] Support 8+ materials
@ -92,39 +92,41 @@ Compares this "Baking mesh" approach with the conventional approach:
### Requirement
![](https://img.shields.io/badge/Unity%202018.2+-supported-blue.svg)
![](https://img.shields.io/badge/Unity%202019.x-supported-blue.svg)
![](https://img.shields.io/badge/Unity%202020.x-supported-blue.svg)
![](https://img.shields.io/badge/Universal%20Rendering%20Pipeline-supported-blue.svg)
Unity 2018.2 or later
### Using OpenUPM
### Install via OpenUPM
This package is available on [OpenUPM](https://openupm.com).
You can install it via [openupm-cli](https://github.com/openupm/openupm-cli).
It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
```
openupm add com.coffee.ui-particle
```
### Using Git
### Install via Package Manager Window (using Git URL)
Find the manifest.json file in the Packages folder of your project and add a line to `dependencies` field.
1. Select `Window/Package Manager` menu to open `Package Manager` window.
2. Click `+` and `Install package from git URL...`
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/57317aa4-e55c-4568-b2aa-2ee2a78ddc02)
3. Input `https://github.com/mob-sakai/ParticleEffectForUGUI.git` and click `Install`
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/72cc38b5-cb32-4c85-8209-c85f7bb931ea)
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git"`
To update the package, change suffix `#{version}` to the target version.
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.0.0",`
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
### For Unity 2018.2
### Install via manifest.json (using Git URL)
Unity 2018.2 supports embedded packages.
1. Open `Packages/manifest.json` in your project.
2. Add this line below `"dependencies": {`
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",`
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/fe1cad9c-8d09-4e17-b6f5-9eac0d267921)
3. To update the package, change suffix `#{version}`.
* `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.2.0",`
### Install as an embed package
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI/releases) page
2. Extract it
3. Import it under `Packages` directory in your Unity project
2. Extract it and place it under `Packages` directory in your project.
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/4c3d3439-5bb0-4e87-a917-ebe328ef89a8)
<br><br><br><br>
@ -161,17 +163,17 @@ Unity 2018.2 supports embedded packages.
`UIParticle` controls the ParticleSystems that is attached to its own game objects and child game objects.
![](https://user-images.githubusercontent.com/12690315/174413976-691eb38e-7f92-4fbe-9790-8771b9dc70b2.png)
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/3559df45-63e7-4c4c-9233-f455779efa29)
| Properties | Description |
| -- | -- |
| Maskable | Does this graphic allow masking. |
| Ignore Canvas Scale | Ignore the scale of the root canvas.<br>This prevents it from displaying small even in hierarchy scaling mode of `ParticleSystem`. |
| Scale | Scale the rendering.<br>When the `3D` toggle is enabled, 3D scale (x,y,z) is supported. |
| Animatable Properties | If you want update material properties (e.g. `_MainTex_ST`, `_Color`) in AnimationClip, use this to mark the changes. |
| Mesh Sharing | Particle simulation results are shared within the same group.<br>A large number of the same effects can be displayed with a small load.<br>When the `Random` toggle is enabled, it will be grouped randomaly. |
| Absolute Mode | The particles will be emitted at the ParticleSystem position.<br>Move the UIParticle/ParticleSystem to move the particle. |
| Rendering Order | The ParticleSystems to be rendered.<br>You can change the rendering order and the materials. |
| Position Mode | **Absolute:** Emit from the world position of the `ParticleSystem`.<br>**Relative:** Emit from the scaled position of the `ParticleSystem`. |
| Auto Scaling | Transform.lossyScale (=world scale) will be set to `(1, 1, 1)` on update.<br>It prevents the root-Canvas scale from affecting the hierarchy-scaled `ParticleSystem`. |
| Rendering Order | The ParticleSystem list to be rendered.<br>You can change the order and the materials. |
NOTE: Press `Refresh` button to reconstruct rendering order based on children ParticleSystem's sorting order and z position.
@ -227,7 +229,7 @@ uiParticle.Stop();
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
![](https://user-images.githubusercontent.com/12690315/174413982-b31c358a-8e1d-4b3e-a6d8-18b050b25d6f.png)
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/ea6ae0ed-f9a8-437c-8baa-47526303391e)
![](https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif)
| Properties | Description |
@ -237,6 +239,7 @@ uiParticle.Stop();
| Delay Rate | Delay to start attracting.<br>It is a percentage of the particle's start lifetime. |
| Max Speed | Maximum speed of attracting.<br> If this value is too small, attracting may not be completed by the end of the lifetime and `OnAttracted` may not be called. |
| Movement | Attracting movement type. (Linear, Smooth, Sphere) |
| Update Mode | **Normal:** Update with scaled delta time.<br>**Unscaled Time:** Update with unscaled delta time. |
| OnAttracted | An event called when attracting is complete (per particle). |
<br><br><br><br>
@ -245,14 +248,31 @@ uiParticle.Stop();
### Shader Limitation
UIParticles are based on UIVertex.
Therefore, only xy components is available for each UV in the shader. (zw components will be ignored).
So unfortunately UIParticles will not work well with some shaders.
When using custom vertex streams, you can fill zw components with "unnecessary" data.
https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191
The use of UI shaders is recommended.
- If you need a simple Additive shader, use the `UI/Additive` shader instead.
- If you need a simple alpha-blend shader, use the `UI/Default` shader instead.
- If your custom shader does not work properly with UIParticle, consider creating a custom UI shader.
#### Built-in shaders are not supported
UIParticle does not support all built-in shaders except for `UI/Default`.
If their use is detected, an error is displayed in the inspector.
Use UI shaders instead.
#### UV.zw components will be discarded
UIParticleRenderer renders the particles based on UIVertex.
Therefore, only xy components is available for each UV in the shader. (zw components will be discarded).
So unfortunately UIParticles will not work well with some shaders.
#### Custom vertex streams
When using custom vertex streams, you can fill zw components with "unnecessary" data.
https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191
<br>
### Overheads

View File

@ -12,6 +12,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Coffee.UIParticleExtensions;
using UnityEditor;
using UnityEditor.UI;
using UnityEditorInternal;
@ -59,11 +60,6 @@ namespace Coffee.UIExtensions
private static readonly GUIContent s_Content3D = new GUIContent("3D");
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
private static readonly GUIContent s_ContentAutoScaling = new GUIContent("Auto Scaling",
"Transform.lossyScale (=world scale) is automatically set to (1, 1, 1)," +
" to prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.");
private static SerializedObject s_SerializedObject;
private static bool s_XYZMode;
@ -73,8 +69,8 @@ namespace Coffee.UIExtensions
private SerializedProperty _meshSharing;
private SerializedProperty _groupId;
private SerializedProperty _groupMaxId;
private SerializedProperty _absoluteMode;
private SerializedProperty _ignoreCanvasScaler;
private SerializedProperty _positionMode;
private SerializedProperty _autoScaling;
private ReorderableList _ro;
private bool _showMax;
@ -127,7 +123,7 @@ namespace Coffee.UIExtensions
{
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
.Where(x => x)
.Select(x => x.GetComponentInParent<UIParticle>())
.Select(x => x.GetComponentInParent<UIParticle>(true))
.Where(x => x && x.canvas)
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
.Where(x => x && x.canvas))
@ -156,8 +152,8 @@ namespace Coffee.UIExtensions
_meshSharing = serializedObject.FindProperty("m_MeshSharing");
_groupId = serializedObject.FindProperty("m_GroupId");
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
_absoluteMode = serializedObject.FindProperty("m_AbsoluteMode");
_ignoreCanvasScaler = serializedObject.FindProperty("m_IgnoreCanvasScaler");
_positionMode = serializedObject.FindProperty("m_PositionMode");
_autoScaling = serializedObject.FindProperty("m_AutoScaling");
var sp = serializedObject.FindProperty("m_Particles");
_ro = new ReorderableList(sp.serializedObject, sp, true, true, true, true)
@ -271,20 +267,11 @@ namespace Coffee.UIExtensions
}
}
// Absolute Mode
EditorGUILayout.PropertyField(_absoluteMode);
// Position Mode
EditorGUILayout.PropertyField(_positionMode);
// Auto Scaling
DrawInversedToggle(_ignoreCanvasScaler, s_ContentAutoScaling, () =>
{
foreach (var uip in targets.OfType<UIParticle>())
{
if (uip && !uip.autoScaling)
{
uip.transform.localScale = Vector3.one;
}
}
});
DrawAutoScaling(_autoScaling, targets.OfType<UIParticle>());
// Target ParticleSystems.
EditorGUI.BeginChangeCheck();
@ -315,7 +302,7 @@ namespace Coffee.UIExtensions
}
// Does the shader support UI masks?
if (current.maskable && current.GetComponentInParent<Mask>())
if (current.maskable && current.GetComponentInParent<Mask>(false))
{
foreach (var mat in current.materials)
{
@ -489,22 +476,21 @@ namespace Coffee.UIExtensions
return showMax;
}
private static void DrawInversedToggle(SerializedProperty sp, GUIContent label, Action onChanged)
private static void DrawAutoScaling(SerializedProperty prop, IEnumerable<UIParticle> uiParticles)
{
EditorGUI.showMixedValue = sp.hasMultipleDifferentValues;
var autoScaling = !sp.boolValue;
EditorGUI.BeginChangeCheck();
if (autoScaling != EditorGUILayout.Toggle(label, autoScaling))
{
sp.boolValue = autoScaling;
}
EditorGUILayout.PropertyField(prop);
if (!EditorGUI.EndChangeCheck()) return;
if (EditorGUI.EndChangeCheck())
// on changed true->false, reset scale.
EditorApplication.delayCall += () =>
{
EditorApplication.delayCall += onChanged.Invoke;
foreach (var uip in uiParticles)
{
if (!uip || uip.autoScaling) continue;
uip.transform.localScale = Vector3.one;
}
EditorGUI.showMixedValue = false;
};
}
private static void WindowFunction(Object target, SceneView sceneView)
@ -512,7 +498,8 @@ namespace Coffee.UIExtensions
try
{
if (s_SerializedObject == null || !s_SerializedObject.targetObject) return;
if (s_SerializedObject.targetObjects.OfType<UIParticle>().Any(x => !x || !x.canvas)) return;
var uiParticles = s_SerializedObject.targetObjects.OfType<UIParticle>();
if (uiParticles.Any(x => !x || !x.canvas)) return;
s_SerializedObject.Update();
using (new EditorGUILayout.VerticalScope(GUILayout.Width(220f)))
@ -521,17 +508,8 @@ namespace Coffee.UIExtensions
EditorGUIUtility.labelWidth = 100;
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_Enabled"));
s_XYZMode = DrawFloatOrVector3Field(s_SerializedObject.FindProperty("m_Scale3D"), s_XYZMode);
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_AbsoluteMode"));
DrawInversedToggle(s_SerializedObject.FindProperty("m_IgnoreCanvasScaler"),
s_ContentAutoScaling,
() =>
{
s_SerializedObject.targetObjects
.OfType<UIParticle>()
.Where(x => x && !x.autoScaling)
.ToList()
.ForEach(x => x.transform.localScale = Vector3.one);
});
EditorGUILayout.PropertyField(s_SerializedObject.FindProperty("m_PositionMode"));
DrawAutoScaling(s_SerializedObject.FindProperty("m_AutoScaling"), uiParticles);
EditorGUIUtility.labelWidth = labelWidth;
}

View File

@ -19,7 +19,7 @@ namespace Coffee.UIExtensions
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
public class UIParticle : MaskableGraphic
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
{
public enum MeshSharing
{
@ -30,10 +30,25 @@ namespace Coffee.UIExtensions
Replica
}
public enum PositionMode
{
Relative,
Absolute
}
[HideInInspector]
[SerializeField]
internal bool m_IsTrail;
[HideInInspector]
[FormerlySerializedAs("m_IgnoreParent")]
[SerializeField]
private bool m_IgnoreCanvasScaler;
[HideInInspector]
[SerializeField]
private bool m_AbsoluteMode;
[Tooltip("Particle effect scale")]
[SerializeField]
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
@ -64,20 +79,15 @@ namespace Coffee.UIExtensions
[SerializeField]
private int m_GroupMaxId;
[Tooltip("Relative: The particles will be emitted from the scaled position of ParticleSystem.\n" +
"Absolute: The particles will be emitted from the world position of ParticleSystem.")]
[SerializeField]
[Tooltip("Particle position mode.\n" +
"Absolute Mode: The particles will be emitted from the ParticleSystem position.\n" +
" Move the UIParticle or ParticleSystem to move the particle.\n" +
"Relative Mode: The particles will be emitted from the scaled ParticleSystem position.\n" +
" Move the UIParticle to move the particle.")]
private bool m_AbsoluteMode = true;
private PositionMode m_PositionMode = PositionMode.Relative;
/// <summary>
/// This field uses the inverted value as "AutoScaling".
/// </summary>
[FormerlySerializedAs("m_IgnoreParent")]
[SerializeField]
private bool m_IgnoreCanvasScaler;
[Tooltip("Transform.lossyScale (=world scale) is automatically set to (1, 1, 1), " +
"to prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
private bool m_AutoScaling = true;
#if !SERIALIZE_FIELD_MASKABLE
[SerializeField]
@ -142,30 +152,37 @@ namespace Coffee.UIExtensions
/// <summary>
/// Particle position mode.
/// Absolute Mode: The particles will be emitted from the ParticleSystem position.
/// Move the UIParticle or ParticleSystem to move the particle.
/// Relative Mode: The particles will be emitted from the scaled ParticleSystem position.
/// Move the UIParticle to move the particle.
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
/// </summary>
public bool absoluteMode
public PositionMode positionMode
{
get { return m_AbsoluteMode; }
set { m_AbsoluteMode = value; }
get { return m_PositionMode; }
set { m_PositionMode = value; }
}
/// <summary>
/// Transform.lossyScale (=world scale) is automatically set to (1, 1, 1).
/// Particle position mode.
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
/// </summary>
public bool absoluteMode
{
get { return m_PositionMode == PositionMode.Absolute; }
set { positionMode = value ? PositionMode.Absolute : PositionMode.Relative; }
}
/// <summary>
/// Transform.lossyScale (=world scale) will be set to (1, 1, 1) on update.
/// It prevents the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.
///
/// Note: This option works in reverse of IgnoreCanvasScaler option in v3.x.
/// </summary>
public bool autoScaling
{
get { return !m_IgnoreCanvasScaler; }
get { return m_AutoScaling; }
set
{
if (m_IgnoreCanvasScaler != value) return;
m_IgnoreCanvasScaler = !value;
if (m_AutoScaling == value) return;
m_AutoScaling = value;
UpdateTracker();
}
}
@ -307,6 +324,25 @@ namespace Coffee.UIExtensions
}
#endif
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
m_IgnoreCanvasScaler = !m_AutoScaling;
m_AbsoluteMode = m_PositionMode == PositionMode.Absolute;
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (m_IgnoreCanvasScaler)
{
m_AutoScaling = false;
}
if (m_AbsoluteMode)
{
m_PositionMode = PositionMode.Absolute;
}
}
public void Play()
{
particles.Exec(p => p.Simulate(0, false, true));
@ -395,8 +431,8 @@ namespace Coffee.UIExtensions
private void RefreshParticles(GameObject root)
{
if (!root) return;
root.GetComponentsInChildren(particles);
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>() != this);
root.GetComponentsInChildren(true, particles);
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
for (var i = 0; i < particles.Count; i++)
{

View File

@ -185,7 +185,7 @@ namespace Coffee.UIExtensions
dstPos = dstPos.GetScaled(inverseScale, _uiParticle.scale3D.Inverse());
// Relative mode
if (!_uiParticle.absoluteMode)
if (_uiParticle.positionMode == UIParticle.PositionMode.Relative)
{
var diff = _uiParticle.transform.position - psPos;
diff.Scale(_uiParticle.scale3D - inverseScale);
@ -248,7 +248,7 @@ namespace Coffee.UIExtensions
return;
}
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>();
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>(true);
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
{
_uiParticle = null;

View File

@ -129,7 +129,8 @@ namespace Coffee.UIExtensions
{
s_CombineInstances[0].mesh = new Mesh
{
name = "[UIParticleRenderer] Combine Instance Mesh", hideFlags = HideFlags.HideAndDontSave
name = "[UIParticleRenderer] Combine Instance Mesh",
hideFlags = HideFlags.HideAndDontSave
};
}
@ -150,7 +151,8 @@ namespace Coffee.UIExtensions
// Create renderer object.
var go = new GameObject("UIParticleRenderer", typeof(UIParticleRenderer))
{
hideFlags = HideFlags.DontSave, layer = parent.gameObject.layer
hideFlags = HideFlags.DontSave,
layer = parent.gameObject.layer
};
// Set parent.
@ -319,7 +321,7 @@ namespace Coffee.UIExtensions
// Bake mesh.
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
if (_isTrail && _parent.canSimulate && 0 < s_CombineInstances[0].mesh.vertices.Length)
if (_isTrail && _parent.canSimulate && 0 < s_CombineInstances[0].mesh.vertexCount)
{
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
}
@ -342,6 +344,7 @@ namespace Coffee.UIExtensions
_isTrail,
s_CombineInstances[0].mesh.vertexCount
);
s_CombineInstances[0].mesh.Clear(false);
}
Profiler.EndSample();
@ -350,7 +353,7 @@ namespace Coffee.UIExtensions
Profiler.BeginSample("[UIParticleRenderer] Combine Mesh");
if (_parent.canSimulate)
{
if (_parent.absoluteMode)
if (_parent.positionMode == UIParticle.PositionMode.Absolute)
{
s_CombineInstances[0].transform =
canvasRenderer.transform.worldToLocalMatrix

View File

@ -244,5 +244,40 @@ namespace Coffee.UIParticleExtensions
Object.Destroy(obj);
}
}
#if !UNITY_2020_3_OR_NEWER || UNITY_2021_1
public static T GetComponentInParent<T>(this Component self, bool includeInactive) where T : Component
{
if (!self) return null;
if (!includeInactive) return self.GetComponentInParent<T>();
var current = self.transform;
while (current)
{
var component = current.GetComponent<T>();
if (component) return component;
current = current.parent;
}
return null;
}
public static T GetComponentInChildren<T>(this Component self, bool includeInactive) where T : Component
{
if (!self) return null;
if (!includeInactive) return self.GetComponentInChildren<T>();
var component = self.GetComponent<T>();
if (component) return component;
foreach (Transform child in self.transform)
{
component = child.GetComponentInChildren<T>(true);
if (component) return component;
}
return null;
}
#endif
}
}