refactor
parent
4c5251a5ba
commit
4d0cfd3510
|
@ -4,7 +4,7 @@
|
||||||
"release-4.x",
|
"release-4.x",
|
||||||
{
|
{
|
||||||
"name": "release-preview",
|
"name": "release-preview",
|
||||||
"prerelease": true
|
"prerelease": "preview"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
|
|
@ -31,35 +31,35 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
result.Aggregate(s_Sb, (a, b) =>
|
||||||
|
{
|
||||||
|
s_Sb.Append(b);
|
||||||
|
return s_Sb.Append(", ");
|
||||||
|
});
|
||||||
s_Sb.Length -= 2;
|
s_Sb.Length -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_Sb.ToString();
|
return s_Sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Draw(SerializedProperty sp, Material[] mats)
|
public static void Draw(SerializedProperty sp, List<Material> mats)
|
||||||
{
|
{
|
||||||
bool isClicked;
|
var pos = EditorGUILayout.GetControlRect(true);
|
||||||
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
var label = new GUIContent(sp.displayName, sp.tooltip);
|
||||||
{
|
var rect = EditorGUI.PrefixLabel(pos, label);
|
||||||
var pos = EditorGUILayout.GetControlRect(true);
|
var text = sp.hasMultipleDifferentValues
|
||||||
var label = new GUIContent(sp.displayName, sp.tooltip);
|
? "-"
|
||||||
var rect = EditorGUI.PrefixLabel(pos, label);
|
: CollectActiveNames(sp, s_ActiveNames);
|
||||||
var text = sp.hasMultipleDifferentValues
|
|
||||||
? "-"
|
|
||||||
: CollectActiveNames(sp, s_ActiveNames);
|
|
||||||
isClicked = GUI.Button(rect, text, EditorStyles.popup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isClicked) return;
|
if (!GUI.Button(rect, text, EditorStyles.popup)) return;
|
||||||
|
|
||||||
var gm = new GenericMenu();
|
var gm = new GenericMenu();
|
||||||
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, () =>
|
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, x =>
|
||||||
{
|
{
|
||||||
sp.ClearArray();
|
var current = (SerializedProperty)x;
|
||||||
sp.serializedObject.ApplyModifiedProperties();
|
current.ClearArray();
|
||||||
});
|
current.serializedObject.ApplyModifiedProperties();
|
||||||
|
}, sp);
|
||||||
|
|
||||||
if (!sp.hasMultipleDifferentValues)
|
if (!sp.hasMultipleDifferentValues)
|
||||||
{
|
{
|
||||||
|
@ -73,7 +73,7 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
s_Names.Clear();
|
s_Names.Clear();
|
||||||
for (var j = 0; j < mats.Length; j++)
|
for (var j = 0; j < mats.Count; j++)
|
||||||
{
|
{
|
||||||
var mat = mats[j];
|
var mat = mats[j];
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
|
@ -82,8 +82,7 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
var name = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||||
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
|
||||||
if (s_Names.Contains(name)) continue;
|
if (!s_Names.Add(name)) continue;
|
||||||
s_Names.Add(name);
|
|
||||||
|
|
||||||
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
AddMenu(gm, sp, new ShaderProperty(name, type), true);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ using UnityEditor;
|
||||||
using UnityEditor.UI;
|
using UnityEditor.UI;
|
||||||
using UnityEditorInternal;
|
using UnityEditorInternal;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Profiling;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using Coffee.UIParticleExtensions;
|
using Coffee.UIParticleExtensions;
|
||||||
#if UNITY_2021_2_OR_NEWER
|
#if UNITY_2021_2_OR_NEWER
|
||||||
|
@ -42,6 +43,8 @@ namespace Coffee.UIExtensions
|
||||||
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
private static readonly GUIContent s_ContentRandom = new GUIContent("Random");
|
||||||
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
||||||
private static readonly GUIContent s_ContentPrimary = new GUIContent("Primary");
|
private static readonly GUIContent s_ContentPrimary = new GUIContent("Primary");
|
||||||
|
private static readonly Regex s_RegexBuiltInGuid = new Regex(@"^0{16}.0{15}$", RegexOptions.Compiled);
|
||||||
|
private static readonly List<Material> s_TempMaterials = new List<Material>();
|
||||||
private static bool s_XYZMode;
|
private static bool s_XYZMode;
|
||||||
|
|
||||||
private SerializedProperty _maskable;
|
private SerializedProperty _maskable;
|
||||||
|
@ -169,6 +172,7 @@ namespace Coffee.UIExtensions
|
||||||
var current = target as UIParticle;
|
var current = target as UIParticle;
|
||||||
if (!current) return;
|
if (!current) return;
|
||||||
|
|
||||||
|
Profiler.BeginSample("(UIP:E) OnInspectorGUI");
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|
||||||
// Maskable
|
// Maskable
|
||||||
|
@ -180,13 +184,8 @@ namespace Coffee.UIExtensions
|
||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
// AnimatableProperties
|
// AnimatableProperties
|
||||||
var mats = current.particles
|
current.GetMaterials(s_TempMaterials);
|
||||||
.Where(x => x)
|
AnimatablePropertyEditor.Draw(_animatableProperties, s_TempMaterials);
|
||||||
.Select(x => x.GetComponent<ParticleSystemRenderer>().sharedMaterial)
|
|
||||||
.Where(x => x)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
|
|
||||||
|
|
||||||
// Mesh sharing
|
// Mesh sharing
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
|
@ -194,9 +193,12 @@ namespace Coffee.UIExtensions
|
||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
{
|
{
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
foreach (var uip in targets.OfType<UIParticle>())
|
foreach (var t in targets)
|
||||||
{
|
{
|
||||||
uip.ResetGroupId();
|
if (t is UIParticle uip)
|
||||||
|
{
|
||||||
|
uip.ResetGroupId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +206,7 @@ namespace Coffee.UIExtensions
|
||||||
EditorGUILayout.PropertyField(_positionMode);
|
EditorGUILayout.PropertyField(_positionMode);
|
||||||
|
|
||||||
// Auto Scaling
|
// Auto Scaling
|
||||||
DrawAutoScaling(_autoScalingMode, targets.OfType<UIParticle>());
|
EditorGUILayout.PropertyField(_autoScalingMode);
|
||||||
|
|
||||||
// Custom View Size
|
// Custom View Size
|
||||||
EditorGUILayout.PropertyField(_useCustomView);
|
EditorGUILayout.PropertyField(_useCustomView);
|
||||||
|
@ -221,9 +223,7 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
// Target ParticleSystems.
|
// Target ParticleSystems.
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
EditorGUI.BeginDisabledGroup(targets.OfType<UIParticle>().Any(x => !x.canvas));
|
|
||||||
_ro.DoLayoutList();
|
_ro.DoLayoutList();
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
@ -236,7 +236,8 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-UI built-in shader is not supported.
|
// Non-UI built-in shader is not supported.
|
||||||
foreach (var mat in current.materials)
|
Profiler.BeginSample("(UIP:E) Non-UI built-in shader is not supported.");
|
||||||
|
foreach (var mat in s_TempMaterials)
|
||||||
{
|
{
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
var shader = mat.shader;
|
var shader = mat.shader;
|
||||||
|
@ -249,15 +250,18 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
// Does the shader support UI masks?
|
// Does the shader support UI masks?
|
||||||
|
Profiler.BeginSample("(UIP:E) Does the shader support UI masks?");
|
||||||
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
if (current.maskable && current.GetComponentInParent<Mask>(false))
|
||||||
{
|
{
|
||||||
foreach (var mat in current.materials)
|
foreach (var mat in s_TempMaterials)
|
||||||
{
|
{
|
||||||
if (!mat || !mat.shader) continue;
|
if (!mat || !mat.shader) continue;
|
||||||
var shader = mat.shader;
|
var shader = mat.shader;
|
||||||
if (s_Shaders.Contains(shader)) continue;
|
if (!s_Shaders.Add(shader)) continue;
|
||||||
s_Shaders.Add(shader);
|
|
||||||
foreach (var propName in s_MaskablePropertyNames)
|
foreach (var propName in s_MaskablePropertyNames)
|
||||||
{
|
{
|
||||||
if (mat.HasProperty(propName)) continue;
|
if (mat.HasProperty(propName)) continue;
|
||||||
|
@ -271,7 +275,9 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_TempMaterials.Clear();
|
||||||
s_Shaders.Clear();
|
s_Shaders.Clear();
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
// UIParticle for trail should be removed.
|
// UIParticle for trail should be removed.
|
||||||
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
|
||||||
|
@ -310,12 +316,15 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Profiler.EndSample();
|
||||||
|
EditorApplication.delayCall += () => Profiler.enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsBuiltInObject(Object obj)
|
private static bool IsBuiltInObject(Object obj)
|
||||||
{
|
{
|
||||||
return AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
return AssetDatabase.IsMainAsset(obj)
|
||||||
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
|
&& AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
|
||||||
|
&& s_RegexBuiltInGuid.IsMatch(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_2018 || UNITY_2019
|
#if UNITY_2018 || UNITY_2019
|
||||||
|
@ -419,7 +428,7 @@ namespace Coffee.UIExtensions
|
||||||
return showMax;
|
return showMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawAutoScaling(SerializedProperty prop, IEnumerable<UIParticle> uiParticles)
|
private static void DrawAutoScaling(SerializedProperty prop)
|
||||||
{
|
{
|
||||||
EditorGUILayout.PropertyField(prop);
|
EditorGUILayout.PropertyField(prop);
|
||||||
}
|
}
|
||||||
|
|
152
README.md
152
README.md
|
@ -1,4 +1,4 @@
|
||||||
# Particle Effect For UGUI (UI Particle)
|
# <img alt="UIParticleIcon" src="https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/d76e105e-a840-4f61-a1f6-8cf311c0812d" width="26"/> Particle Effect For UGUI (UI Particle)
|
||||||
|
|
||||||
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
|
This package provides a component to render particle effects for uGUI in Unity 2018.2 or later.
|
||||||
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
|
The particle rendering is maskable and sortable, without the need for an extra Camera, RenderTexture, or Canvas.
|
||||||
|
@ -17,45 +17,36 @@ The particle rendering is maskable and sortable, without the need for an extra C
|
||||||
|
|
||||||
## 📝 Description
|
## 📝 Description
|
||||||
|
|
||||||
![](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
|
![Demo](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
|
||||||
|
|
||||||
This package utilizes the new APIs `MeshBake/MashTrailBake` (introduced with Unity 2018.2) to render particles through
|
This package uses the new APIs `MeshBake/MeshTrailBake` (introduced in Unity 2018.2) to render particles through CanvasRenderer.
|
||||||
CanvasRenderer.
|
You can render, mask, and sort your ParticleSystems for UI without the need for an additional Camera, RenderTexture, or Canvas.
|
||||||
You can render, mask, and sort your ParticleSystems for UI without the necessity of an additional Camera, RenderTexture,
|
|
||||||
or Canvas.
|
|
||||||
|
|
||||||
### Features
|
### Key Features
|
||||||
|
|
||||||
* Easy to use: The package is ready to use out of the box.
|
* **Easy to use:** The package is ready to use out of the box.
|
||||||
* Sort particle effects and other UI by sibling index.
|
* **Sortable:** Sort particle effects and other UI elements by sibling index.
|
||||||
* No extra Camera, RenderTexture, or Canvas required.
|
* **Maskable:** Supports `Mask` or `RectMask2D`.
|
||||||
* Masking options for Mask or RectMask2D.
|
* **No extra components required:** No need for an additional `Camera`, `RenderTexture`, or `Canvas`.
|
||||||
* Support for the Trail module.
|
* **Trail module support:** Fully supports the Trail module.
|
||||||
* Support for CanvasGroup alpha.
|
* **CanvasGroup alpha support:** Integrates with `CanvasGroup` alpha.
|
||||||
* No allocations needed to render particles.
|
* **No allocations:** Efficiently renders particles without allocations.
|
||||||
* Compatibility with overlay, camera space, and world space.
|
* **Any canvas render mode support:** Works with overlay, camera space, and world space.
|
||||||
* Support for Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
* **Any Render pipeline support:** Compatible with Universal Render Pipeline (URP) and High Definition Render Pipeline (HDRP).
|
||||||
* Support for disabling `Enter Play Mode Options > Reload Domain`.
|
* **Disabling domain reload support:** Supports disabling `Enter Play Mode Options > Reload Domain`.
|
||||||
* Support for changing material property with AnimationClip (AnimatableProperty).
|
* **Animatable material properties:** Supports changing material properties with AnimationClip (AnimatableProperty).
|
||||||
![AnimatableProperty.gif][AnimatableProperty.gif]
|
![AnimatableProperty.gif](https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif)
|
||||||
* [4.0.0+] Support for 8+ materials.
|
* **Multiple materials:** Supports 8+ materials.
|
||||||
* [4.0.0+] Correct world space particle position adjustment when changing window size for standalone platforms (Windows,
|
* **Correct positioning:** Adjusts world space particle positions correctly when changing window size for standalone platforms (Windows, MacOSX, and Linux).
|
||||||
MacOSX, and Linux).
|
* **Adaptive scaling:** Provides adaptive scaling for UI (AutoScalingMode).
|
||||||
* [4.0.0+] Adaptive scaling for UI.
|
* **Performance optimization:** Mesh sharing group to improve performance.
|
||||||
* [4.0.0+] Mesh sharing group to improve performance.
|
<img alt="MeshSharing.gif" src="https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif" width="450"/>
|
||||||
![MeshSharing.gif][MeshSharing.gif]
|
* **Particle attractor:** Includes a particle attractor component.
|
||||||
* [4.0.0+] Particle attractor component.
|
<img alt="ParticleAttractor.gif" src="https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif" width="450"/>
|
||||||
![ParticleAttractor.gif][ParticleAttractor.gif]
|
* **Emission position mode:** Supports relative/absolute particle emission position modes.
|
||||||
* [4.1.0+] Relative/Absolute particle position mode.
|
<img alt="AbsolutePosition.gif" src="https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif" width="450"/>
|
||||||
![AbsolutePosition.gif][AbsolutePosition.gif]
|
* **Custom view size:** Fixes min/max particle size mismatch.
|
||||||
|
![CustomViewSize.gif](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/dd929959-1a37-420b-b13d-e849022b9c9d)
|
||||||
[AnimatableProperty.gif]: https://user-images.githubusercontent.com/12690315/53286323-2d94a980-37b0-11e9-8afb-c4a207805ff2.gif
|
|
||||||
|
|
||||||
[MeshSharing.gif]: https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif
|
|
||||||
|
|
||||||
[ParticleAttractor.gif]: https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif
|
|
||||||
|
|
||||||
[AbsolutePosition.gif]: https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif
|
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
@ -76,44 +67,55 @@ or Canvas.
|
||||||
|
|
||||||
[JMO]: https://assetstore.unity.com/publishers/1669
|
[JMO]: https://assetstore.unity.com/publishers/1669
|
||||||
|
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
## ⚙ Installation
|
## ⚙ Installation
|
||||||
|
|
||||||
_This package requires Unity 2018.3 or later._
|
_This package requires **Unity 2018.3 or later**._
|
||||||
|
|
||||||
#### Install via OpenUPM
|
#### Install via OpenUPM
|
||||||
|
|
||||||
This package is available on [OpenUPM](https://openupm.com) package registry.
|
- This package is available on [OpenUPM](https://openupm.com) package registry.
|
||||||
This is the preferred method of installation, as you can easily receive updates as they're released.
|
- This is the preferred method of installation, as you can easily receive updates as they're released.
|
||||||
|
- If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your project's directory:
|
||||||
|
```
|
||||||
|
openupm add com.coffee.ui-particle
|
||||||
|
```
|
||||||
|
- To update the package, use Package Manager UI (`Window > Package Manager`) or run the following command with `@{version}`:
|
||||||
|
```
|
||||||
|
openupm add com.coffee.ui-particle@4.8.0
|
||||||
|
```
|
||||||
|
|
||||||
If you have [openupm-cli](https://github.com/openupm/openupm-cli) installed, then run the following command in your
|
#### Install via UPM (with Package Manager UI)
|
||||||
project's directory:
|
|
||||||
|
|
||||||
```sh
|
- Click `Window > Package Manager` to open Package Manager UI.
|
||||||
openupm add com.coffee.ui-particle
|
- Click `+ > Add package from git URL...` and input the repository URL: `https://github.com/mob-sakai/ParticleEffectForUGUI.git`
|
||||||
```
|
![](https://gist.github.com/assets/12690315/24af63ed-8a2e-483d-9023-7aa53d913330)
|
||||||
|
- To update the package, change suffix `#{version}` to the target version.
|
||||||
|
- e.g. `https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.8.0`
|
||||||
|
|
||||||
#### Install via UPM (using Git URL)
|
#### Install via UPM (Manually)
|
||||||
|
|
||||||
Navigate to your project's Packages folder and open the `manifest.json` file. Then add this package somewhere in
|
- Open the `Packages/manifest.json` file in your project. Then add this package somewhere in the `dependencies` block:
|
||||||
the `dependencies` block:
|
```json
|
||||||
|
{
|
||||||
```json
|
"dependencies": {
|
||||||
{
|
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
|
||||||
"dependencies": {
|
...
|
||||||
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git",
|
}
|
||||||
...
|
|
||||||
}
|
}
|
||||||
}
|
```
|
||||||
```
|
|
||||||
|
|
||||||
To update the package, change suffix `#{version}` to the target version.
|
- To update the package, change suffix `#{version}` to the target version.
|
||||||
|
- e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.8.0",`
|
||||||
|
|
||||||
* e.g. `"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#4.6.0",`
|
#### Install as Embedded Package
|
||||||
|
|
||||||
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
|
1. Download a source code zip file from [Releases](https://github.com/mob-sakai/ParticleEffectForUGUI.git/releases) and extract it.
|
||||||
|
2. Place it in your project's `Packages` directory.
|
||||||
|
![](https://github.com/mob-sakai/mob-sakai/assets/12690315/0b7484b4-5fca-43b0-a9ef-e5dbd99bcdb4)
|
||||||
|
- If you want to fix bugs or add features, install it as an embedded package.
|
||||||
|
- To update the package, you need to re-download it and replace the contents.
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
@ -123,19 +125,28 @@ Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to insta
|
||||||
|
|
||||||
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
`UIParticle` controls the ParticleSystems that are attached to its own game objects and child game objects.
|
||||||
|
|
||||||
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/3559df45-63e7-4c4c-9233-f455779efa29)
|
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/1cf5753b-33fc-4cef-91c3-413c515a954f)
|
||||||
|
|
||||||
- **Maskable**: Does this graphic allow masking.
|
- **Maskable**: Does this graphic allow maskable.
|
||||||
- **Scale**: Scale the rendering. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
- **Scale**: Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.
|
||||||
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
|
- **Animatable Properties**: If you want to update material properties (e.g., `_MainTex_ST`, `_Color`) in AnimationClip,
|
||||||
use this to mark the changes.
|
use this to mark as animatable.
|
||||||
- **Mesh Sharing**: Particle simulation results are shared within the same group. A large number of the same effects can
|
- **Mesh Sharing**: Particle simulation results are shared within the same group. A large number of the same effects can
|
||||||
be displayed with a small load. When the `Random` toggle is enabled, it will be grouped randomly.
|
be displayed with a small load. When the `Random` toggle is enabled, it will be grouped randomly.
|
||||||
|
- **None:** Disable mesh sharing.
|
||||||
|
- **Auto:** Automatically select Primary/Replica.
|
||||||
|
- **Primary:** Provides particle simulation results to the same group.
|
||||||
|
- **Primary Simulator:** Primary, but do not render the particle (simulation only).
|
||||||
|
- **Replica:** Render simulation results provided by the primary.
|
||||||
- **Position Mode**: Emission position mode.
|
- **Position Mode**: Emission position mode.
|
||||||
- **Absolute:** Emit from the world position of the `ParticleSystem`.
|
- **Absolute:** The particles will be emitted from the world position.
|
||||||
- **Relative:** Emit from the scaled position of the `ParticleSystem`.
|
- **Relative:** The particles will be emitted from the scaled position.
|
||||||
- **Auto Scaling**: `Transform.lossyScale` (=world scale) will be set to `(1, 1, 1)` on update. It prevents the
|
- **Auto Scaling Mode**: How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
|
||||||
root-Canvas scale from affecting the hierarchy-scaled `ParticleSystem`.
|
- **None:** Do nothing.
|
||||||
|
- **Transform:** Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
||||||
|
- **UIParticle:** UIParticle.scale will be adjusted.
|
||||||
|
- **Use Custom View:** Use this if the particles are not displayed correctly due to min/max particle size.
|
||||||
|
- **Custom view size:** Change the bake view size.
|
||||||
- **Rendering Order**: The ParticleSystem list to be rendered. You can change the order and the materials.
|
- **Rendering Order**: The ParticleSystem list to be rendered. You can change the order and the materials.
|
||||||
|
|
||||||
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
|
**NOTE:** Press the `Refresh` button to reconstruct the rendering order based on children ParticleSystem's sorting order
|
||||||
|
@ -176,9 +187,10 @@ section.
|
||||||
### Script usage
|
### Script usage
|
||||||
|
|
||||||
```cs
|
```cs
|
||||||
// Instant ParticleSystem prefab with UIParticle on runtime.
|
// Instantiate ParticleSystem prefab with UIParticle on runtime.
|
||||||
var go = GameObject.Instantiate(prefab);
|
var go = GameObject.Instantiate(prefab);
|
||||||
var uiParticle = go.AddComponent<UIParticle>();
|
var uiParticle = go.AddComponent<UIParticle>();
|
||||||
|
uiParticle.scale = 100;
|
||||||
|
|
||||||
// Control by ParticleSystem.
|
// Control by ParticleSystem.
|
||||||
particleSystem.Play();
|
particleSystem.Play();
|
||||||
|
@ -195,7 +207,7 @@ uiParticle.Stop();
|
||||||
|
|
||||||
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
|
||||||
|
|
||||||
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/ea6ae0ed-f9a8-437c-8baa-47526303391e)
|
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/5c20ad73-4b9a-4f38-9cdc-119df5cce077)
|
||||||
![](https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif)
|
![](https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif)
|
||||||
|
|
||||||
- **Particle System**: Attracts particles generated by the specified particle system.
|
- **Particle System**: Attracts particles generated by the specified particle system.
|
||||||
|
|
|
@ -44,23 +44,26 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
[Obsolete]
|
||||||
internal bool m_IsTrail;
|
internal bool m_IsTrail;
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[FormerlySerializedAs("m_IgnoreParent")]
|
[FormerlySerializedAs("m_IgnoreParent")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
[Obsolete]
|
||||||
private bool m_IgnoreCanvasScaler;
|
private bool m_IgnoreCanvasScaler;
|
||||||
|
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool m_AbsoluteMode;
|
[Obsolete]
|
||||||
|
internal bool m_AbsoluteMode;
|
||||||
|
|
||||||
[Tooltip("Particle effect scale")]
|
[Tooltip("Scale the rendering particles. When the `3D` toggle is enabled, 3D scale (x, y, z) is supported.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
private Vector3 m_Scale3D = new Vector3(10, 10, 10);
|
||||||
|
|
||||||
[Tooltip("Animatable material properties.\n" +
|
[Tooltip("If you want to update material properties (e.g. _MainTex_ST, _Color) in AnimationClip, " +
|
||||||
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
|
"use this to mark as animatable.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
|
||||||
|
|
||||||
|
@ -68,12 +71,13 @@ namespace Coffee.UIExtensions
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
|
||||||
|
|
||||||
[Tooltip("Mesh sharing.\n" +
|
[Tooltip("Particle simulation results are shared within the same group. " +
|
||||||
"None: disable mesh sharing.\n" +
|
"A large number of the same effects can be displayed with a small load.\n" +
|
||||||
"Auto: automatically select Primary/Replica.\n" +
|
"None: Disable mesh sharing.\n" +
|
||||||
"Primary: provides particle simulation results to the same group.\n" +
|
"Auto: Automatically select Primary/Replica.\n" +
|
||||||
|
"Primary: Provides particle simulation results to the same group.\n" +
|
||||||
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
"Primary Simulator: Primary, but do not render the particle (simulation only).\n" +
|
||||||
"Replica: render simulation results provided by the primary.")]
|
"Replica: Render simulation results provided by the primary.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private MeshSharing m_MeshSharing = MeshSharing.None;
|
private MeshSharing m_MeshSharing = MeshSharing.None;
|
||||||
|
|
||||||
|
@ -85,18 +89,22 @@ namespace Coffee.UIExtensions
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int m_GroupMaxId;
|
private int m_GroupMaxId;
|
||||||
|
|
||||||
[Tooltip("Relative: The particles will be emitted from the scaled position of ParticleSystem.\n" +
|
[Tooltip("Emission position mode.\n" +
|
||||||
"Absolute: The particles will be emitted from the world position of ParticleSystem.")]
|
"Relative: The particles will be emitted from the scaled position.\n" +
|
||||||
|
"Absolute: The particles will be emitted from the world position.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private PositionMode m_PositionMode = PositionMode.Relative;
|
private PositionMode m_PositionMode = PositionMode.Relative;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Tooltip("Prevent the root-Canvas scale from affecting the hierarchy-scaled ParticleSystem.")]
|
[Obsolete]
|
||||||
private bool m_AutoScaling = true;
|
internal bool m_AutoScaling;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
[Tooltip("Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1)." +
|
[Tooltip(
|
||||||
"UIParticle: UIParticle.scale will be adjusted.")]
|
"How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.\n" +
|
||||||
|
"None: Do nothing.\n" +
|
||||||
|
"Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).\n" +
|
||||||
|
"UIParticle: UIParticle.scale will be adjusted.")]
|
||||||
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
private AutoScalingMode m_AutoScalingMode = AutoScalingMode.Transform;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
@ -110,11 +118,12 @@ namespace Coffee.UIExtensions
|
||||||
private float m_CustomViewSize = 10;
|
private float m_CustomViewSize = 10;
|
||||||
|
|
||||||
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
|
||||||
private int _groupId;
|
|
||||||
private Camera _bakeCamera;
|
private Camera _bakeCamera;
|
||||||
private DrivenRectTransformTracker _tracker;
|
private Canvas _canvas;
|
||||||
private Vector3 _storedScale;
|
private int _groupId;
|
||||||
private bool _isScaleStored;
|
private bool _isScaleStored;
|
||||||
|
private Vector3 _storedScale;
|
||||||
|
private DrivenRectTransformTracker _tracker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should this graphic be considered a target for ray-casting?
|
/// Should this graphic be considered a target for ray-casting?
|
||||||
|
@ -126,7 +135,8 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mesh sharing.
|
/// Particle simulation results are shared within the same group.
|
||||||
|
/// A large number of the same effects can be displayed with a small load.
|
||||||
/// None: disable mesh sharing.
|
/// None: disable mesh sharing.
|
||||||
/// Auto: automatically select Primary/Replica.
|
/// Auto: automatically select Primary/Replica.
|
||||||
/// Primary: provides particle simulation results to the same group.
|
/// Primary: provides particle simulation results to the same group.
|
||||||
|
@ -169,9 +179,9 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Particle position mode.
|
/// Emission position mode.
|
||||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
/// Relative: The particles will be emitted from the scaled position.
|
||||||
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
/// Absolute: The particles will be emitted from the world position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PositionMode positionMode
|
public PositionMode positionMode
|
||||||
{
|
{
|
||||||
|
@ -184,6 +194,7 @@ namespace Coffee.UIExtensions
|
||||||
/// Relative: The particles will be emitted from the scaled position of the ParticleSystem.
|
/// 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.
|
/// Absolute: The particles will be emitted from the world position of the ParticleSystem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("The absoluteMode is now obsolete. Please use the autoScalingMode instead.", false)]
|
||||||
public bool absoluteMode
|
public bool absoluteMode
|
||||||
{
|
{
|
||||||
get => m_PositionMode == PositionMode.Absolute;
|
get => m_PositionMode == PositionMode.Absolute;
|
||||||
|
@ -201,8 +212,12 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Auto scaling mode.
|
/// How to automatically adjust when the Canvas scale is changed by the screen size or reference resolution.
|
||||||
|
/// <para/>
|
||||||
|
/// None: Do nothing.
|
||||||
|
/// <para/>
|
||||||
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
/// Transform: Transform.lossyScale (=world scale) will be set to (1, 1, 1).
|
||||||
|
/// <para/>
|
||||||
/// UIParticle: UIParticle.scale will be adjusted.
|
/// UIParticle: UIParticle.scale will be adjusted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AutoScalingMode autoScalingMode
|
public AutoScalingMode autoScalingMode
|
||||||
|
@ -286,24 +301,6 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
public List<ParticleSystem> particles => m_Particles;
|
public List<ParticleSystem> particles => m_Particles;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get all base materials to render.
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<Material> materials
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
|
||||||
{
|
|
||||||
var r = _renderers[i];
|
|
||||||
if (!r || !r.material) continue;
|
|
||||||
yield return r.material;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Material materialForRendering => null;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Paused.
|
/// Paused.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -358,12 +355,20 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This function is called when a direct or indirect parent of the transform of the GameObject has changed.
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnTransformParentChanged()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
if (m_IgnoreCanvasScaler || m_AutoScaling)
|
||||||
{
|
{
|
||||||
m_IgnoreCanvasScaler = false;
|
m_IgnoreCanvasScaler = false;
|
||||||
|
@ -376,31 +381,47 @@ namespace Coffee.UIExtensions
|
||||||
m_AbsoluteMode = false;
|
m_AbsoluteMode = false;
|
||||||
m_PositionMode = PositionMode.Absolute;
|
m_PositionMode = PositionMode.Absolute;
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CS0612 // Type or member is obsolete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Play the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Simulate(0, false, true));
|
particles.Exec(p => p.Simulate(0, false, true));
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pause the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Pause()
|
public void Pause()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Pause());
|
particles.Exec(p => p.Pause());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpause the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Resume()
|
public void Resume()
|
||||||
{
|
{
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Stop());
|
particles.Exec(p => p.Stop());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start emission of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void StartEmission()
|
public void StartEmission()
|
||||||
{
|
{
|
||||||
particles.Exec(p =>
|
particles.Exec(p =>
|
||||||
|
@ -410,6 +431,9 @@ namespace Coffee.UIExtensions
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop emission of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void StopEmission()
|
public void StopEmission()
|
||||||
{
|
{
|
||||||
particles.Exec(p =>
|
particles.Exec(p =>
|
||||||
|
@ -419,17 +443,41 @@ namespace Coffee.UIExtensions
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear the particles of the ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
particles.Exec(p => p.Clear());
|
particles.Exec(p => p.Clear());
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all base materials to render.
|
||||||
|
/// </summary>
|
||||||
|
public void GetMaterials(List<Material> result)
|
||||||
|
{
|
||||||
|
if (result == null) return;
|
||||||
|
|
||||||
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
|
{
|
||||||
|
var r = _renderers[i];
|
||||||
|
if (!r || !r.material) continue;
|
||||||
|
result.Add(r.material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using the ParticleSystem instance.
|
||||||
|
/// </summary>
|
||||||
public void SetParticleSystemInstance(GameObject instance)
|
public void SetParticleSystemInstance(GameObject instance)
|
||||||
{
|
{
|
||||||
SetParticleSystemInstance(instance, true);
|
SetParticleSystemInstance(instance, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using the ParticleSystem instance.
|
||||||
|
/// </summary>
|
||||||
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
|
||||||
{
|
{
|
||||||
if (!instance) return;
|
if (!instance) return;
|
||||||
|
@ -455,6 +503,10 @@ namespace Coffee.UIExtensions
|
||||||
RefreshParticles(instance);
|
RefreshParticles(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using the prefab.
|
||||||
|
/// The prefab is automatically instantiated.
|
||||||
|
/// </summary>
|
||||||
public void SetParticleSystemPrefab(GameObject prefab)
|
public void SetParticleSystemPrefab(GameObject prefab)
|
||||||
{
|
{
|
||||||
if (!prefab) return;
|
if (!prefab) return;
|
||||||
|
@ -462,16 +514,31 @@ namespace Coffee.UIExtensions
|
||||||
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle.
|
||||||
|
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
||||||
|
/// </summary>
|
||||||
public void RefreshParticles()
|
public void RefreshParticles()
|
||||||
{
|
{
|
||||||
RefreshParticles(gameObject);
|
RefreshParticles(gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh UIParticle.
|
||||||
|
/// Collect ParticleSystems under the GameObject and refresh the UIParticle.
|
||||||
|
/// </summary>
|
||||||
private void RefreshParticles(GameObject root)
|
private void RefreshParticles(GameObject root)
|
||||||
{
|
{
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
root.GetComponentsInChildren(true, particles);
|
root.GetComponentsInChildren(true, particles);
|
||||||
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
|
for (var i = particles.Count - 1; 0 <= i; i--)
|
||||||
|
{
|
||||||
|
var ps = particles[i];
|
||||||
|
if (!ps || ps.GetComponentInParent<UIParticle>(true) != this)
|
||||||
|
{
|
||||||
|
particles.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < particles.Count; i++)
|
for (var i = 0; i < particles.Count; i++)
|
||||||
{
|
{
|
||||||
|
@ -486,31 +553,39 @@ namespace Coffee.UIExtensions
|
||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshParticles(List<ParticleSystem> particles)
|
/// <summary>
|
||||||
|
/// Refresh UIParticle using a list of ParticleSystems.
|
||||||
|
/// </summary>
|
||||||
|
public void RefreshParticles(List<ParticleSystem> particleSystems)
|
||||||
{
|
{
|
||||||
|
// Collect children UIParticleRenderer components.
|
||||||
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
|
||||||
_renderers.Clear();
|
_renderers.Clear();
|
||||||
foreach (Transform child in transform)
|
var childCount = transform.childCount;
|
||||||
|
for (var i = 0; i < childCount; i++)
|
||||||
{
|
{
|
||||||
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
|
var child = transform.GetChild(i);
|
||||||
|
if (child.TryGetComponent(out UIParticleRenderer uiParticleRenderer))
|
||||||
if (uiParticleRenderer != null)
|
|
||||||
{
|
{
|
||||||
_renderers.Add(uiParticleRenderer);
|
_renderers.Add(uiParticleRenderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the UIParticleRenderer components.
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
_renderers[i].Reset(i);
|
_renderers[i].Reset(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the ParticleSystem to the UIParticleRenderer. If the trail is enabled, set it additionally.
|
||||||
var j = 0;
|
var j = 0;
|
||||||
for (var i = 0; i < particles.Count; i++)
|
for (var i = 0; i < particleSystems.Count; i++)
|
||||||
{
|
{
|
||||||
var ps = particles[i];
|
var ps = particleSystems[i];
|
||||||
if (!ps) continue;
|
if (!ps) continue;
|
||||||
GetRenderer(j++).Set(this, ps, false);
|
GetRenderer(j++).Set(this, ps, false);
|
||||||
|
|
||||||
|
// If the trail is enabled, set it additionally.
|
||||||
if (ps.trails.enabled)
|
if (ps.trails.enabled)
|
||||||
{
|
{
|
||||||
GetRenderer(j++).Set(this, ps, true);
|
GetRenderer(j++).Set(this, ps, true);
|
||||||
|
@ -556,11 +631,10 @@ namespace Coffee.UIExtensions
|
||||||
for (var i = 0; i < _renderers.Count; i++)
|
for (var i = 0; i < _renderers.Count; i++)
|
||||||
{
|
{
|
||||||
var r = _renderers[i];
|
var r = _renderers[i];
|
||||||
if (!r)
|
if (r) continue;
|
||||||
{
|
|
||||||
RefreshParticles(particles);
|
RefreshParticles(particles);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var bakeCamera = GetBakeCamera();
|
var bakeCamera = GetBakeCamera();
|
||||||
|
@ -568,6 +642,7 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
var r = _renderers[i];
|
var r = _renderers[i];
|
||||||
if (!r) continue;
|
if (!r) continue;
|
||||||
|
|
||||||
r.UpdateMesh(bakeCamera);
|
r.UpdateMesh(bakeCamera);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace Coffee.UIExtensions
|
||||||
private Material _currentMaterialForRendering;
|
private Material _currentMaterialForRendering;
|
||||||
private bool _delay;
|
private bool _delay;
|
||||||
private int _index;
|
private int _index;
|
||||||
|
private bool _isPrevStored;
|
||||||
private bool _isTrail;
|
private bool _isTrail;
|
||||||
private Bounds _lastBounds;
|
private Bounds _lastBounds;
|
||||||
private Material _modifiedMaterial;
|
private Material _modifiedMaterial;
|
||||||
|
@ -39,9 +40,8 @@ namespace Coffee.UIExtensions
|
||||||
private float _prevCanvasScale;
|
private float _prevCanvasScale;
|
||||||
private Vector3 _prevPsPos;
|
private Vector3 _prevPsPos;
|
||||||
private Vector3 _prevScale;
|
private Vector3 _prevScale;
|
||||||
private bool _isPrevStored;
|
|
||||||
private Vector2Int _prevScreenSize;
|
private Vector2Int _prevScreenSize;
|
||||||
private bool _prewarm;
|
private bool _preWarm;
|
||||||
private ParticleSystemRenderer _renderer;
|
private ParticleSystemRenderer _renderer;
|
||||||
|
|
||||||
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
public override Texture mainTexture => _isTrail ? null : _particleSystem.GetTextureForSprite();
|
||||||
|
@ -111,8 +111,7 @@ namespace Coffee.UIExtensions
|
||||||
if (this && isActiveAndEnabled)
|
if (this && isActiveAndEnabled)
|
||||||
{
|
{
|
||||||
material = null;
|
material = null;
|
||||||
workerMesh.Clear();
|
canvasRenderer.Clear();
|
||||||
canvasRenderer.SetMesh(workerMesh);
|
|
||||||
_lastBounds = new Bounds();
|
_lastBounds = new Bounds();
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
|
@ -221,20 +220,20 @@ namespace Coffee.UIExtensions
|
||||||
gameObject.layer = parent.gameObject.layer;
|
gameObject.layer = parent.gameObject.layer;
|
||||||
|
|
||||||
_particleSystem = ps;
|
_particleSystem = ps;
|
||||||
_prewarm = _particleSystem.main.prewarm;
|
_preWarm = _particleSystem.main.prewarm;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (_particleSystem.isPlaying || _prewarm)
|
if (_particleSystem.isPlaying || _preWarm)
|
||||||
{
|
{
|
||||||
_particleSystem.Clear();
|
_particleSystem.Clear();
|
||||||
_particleSystem.Pause();
|
_particleSystem.Pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderer = ps.GetComponent<ParticleSystemRenderer>();
|
ps.TryGetComponent(out _renderer);
|
||||||
_renderer.enabled = false;
|
_renderer.enabled = false;
|
||||||
|
|
||||||
//_emitter = emitter;
|
//_emitter = emitter;
|
||||||
|
@ -563,10 +562,7 @@ namespace Coffee.UIExtensions
|
||||||
return Matrix4x4.Scale(scale);
|
return Matrix4x4.Scale(scale);
|
||||||
case ParticleSystemSimulationSpace.Custom:
|
case ParticleSystemSimulationSpace.Custom:
|
||||||
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
|
||||||
//* Matrix4x4.Translate(wpos)
|
* Matrix4x4.Scale(scale);
|
||||||
* Matrix4x4.Scale(scale)
|
|
||||||
//* Matrix4x4.Translate(-wpos)
|
|
||||||
;
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
@ -582,7 +578,8 @@ namespace Coffee.UIExtensions
|
||||||
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
var screenSize = new Vector2Int(Screen.width, Screen.height);
|
||||||
var isWorldSpace = _particleSystem.IsWorldSpace();
|
var isWorldSpace = _particleSystem.IsWorldSpace();
|
||||||
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
var canvasScale = _parent.canvas ? _parent.canvas.scaleFactor : 1f;
|
||||||
var resolutionChanged = _prevScreenSize != screenSize || _prevCanvasScale != canvasScale;
|
var resolutionChanged = _prevScreenSize != screenSize
|
||||||
|
|| !Mathf.Approximately(_prevCanvasScale, canvasScale);
|
||||||
if (resolutionChanged && isWorldSpace && _isPrevStored)
|
if (resolutionChanged && isWorldSpace && _isPrevStored)
|
||||||
{
|
{
|
||||||
// Update particle array size and get particles.
|
// Update particle array size and get particles.
|
||||||
|
@ -590,7 +587,7 @@ namespace Coffee.UIExtensions
|
||||||
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
var particles = ParticleSystemExtensions.GetParticleArray(size);
|
||||||
_particleSystem.GetParticles(particles, size);
|
_particleSystem.GetParticles(particles, size);
|
||||||
|
|
||||||
// Resolusion resolver:
|
// Resolution resolver:
|
||||||
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
|
||||||
var modifier = psPos.GetScaled(
|
var modifier = psPos.GetScaled(
|
||||||
scale.Inverse(),
|
scale.Inverse(),
|
||||||
|
@ -625,11 +622,11 @@ namespace Coffee.UIExtensions
|
||||||
? Time.unscaledDeltaTime
|
? Time.unscaledDeltaTime
|
||||||
: Time.deltaTime;
|
: Time.deltaTime;
|
||||||
|
|
||||||
// Prewarm:
|
// Pre-warm:
|
||||||
if (0 < deltaTime && _prewarm)
|
if (0 < deltaTime && _preWarm)
|
||||||
{
|
{
|
||||||
deltaTime += main.duration;
|
deltaTime += main.duration;
|
||||||
_prewarm = false;
|
_preWarm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get world position.
|
// get world position.
|
||||||
|
|
|
@ -39,8 +39,9 @@ namespace Coffee.UIExtensions
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
[InitializeOnLoadMethod]
|
[InitializeOnLoadMethod]
|
||||||
|
#else
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||||
#endif
|
#endif
|
||||||
[RuntimeInitializeOnLoadMethod]
|
|
||||||
private static void InitializeOnLoad()
|
private static void InitializeOnLoad()
|
||||||
{
|
{
|
||||||
Canvas.willRenderCanvases -= Refresh;
|
Canvas.willRenderCanvases -= Refresh;
|
||||||
|
|
Loading…
Reference in New Issue