备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: mob-sakai # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: mob_sakai # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -0,0 +1,48 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
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)**
- 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. 2021.3.7f1]
- Project options: [e.g. Mono/IL2CPP, .Net Standard 2.1/.Net 4.x, URP/HDRP, GraphicAPIs]
**Additional context**
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

@@ -0,0 +1,26 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
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 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

@@ -0,0 +1,16 @@
---
name: Question
about: Ask a question about this project
title: ''
labels: question
assignees: mob-sakai
---
NOTE: Your issue may already be reported! Please search on the [issue tracker](../) before creating one.
**Describe what help do you need**
A description of the question.
**Additional context**
Add any other context or screenshots about the question here.

View File

@@ -0,0 +1,24 @@
name: release
on:
push:
branches:
- preview
- main
- v*.x
tags-ignore:
- "**"
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cycjimmy/semantic-release-action@v3
with:
extra_plugins: |
@semantic-release/changelog
@semantic-release/git
env:
GITHUB_TOKEN: ${{ github.token }}

View File

@@ -0,0 +1,69 @@
# Secrets
# UNITY_LICENSE:
name: test
on:
push:
branches:
- develop
tags:
- "!*"
pull_request:
types:
- opened
- synchronize
jobs:
setup:
runs-on: ubuntu-latest
outputs:
versions: ${{ steps.setup.outputs.versions }}
steps:
- id: setup
run: |
VERSIONS=`npx unity-changeset list --versions --all --latest-patch --min 2018.3 --json`
echo "==== Target Unity Versions ===="
echo "${VERSIONS}"
echo "::set-output name=versions::${VERSIONS}"
test:
runs-on: ubuntu-latest
needs: setup
strategy:
fail-fast: false
matrix:
version: ${{ fromJson(needs.setup.outputs.versions) }}
steps:
# Checkout sandbox project
- uses: actions/checkout@v3
with:
ref: sandbox
submodules: true
fetch-depth: 0
# Update package submodule
- name: "Update package submodule"
working-directory: Packages/dev
run: git checkout ${{ github.sha }}
# Cache
- uses: actions/cache@v3
with:
path: Library
key: Library-${{ matrix.version }}-${{ github.sha }}
restore-keys: |
Library-${{ matrix.version }}-
Library-
# Run tests
- name: "Run tests"
uses: game-ci/unity-test-runner@v2
with:
customImage: mobsakai/unity3d:${{ matrix.version }}
customParameters: -nographics
# unityVersion: ${{ matrix.version }}
checkName: ${{ matrix.version }} Test Results
githubToken: ${{ github.token }}
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}

View File

@@ -0,0 +1,25 @@
{
"branches": [
"+([0-9])?(.{+([0-9]),x}).x",
"master",
"main",
{
"name": "preview",
"prerelease": true
}
],
"tagFormat": "${version}",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
[
"@semantic-release/npm",
{
"npmPublish": false
}
],
"@semantic-release/git",
"@semantic-release/github"
]
}

View File

@@ -0,0 +1,941 @@
## [4.2.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.2.0...4.2.1) (2023-08-18)
### Bug Fixes
* autoScaling and PositionMode may be locked ([3f2f12d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3f2f12d2cf7541118c02830ec9fdea8183357487))
# [4.2.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.7...4.2.0) (2023-08-18)
### Bug Fixes
* assertion 'ps->array_size()' in UpdateMesh() when using trails of type ribbon ([f75fcce](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f75fcce0dae0bc166bd01d36a150aded1fd721f3)), closes [#241](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/241)
* built-in shaders are no longer supported ([c2119c1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c2119c171a1262431eac7fea6bf3125db2bcaaca)), closes [#233](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/233) [#257](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/257)
* crash occurs when too many vertices are rendered ([723a04d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/723a04d0cfd156715a3c92b6d6bd75fdc1862c28))
* error: SerializedObject target has been destroyed ([e930516](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e93051603e121732c92bcd89ded48087c2b0d7fb)), closes [#267](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/267)
* excessive particle emitted on move ParticleSystem for local space simulation and emission over distance ([2fe0bde](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2fe0bde422f9769dfedaf6b053ea07f773646679)), closes [#265](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/265)
* fix typos ([52f2ef1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/52f2ef1f2471a2e1c29fca96255c04b222d9c848))
* generated GameObject will be named '[generated] *' ([9b2e5c1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9b2e5c1d1024e091de6d18a4578cd18b43563e48))
* inactive ParticleSystems are removed from the list on refresh ([4851a18](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4851a1880eef9f385dd9db644ea7e544f95da4fc))
* mesh sharing not working ([8b4ca1a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8b4ca1add5c409601e840253e1c0dbcdbf536da8)), closes [#236](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/236)
* nullptr exceptions when using nested UIParticle components in hierarchy ([e67e948](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e67e9482e2cb840b16e2cfe76e04f7423fcbd3a3)), closes [#246](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/246)
* nullReferenceException after copy-n-paste ([425aad0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/425aad0cbab475635c72bee84ecbf3f2acedccc2)), closes [#258](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/258)
* remove unnecessary per-frame allocation. ([e92b514](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e92b514624cc362e53ddeae5ade20fa732f94c7c))
* scaling ParticleSystem puts prewarmed particles in wrong location ([fb31db4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fb31db47f2debb3aadbdc4d1b88d0efd9c4ad7bd)), closes [#235](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/235)
* sub-emitters option is not work in editor playing ([b308b26](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b308b2683372662bb834b6f6d23ea3435a68d1b3)), closes [#231](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/231)
* the camera under UIParticle will be assigned as _orthoCamera ([c42f8c8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c42f8c8ab0ff033689349a81e02a4808e071a8a2))
* UIParticleAttractor attracts the particles at wrong position when in RelativeMode ([68d9925](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/68d9925a16237df3c7b07b4781172cbd03425421)), closes [#262](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/262)
### Features
* 'AbsoluteMode' option is renamed to 'PositionMode' ([67eff61](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/67eff610736344ba0122163ff5ee63b25c43f555))
* 'AutoScaling' option will be imported from 'IgnoreCanvasScale' (for v3.x) ([4103041](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/410304125f3f25f3f543c7bc01dcc661eab00609))
* add 'AutoScaling' option for UIParticle ([35325c8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/35325c88996fa6aea19a6dd1395c05884e1f84ae))
* add 'UpdateMode' option for UIParticleAttractor ([903f702](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/903f702d7be38228841a5a693e3afdceb4a59d9f)), closes [#250](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/250)
* add particle system getter and setter for attractor ([a4bcf93](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a4bcf93022d2729f3d2a74a2cac4f52e68641b18)), closes [#253](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/253)
* add public properties for UIParticleAttractor ([392ab6d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/392ab6dd76c36e815320d3a50744d19faa631260)), closes [#253](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/253)
* add Start/StopEmission API for UIParticle ([e499836](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e4998365c9825fa385e0a317768ce073a1f15b48)), closes [#240](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/240)
## [4.1.7](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.6...4.1.7) (2022-08-30)
### Bug Fixes
* the annoying empty black scene overlay box shown even when nothing is selected ([bdeeabb](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/bdeeabbbe140b0ba80fac7ac477874c2467d3a16))
## [4.1.6](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.5...4.1.6) (2022-08-10)
### Bug Fixes
* fix abnormal mesh bounds error ([f60d6df](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f60d6dfe6030ac89527a4265e414e9a0a20d56db)), closes [#213](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/213) [#218](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/218)
## [4.1.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.4...4.1.5) (2022-08-10)
### Bug Fixes
* fix culling for RectMask2D ([9e2dbe7](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9e2dbe7758eb28a4f6a7c11113d9169847880f96)), closes [#220](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/220)
## [4.1.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.3...4.1.4) (2022-07-01)
### Bug Fixes
* add `Enabled` toggle in overlay window ([f97e619](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f97e6195e62b5acfa8f3e97bfe3bc4a7dcadf38a))
* if `m_Particles` contains null, an error will occur ([550d0c4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/550d0c43be35cd07e390ffd5749557c89fee0332)), closes [#214](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/214)
* ParticleSystem reordering and refreshing in inspector does not work for prefab asset ([7eb4112](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7eb41124db06ea794db76788b35ce82a0af2c402))
* refresh button does not works in prefab edit mode ([c1538a8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c1538a83998608a30dc90944b05f8b75e165cf05)), closes [#214](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/214)
* when `UIParticlrRenderer` destroy manually, an error will occur ([a11d2d0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a11d2d01ce5f67e3f430bcb0bfdee1ad9abf7cfe))
## [4.1.3](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.2...4.1.3) (2022-06-28)
### Bug Fixes
* error on drag prefab to scene ([fa2f867](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fa2f867bcaff437bb9420da1abcef970cdb09ade)), closes [#211](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/211)
## [4.1.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.1...4.1.2) (2022-06-27)
### Bug Fixes
* error on editor ([8034228](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/80342287137c07d58a7492875a401d80cb134073)), closes [#210](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/210)
* incorrect position of world space trail particles ([fb7f308](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fb7f308f092db8a1512383857b80110cd626ecf9)), closes [#209](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/209)
## [4.1.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.1.0...4.1.1) (2022-06-25)
### Bug Fixes
* add absolute mode toggle to overlay window ([48d1994](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/48d1994f5f8751b707b6ef7695b552df731bece9))
# [4.1.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.0.1...4.1.0) (2022-06-25)
### Features
* add relative/absolute particle position mode ([1879ac8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1879ac8c538778e386e68cfc989a6f4f974043ca)), closes [#205](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/205)
## [4.0.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/4.0.0...4.0.1) (2022-06-24)
### Bug Fixes
* overlays do not exist in Unity 2019.2-2021.1 ([cd8e037](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/cd8e0372b63bb6feaaf053518013a641bc7e65ac)), closes [#207](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/207) [#208](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/208)
# [4.0.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.12...4.0.0) (2022-06-21)
### Bug Fixes
* correct world space particle position when changing screen size ([c6644a2](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c6644a213263375c7a35b5082ef4b71cc58964e6))
* keep properly canvas batches ([d8e96e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d8e96e69a62dff7a451eaed32c7a814e7e62dbb9))
### Features
* adaptive scaling for UI ([aa0d56f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/aa0d56f9faa05e9679d4b476bcf135eafb1b8af9))
* add overlay window for UIParticle ([7b21c50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7b21c500ef78103b605fdca71051d2357b09602f))
* add particle attractor component ([386170c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/386170cbf68ebf59d4510fe0a45cf83925ec9ba4))
* display warning in inspector if using 'TEXCOORD*.zw' components as custom vertex stream ([59221d5](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/59221d58217a440b77d504e6428bf99f10246260))
* mesh sharing group ([9afeebf](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9afeebf67212cdf4d3ac9e9a3b78a7ced5c7ecfe))
* random mesh sharing group ([4fa43ed](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4fa43eda4bc70c9c827c4fad9d5ae1327bfbc322))
* support 8+ materials ([b76bf5a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b76bf5a5ad378c3c4b16bcf08d21337757557101)), closes [#122](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/122) [#152](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/152) [#186](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/186)
### BREAKING CHANGES
* If you update to v4, you may be required to adjust your UIParticle.scale.
# [4.0.0-preview.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.12...4.0.0-preview.1) (2022-06-18)
### Bug Fixes
* correct world space particle position when changing screen size ([c6644a2](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c6644a213263375c7a35b5082ef4b71cc58964e6))
* keep properly canvas batches ([d8e96e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d8e96e69a62dff7a451eaed32c7a814e7e62dbb9))
### Features
* adaptive scaling for UI ([aa0d56f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/aa0d56f9faa05e9679d4b476bcf135eafb1b8af9))
* add overlay window for UIParticle ([7b21c50](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7b21c500ef78103b605fdca71051d2357b09602f))
* add particle attractor component ([386170c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/386170cbf68ebf59d4510fe0a45cf83925ec9ba4))
* mesh sharing group ([9afeebf](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9afeebf67212cdf4d3ac9e9a3b78a7ced5c7ecfe))
* random mesh sharing group ([4fa43ed](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4fa43eda4bc70c9c827c4fad9d5ae1327bfbc322))
* support 8+ materials ([b76bf5a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b76bf5a5ad378c3c4b16bcf08d21337757557101)), closes [#122](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/122) [#152](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/152) [#186](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/186)
### BREAKING CHANGES
* If you update to v4, you may be required to adjust your UIParticle.scale.
## [3.3.12](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.11...3.3.12) (2022-06-10)
### Bug Fixes
* always display materials in inspector ([a10042d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a10042d989dea18ff010bdbe970aa434e2bdf117))
* UNITY_UI_ALPHACLIP in UIAdditive shader is not working ([e817e8d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e817e8d3c75188f3243243855b135bd840699199))
## [3.3.11](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.10...3.3.11) (2022-06-10)
### Bug Fixes
* sorting by layer does not work properly ([ccc09e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ccc09e6aca2fa3d7bc887e6c733e66706e40ae0f))
* when using linear color space, the particle colors are not output correctly ([11c3a7b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/11c3a7b37415d78e1b8ba3988a6e043c9f1861e0)), closes [#203](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/203)
## [3.3.10](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.9...3.3.10) (2022-02-17)
### Bug Fixes
* annoying warning for [ExecuteInEditMode] ([b6b2c72](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b6b2c72b198566e2880a22831c937eff7e9eff28)), closes [#180](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/180)
* PrefabStageUtility class is not experimental after 2021.2 ([0fd5d7a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0fd5d7affe707fa9e92abd6e192bf400dfb1a80a))
## [3.3.9](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.8...3.3.9) (2021-08-02)
### Bug Fixes
* fix for warning CS0618 ([61760d9](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/61760d940cdd4baacaa196ac1631a0a1a40b7204))
## [3.3.8](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.7...3.3.8) (2021-06-08)
### Bug Fixes
* improve performance ([e352d15](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e352d153cef8c1efb2792e35010d7eed1e31a040))
## [3.3.7](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.6...3.3.7) (2021-06-02)
### Bug Fixes
* Refresh() will be called multiple times in the same frame, due to external assets ([0b9d80d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0b9d80da939580c72ca1471081d7a034edc985d4))
## [3.3.6](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.5...3.3.6) (2021-05-11)
### Bug Fixes
* In rare cases, the generated camera (for baking) will not be deactivated ([12c748a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/12c748a8cd4adfd2dc5f085cec77050431f261a4))
* remove from "Add Component" menu ([476c402](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/476c4027ff5f70fb9b4c026dd5fc59bf5a876227))
## [3.3.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.4...3.3.5) (2021-02-28)
### Bug Fixes
* fix cached position for pre-warmed particles ([e3f42d7](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e3f42d747a7fd973b5813cc72a9444943a6c3ad0))
* ParticleSystem creates particles in wrong position during pre-warm ([b93e0e4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b93e0e4701c7011176eeec5c109dda7f4ea632e0)), closes [#147](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/147)
## [3.3.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.3...3.3.4) (2021-02-22)
### Bug Fixes
* Multiselecting sets all scales to the same value ([13223b2](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/13223b2d747609cf88b424ad590bda7f857b387d))
* support sub emitter with 'PlayOnAwake' ([d5ce78a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d5ce78ae5acf2740ba7fdc6cde9f197c4e165484))
* The maximum material count is 8 ([3bb5241](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3bb52412751360409747192150188ae904f2c3d3))
## [3.3.3](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.2...3.3.3) (2021-02-03)
### Bug Fixes
* particle trails draw in wrong transform ([17ce81e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/17ce81eb0eccb103c21fa553183df97429cf5c6f)), closes [#145](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/145)
## [3.3.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.1...3.3.2) (2021-02-01)
### Bug Fixes
* _cachedPosition defaults to localPosition ([c0aa89b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c0aa89bd6f7847723a4702b6ca70fa202e8a8304)), closes [#121](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/121)
* submeshes can't over 8 ([2a1f334](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2a1f3345bacdecf38e8890781a181a1392224e35)), closes [#122](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/122)
## [3.3.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.3.0...3.3.1) (2021-02-01)
### Bug Fixes
* ignore material check and transform check ([d11cd0a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d11cd0a06d76a32b2a119387bddc34c703b9b497)), closes [#119](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/119)
* the trail is incorrect in SimulationSpace.Local ([9313489](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9313489552b30f2e2b0b42a641f5e0502995b03d))
# [3.3.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.2.0...3.3.0) (2020-11-20)
### Bug Fixes
* the particles may disappear unintentionally ([2ec81da](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2ec81da04877d63593dd863133b6da149dcd79e6)), closes [#117](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/117)
### Features
* ignore rendering of particle systems that do not have a SharedMaterial and TrailMaterial ([08c4aba](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/08c4aba8ab9b5a041d4350a72dae62d25530afca)), closes [#118](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/118)
* show/hide materials in inspector ([4b4aebf](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4b4aebff8cdaff9acc696a1094e170e65631135f))
* shrink rendering by material ([46a7ddd](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/46a7dddd11c3e030192cd998ae1a79441f5e5c14)), closes [#113](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/113)
# [3.2.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.1.1...3.2.0) (2020-11-15)
### Features
* compatibility with other IMaterialModifier ([08273cb](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/08273cb0c340ccb4f35120dc804c37d758da9ce1)), closes [#115](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/115)
## [3.1.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.1.0...3.1.1) (2020-11-09)
### Bug Fixes
* error on build in Unity 2019.3.11-15 ([68669c7](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/68669c739676f2354db4913a0e2296ab1715ee1f)), closes [#114](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/114)
* null Reference when creating New Scene after Prefab was open in PrefabMode ([22bcecd](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/22bcecd0abd6ad651fcf066e5c9efe9a43fd217a)), closes [#111](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/111)
# [3.1.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.0.1...3.1.0) (2020-10-28)
### Bug Fixes
* compile error in 2018.2 ([82f81ef](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/82f81efd7e4ea06465e24f44f96d9726a1a60cc8))
### Features
* maskable option to ignore masking ([af5f7e9](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/af5f7e90b0570d5c7fcf045fd6b81036a060e493)), closes [#109](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/109)
## [3.0.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/3.0.0...3.0.1) (2020-10-28)
### Bug Fixes
* fix the sorting algorithm ([7acbf22](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7acbf22b4de7c3b5251fbb720bb5b575946622f6))
* in rare cases, an IndexOutOfRangeException is thrown ([f7eac0a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f7eac0a34f07767dc04e035f97179cc30935284f))
# [3.0.0](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/2.3.0...3.0.0) (2020-10-27)
### Bug Fixes
* IgnoreCanvasScaler may be enabled unintentionally ([d9f9244](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d9f9244e49127bea405c3cb802b588c1eae00831))
* an error happens during loading scene in editor ([ab9d9aa](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ab9d9aa7b3afcdbdda00004f7af3fd4827aaea54)), closes [#101](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/101)
* not working as expected in world simulation space ([683fcb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/683fcb4ecdf8bfa0994571f5d6c3dd2bc242ca2a)), closes [#98](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/98)
* if the package was installed via openupm, an unintended directory 'Samples' was included ([1913de5](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1913de557743b9480f72c5378d13c284a4ac93f9))
* animatable properties not working ([5b8b0bd](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5b8b0bd28b251a7ea6e0cfa0c4b69bd7f9c4d953)), closes [#95](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/95)
* combine Instances error ([878f812](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/878f81202ac29a8a20f174efa916da64eef99e8a)), closes [#91](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/91)
* in rare cases, the particle size is incorrect with camera-space mode ([90593ac](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/90593ac021ce19d164927e44804354535db047bb)), closes [#93](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/93)
* trails material uses sprite texture ([9e65ee7](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9e65ee7345e16b5124e94d26f5749999c648f677)), closes [#92](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/92)
* ignore missing object on initialize ([8bd9b62](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8bd9b621b9efcd242c410405d066494a1d53f9a3))
* not masked ([4ef5947](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4ef5947baa325002aecd1ccbdc75056a6567f14b))
* in Unity 2018.2, PrefabStageUtility is not found ([0b6dcff](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0b6dcff5d6356db497532daa0a26804852e8de24))
* removed UIParticle will be saved in prefab mode ([08e2d51](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/08e2d51c73a294d44974e7fba35e2477f04e6860))
* hide camera for baking ([30b4703](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/30b4703e2a1746efc4b7db154354f80fd0593b98))
* In ignore canvas scaler mode, Transform.localScale is zero ([cc71f2b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/cc71f2bdac1a61fd5e5fc85d0a69589e05a0f79d)), closes [#89](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/89)
* In prefab mode, an error occurs ([a222f37](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a222f3710b530c7fc9fab10f25bd28d820ffebe2)), closes [#88](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/88)
* the default value of IgnoreCanvasScaler is true ([966fae1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/966fae1d22a98259ec5aff68b4603b7c21dfdfc9))
* build fails ([ac080a4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ac080a44e4d872bc3f784fc222cc74aac7e795e9)), closes [#85](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/85)
* if in the mask, rendering material will be destroyed ([0db40cf](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0db40cf160b2a5a27c83ef15d648b2771a47b51a))
* baking camera settings for camera space ([436c5e4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/436c5e47f75c3e167dcd77c188847e9d7d6ea68d))
* fix local simulation ([7add9de](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7add9defb70be29ddbe536d854591c2e0d9e83fa))
* fix camera for baking mesh ([6395a4f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/6395a4fa744a46551593185711d6545a94d8b456))
* The type or namespace name 'U2D' does not exist in the namespace 'UnityEditor.Experimental' in Unity 2019.3 or later ([930199e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/930199e5e42920825b27d5bf3e2b2a4bda77fa14)), closes [#82](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/82)
* texture sheet animation module Sprite mode not working ([30d1d5d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/30d1d5d3cc67234a8cd985e98f181aff2a8bd8ef)), closes [#79](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/79)
* An exception in the OnSceneGUI caused the scale of the transformation to change unintentionally ([75413e0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/75413e0e2cff42a85b73b33e17e0bb6344ecc8f6))
* read-only properties in the inspector ([f012b23](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f012b238d97aad3fdc3107b1f9a197de869c43e6))
* Added CanvasRenderer as a required component ([a8950f6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a8950f65c817be04b0be222c9728c716fdd7c658))
* If sprite is null, a null exception is thrown ([50c6e98](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/50c6e980ca37dda1bece5252162fa05ca3472ee8))
* fix displayed version in readme ([c29bbdd](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c29bbddf8ad9a251d5f472b77cf85b3d432bba71))
* abnormal Mesh Bounds with Particle Trails ([518a749](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/518a7497105a114a0f6b1782df0c35ba0aecfab2)), closes [#61](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/61)
* multiple UIParticleOverlayCamera in scene ([3f09395](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3f093958b3353463d6c5bd29ef3338203d4e41d7)), closes [#73](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/73)
* add package keywords ([49d8f3f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/49d8f3fe4c76cf6bd2cd5b6134ee23134532da8e))
* particles not visible if scale.z is 0 ([35718e0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/35718e099acbb04fdadf131c7e4d2e6c3f4a1756)), closes [#64](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/64)
* remove unnecessary scripts ([0a43740](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0a4374099dc3151e7f1a3a24a6ce6c39a968e163))
* workaround for [#70](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/70) ([4bbcc33](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4bbcc334abb7cd6db2897fad0bda219d5ea73530))
* change the text in the inspector to make it more understandable. ([7ca0b6f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7ca0b6fa34c1168ef103992e1c69b68631b3bc60)), closes [#66](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/66)
* editor crashes when mesh is set to null when ParticleSystem.RenderMode=Mesh ([e5ebadd](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e5ebadd84731716f82c63ac5ba3eb676720e3ad6)), closes [#69](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/69)
* getting massive errors on editor ([ef82fa8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ef82fa82a69894e643f0d257f99eb9177785f697)), closes [#67](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/67)
* heavy editor UI ([d3b470a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d3b470a2be3a21add9e126b357e46bdfaa6f16c8))
* remove a menu to add overlay camera ([f5d3b6e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f5d3b6edb5687c4d465992ef5c3c0d54f7b36d74))
* rotating the particle rect may cause out of bounds ([3439842](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3439842119f334b50910c0a983e561944cc792a2)), closes [#55](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/55)
* scale will be decrease on editor ([0c59846](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0c59846f11438b12caad04ae5d5b544a28883ea6))
* UI darker than normal when change to linear color space ([db4d8a7](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/db4d8a742ca36c8dd2de6936b9cf2912c72d4b9f)), closes [#57](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/57)
### Features
* cache modified material ([6b397f3](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/6b397f39b89f40c4aae9c9f56706b3bc68a376be)), closes [#94](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/94)
* improve the material batching ([4be5666](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4be56669fb764bf61c0246a6e56d18640053b565))
* un-limit on the number of mesh instances ([f133881](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f1338813ca85d305f334799b78154e03b0aff60c))
* refresh children ParticleSystem with a gameObjects as root ([8bae1d0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8bae1d08cc6f00e2b8d6f336aad92233891da1e4))
* add API to bind ParticleSystem object ([a77bbd3](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a77bbd3a9a65d5fd1198bd8e580982ca8e07fca8))
* material batching ([8f703e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8f703e6d2c0e8229ca14b25638dae5d91a5658c3))
* support AnimatableProperty for multiple materials ([062d988](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/062d9887fb8b096250ec3b43d9aa82637940a8bb))
* remove menu in inspector ([e7f8f51](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e7f8f512122a01423de415b55e3190d62bda146a))
* add menu to create UIParticle ([2fa1843](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2fa18431f0c8c4aeadfdd1cb98eeeef5ac6970a0))
* add play/pause/stop api ([f09a386](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f09a386bc59fbab8143f7f0b814c8684aea7f27c))
* support for changing rendering orders ([745d4a5](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/745d4a598846b3e77d1071433079fdd5140921a8))
* Support for child ParticleSystem rendering ([4ee90be](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4ee90be17c68bf405f81f432615a3eebaa022366))
* UIParticle for trail is no longer needed ([466e43c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/466e43cf931d211907419f804a90776a0d9f4906))
* add menu to create UIParticle ([14f1c78](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/14f1c782ff0f2b67d85d7c9ad0cf662da1dd1fc6))
* Combine baked meshes to improve performance ([633d058](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/633d058756fde776a7e5192a0f023adf6eb0ca7b))
* improve performance ([77c056a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/77c056ad5f2918efe457883f3b0361f952600568))
* optimization for vertices transforms and adding node for trails ([e070e8d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e070e8d5ee205c25a1e3be5d3178821d4a8265d0)), closes [#75](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/75)
* option to ignoring canvas scaling ([fe85fed](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fe85fed3c0ad2881578ff68722863d65dfa4db7a))
* support 3d scaling ([42a84bc](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/42a84bc5e130aed3cf5e57dcd6a9d8dc94deb641))
* support custom simulation space ([a83e647](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a83e64761c008e88ff328a2609118806e97f19cf)), closes [#78](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/78)
* support for particle systems including trail only ([f389d39](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f389d39953c85b97482b12d1c8578ecaeddacd18)), closes [#61](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/61)
* add support for SpriteAtlas ([b31e325](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b31e325bb1ef0856cb1ac4c4b0c4da0f1578b8ba))
* add menu to import sample ([b8b1827](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b8b18273185769235101da01f5bbadbac188e387))
### BREAKING CHANGES
* The development branch name has been changed. Most cases are unaffected.
* The child UIParticle is no longer needed.
* The bake-task has changed significantly. It may look different from previous versions.
* update develop environment to Unity 2018.3. Unity 2018.2 will continue to be supported.
# [3.0.0-preview.38](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.37...v3.0.0-preview.38) (2020-10-04)
### Bug Fixes
* delete unused file in package ([2e69974](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2e699749a8f0f620505621a13a628aa87f192875))
* material dirty on validate (on editor) ([fa34301](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fa3430130cdffa3f934e926645958ad9f19edc5d))
### Features
* display material properties in inspector ([313c1fc](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/313c1fc159429034f84b2e7c30424158c43b71e9)), closes [#104](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/104)
* support 3D scaling ([a508c3b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a508c3bb86ad6694722868303385b20adc914134)), closes [#105](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/105)
# [3.0.0-preview.37](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.36...v3.0.0-preview.37) (2020-10-01)
### Bug Fixes
* fix menus ([5fa12b5](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5fa12b5338a90764a3bf384dcd3911f2ab4eba61))
# [3.0.0-preview.36](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.35...v3.0.0-preview.36) (2020-09-28)
### Bug Fixes
* do not bake particle system to mesh when the alpha is zero ([1775713](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1775713c2dbeef09ad3eb1f49b53cf44bf61d535)), closes [#102](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/102)
* in Unity 2018.x, sample import failed on Windows ([f5861b0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f5861b0add1477987d6b9a3db26979fde50930ad))
# [3.0.0-preview.35](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.34...v3.0.0-preview.35) (2020-09-27)
### Bug Fixes
* an error happens during loading scene in editor ([ab9d9aa](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ab9d9aa7b3afcdbdda00004f7af3fd4827aaea54)), closes [#101](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/101)
# [3.0.0-preview.34](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.33...v3.0.0-preview.34) (2020-09-15)
### Bug Fixes
* not working as expected in world simulation space ([683fcb4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/683fcb4ecdf8bfa0994571f5d6c3dd2bc242ca2a)), closes [#98](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/98)
# [3.0.0-preview.33](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.32...v3.0.0-preview.33) (2020-09-14)
### Bug Fixes
* if the package was installed via openupm, an unintended directory 'Samples' was included ([1913de5](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/1913de557743b9480f72c5378d13c284a4ac93f9))
# [3.0.0-preview.32](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.31...v3.0.0-preview.32) (2020-09-14)
### Bug Fixes
* animatable properties not working ([5b8b0bd](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/5b8b0bd28b251a7ea6e0cfa0c4b69bd7f9c4d953)), closes [#95](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/95)
# [3.0.0-preview.31](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.30...v3.0.0-preview.31) (2020-09-02)
### Bug Fixes
* combine Instances error ([878f812](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/878f81202ac29a8a20f174efa916da64eef99e8a)), closes [#91](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/91)
* in rare cases, the particle size is incorrect with camera-space mode ([90593ac](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/90593ac021ce19d164927e44804354535db047bb)), closes [#93](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/93)
* trails material uses sprite texture ([9e65ee7](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9e65ee7345e16b5124e94d26f5749999c648f677)), closes [#92](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/92)
### Features
* refresh children ParticleSystem with a gameObjects as root ([8bae1d0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8bae1d08cc6f00e2b8d6f336aad92233891da1e4))
# [3.0.0-preview.30](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.29...v3.0.0-preview.30) (2020-09-02)
### Bug Fixes
* ignore missing object on initialize ([8bd9b62](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8bd9b621b9efcd242c410405d066494a1d53f9a3))
### Features
* add API to bind ParticleSystem object ([a77bbd3](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a77bbd3a9a65d5fd1198bd8e580982ca8e07fca8))
# [3.0.0-preview.29](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.28...v3.0.0-preview.29) (2020-09-01)
### Features
* material batching ([8f703e6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/8f703e6d2c0e8229ca14b25638dae5d91a5658c3))
# [3.0.0-preview.28](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.27...v3.0.0-preview.28) (2020-09-01)
### Features
* support AnimatableProperty for multiple materials ([062d988](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/062d9887fb8b096250ec3b43d9aa82637940a8bb))
# [3.0.0-preview.27](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.26...v3.0.0-preview.27) (2020-09-01)
### Bug Fixes
* not masked ([4ef5947](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4ef5947baa325002aecd1ccbdc75056a6567f14b))
# [3.0.0-preview.26](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.25...v3.0.0-preview.26) (2020-09-01)
### Bug Fixes
* in Unity 2018.2, PrefabStageUtility is not found ([0b6dcff](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0b6dcff5d6356db497532daa0a26804852e8de24))
# [3.0.0-preview.25](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.24...v3.0.0-preview.25) (2020-09-01)
### Bug Fixes
* removed UIParticle will be saved in prefab mode ([08e2d51](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/08e2d51c73a294d44974e7fba35e2477f04e6860))
# [3.0.0-preview.24](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.23...v3.0.0-preview.24) (2020-09-01)
### Bug Fixes
* hide camera for baking ([30b4703](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/30b4703e2a1746efc4b7db154354f80fd0593b98))
* In ignore canvas scaler mode, Transform.localScale is zero ([cc71f2b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/cc71f2bdac1a61fd5e5fc85d0a69589e05a0f79d)), closes [#89](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/89)
* In prefab mode, an error occurs ([a222f37](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a222f3710b530c7fc9fab10f25bd28d820ffebe2)), closes [#88](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/88)
### Features
* remove menu in inspector ([e7f8f51](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e7f8f512122a01423de415b55e3190d62bda146a))
# [3.0.0-preview.23](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.22...v3.0.0-preview.23) (2020-08-31)
### Bug Fixes
* the default value of IgnoreCanvasScaler is true ([966fae1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/966fae1d22a98259ec5aff68b4603b7c21dfdfc9))
# [3.0.0-preview.22](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.21...v3.0.0-preview.22) (2020-08-29)
### Bug Fixes
* build fails ([ac080a4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ac080a44e4d872bc3f784fc222cc74aac7e795e9)), closes [#85](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/85)
# [3.0.0-preview.21](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.20...v3.0.0-preview.21) (2020-08-28)
### Bug Fixes
* if in the mask, rendering material will be destroyed ([0db40cf](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0db40cf160b2a5a27c83ef15d648b2771a47b51a))
* support animatable material property (again) ([cf6ca80](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/cf6ca80d1273bcf49e18d805260afa8e36e94617))
# [3.0.0-preview.20](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.19...v3.0.0-preview.20) (2020-08-28)
### Features
* automatically update ([96a868b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/96a868b60a3f36d761d58b5082aa9d37666e63a3))
# [3.0.0-preview.19](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.18...v3.0.0-preview.19) (2020-08-28)
### Bug Fixes
* baking camera settings for camera space ([436c5e4](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/436c5e47f75c3e167dcd77c188847e9d7d6ea68d))
* fix local simulation ([7add9de](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7add9defb70be29ddbe536d854591c2e0d9e83fa))
### Features
* add menu to create UIParticle ([2fa1843](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/2fa18431f0c8c4aeadfdd1cb98eeeef5ac6970a0))
* add play/pause/stop api ([f09a386](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f09a386bc59fbab8143f7f0b814c8684aea7f27c))
* support for changing rendering orders ([745d4a5](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/745d4a598846b3e77d1071433079fdd5140921a8))
* Support for child ParticleSystem rendering ([4ee90be](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4ee90be17c68bf405f81f432615a3eebaa022366))
* UIParticle for trail is no longer needed ([466e43c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/466e43cf931d211907419f804a90776a0d9f4906))
### BREAKING CHANGES
* The child UIParticle is no longer needed.
# [3.0.0-preview.18](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.17...v3.0.0-preview.18) (2020-08-19)
### Bug Fixes
* AsmdefEx is no longer required ([50e749c](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/50e749c183def5e97affa7e6ae9f3ceb69247825))
* fix camera for baking mesh ([6395a4f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/6395a4fa744a46551593185711d6545a94d8b456))
* support .Net Framework 3.5 (again) ([23fcb06](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/23fcb06bf9169ee160ccd8adb2cc3aab1a30186a))
### Features
* 3.0.0 updater ([f99292b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f99292b9a15c9c085efacc0330d6b848669fadfa))
* add menu to create UIParticle ([14f1c78](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/14f1c782ff0f2b67d85d7c9ad0cf662da1dd1fc6))
* Combine baked meshes to improve performance ([633d058](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/633d058756fde776a7e5192a0f023adf6eb0ca7b))
* improve performance ([77c056a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/77c056ad5f2918efe457883f3b0361f952600568))
* optimization for vertices transforms and adding node for trails ([e070e8d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e070e8d5ee205c25a1e3be5d3178821d4a8265d0)), closes [#75](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/75)
* option to ignoring canvas scaling ([fe85fed](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/fe85fed3c0ad2881578ff68722863d65dfa4db7a))
* support 3d scaling ([42a84bc](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/42a84bc5e130aed3cf5e57dcd6a9d8dc94deb641))
* support custom simulation space ([a83e647](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a83e64761c008e88ff328a2609118806e97f19cf)), closes [#78](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/78)
* support for particle systems including trail only ([f389d39](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f389d39953c85b97482b12d1c8578ecaeddacd18)), closes [#61](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/61)
### BREAKING CHANGES
* The bake-task has changed significantly. It may look different from previous versions.
# [3.0.0-preview.17](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.16...v3.0.0-preview.17) (2020-08-13)
### Bug Fixes
* The type or namespace name 'U2D' does not exist in the namespace 'UnityEditor.Experimental' in Unity 2019.3 or later ([930199e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/930199e5e42920825b27d5bf3e2b2a4bda77fa14)), closes [#82](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/82)
# [3.0.0-preview.16](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.15...v3.0.0-preview.16) (2020-08-12)
### Bug Fixes
* texture sheet animation module Sprite mode not working ([30d1d5d](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/30d1d5d3cc67234a8cd985e98f181aff2a8bd8ef)), closes [#79](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/79)
# [3.0.0-preview.15](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.14...v3.0.0-preview.15) (2020-08-11)
### Bug Fixes
* An exception in the OnSceneGUI caused the scale of the transformation to change unintentionally ([75413e0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/75413e0e2cff42a85b73b33e17e0bb6344ecc8f6))
# [3.0.0-preview.14](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.13...v3.0.0-preview.14) (2020-08-11)
### Bug Fixes
* read-only properties in the inspector ([f012b23](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f012b238d97aad3fdc3107b1f9a197de869c43e6))
# [3.0.0-preview.13](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.12...v3.0.0-preview.13) (2020-08-11)
### Bug Fixes
* Added CanvasRenderer as a required component ([a8950f6](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/a8950f65c817be04b0be222c9728c716fdd7c658))
* inspector is broken in Unity 2020.1 ([26c5395](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/26c5395a45ff00e99e46ee4aae85c51df6c3641f))
### Features
* update OSC to 1.0.0-preview.25 ([22e116e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/22e116e11d3b8cf13b941e9a02a0ffce24e3e99f))
# [3.0.0-preview.12](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.11...v3.0.0-preview.12) (2020-08-11)
### Bug Fixes
* Profiler.BeginSample -> Profiler.EndSample if a canvas is disabled or a camera doesn't found ([4a0a5d1](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4a0a5d13be68e38d5b2e225156740aed27c52d12))
# [3.0.0-preview.11](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.10...v3.0.0-preview.11) (2020-05-07)
### Bug Fixes
* If sprite is null, a null exception is thrown ([50c6e98](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/50c6e980ca37dda1bece5252162fa05ca3472ee8))
# [3.0.0-preview.10](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.9...v3.0.0-preview.10) (2020-04-30)
### Features
* add support for SpriteAtlas ([b31e325](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b31e325bb1ef0856cb1ac4c4b0c4da0f1578b8ba))
# [3.0.0-preview.9](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.8...v3.0.0-preview.9) (2020-03-04)
### Bug Fixes
* fix displayed version in readme ([c29bbdd](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/c29bbddf8ad9a251d5f472b77cf85b3d432bba71))
# [3.0.0-preview.8](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.7...v3.0.0-preview.8) (2020-03-03)
### Bug Fixes
* abnormal Mesh Bounds with Particle Trails ([518a749](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/518a7497105a114a0f6b1782df0c35ba0aecfab2)), closes [#61](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/61)
* multiple UIParticleOverlayCamera in scene ([3f09395](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3f093958b3353463d6c5bd29ef3338203d4e41d7)), closes [#73](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/73)
# [3.0.0-preview.7](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.6...v3.0.0-preview.7) (2020-03-02)
### Bug Fixes
* add package keywords ([49d8f3f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/49d8f3fe4c76cf6bd2cd5b6134ee23134532da8e))
* fix sample path ([57ee210](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/57ee21005e114fdf186b5db55ca2b77b7b7c441a))
# [3.0.0-preview.6](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.5...v3.0.0-preview.6) (2020-02-21)
### Bug Fixes
* sample version ([ed18032](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ed18032be43397debbd538cae258c226ebeeb2e9))
# [3.0.0-preview.5](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.4...v3.0.0-preview.5) (2020-02-21)
### Bug Fixes
* particles not visible if scale.z is 0 ([35718e0](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/35718e099acbb04fdadf131c7e4d2e6c3f4a1756)), closes [#64](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/64)
# [3.0.0-preview.4](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.3...v3.0.0-preview.4) (2020-02-18)
### Bug Fixes
* compile error in Unity 2019.1 or later ([28ca922](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/28ca922167afff3ef8341fa747968357d4487d1f)), closes [#70](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/70) [#71](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/71)
# [3.0.0-preview.3](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.2...v3.0.0-preview.3) (2020-02-17)
### Bug Fixes
* remove unnecessary scripts ([0a43740](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0a4374099dc3151e7f1a3a24a6ce6c39a968e163))
* workaround for [#70](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/70) ([4bbcc33](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/4bbcc334abb7cd6db2897fad0bda219d5ea73530))
# [3.0.0-preview.2](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.1...v3.0.0-preview.2) (2020-02-13)
### Bug Fixes
* compile error ([e2c5c7b](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e2c5c7b05d1307877e2f37555d4845932d542930))
# [3.0.0-preview.1](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.3.0...v3.0.0-preview.1) (2020-02-12)
### Bug Fixes
* change the text in the inspector to make it more understandable. ([7ca0b6f](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/7ca0b6fa34c1168ef103992e1c69b68631b3bc60)), closes [#66](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/66)
* editor crashes when mesh is set to null when ParticleSystem.RenderMode=Mesh ([e5ebadd](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/e5ebadd84731716f82c63ac5ba3eb676720e3ad6)), closes [#69](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/69)
* getting massive errors on editor ([ef82fa8](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/ef82fa82a69894e643f0d257f99eb9177785f697)), closes [#67](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/67)
* heavy editor UI ([d3b470a](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/d3b470a2be3a21add9e126b357e46bdfaa6f16c8))
* remove a menu to add overlay camera ([f5d3b6e](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/f5d3b6edb5687c4d465992ef5c3c0d54f7b36d74))
* rotating the particle rect may cause out of bounds ([3439842](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/3439842119f334b50910c0a983e561944cc792a2)), closes [#55](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/55)
* scale will be decrease on editor ([0c59846](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/0c59846f11438b12caad04ae5d5b544a28883ea6))
* UI darker than normal when change to linear color space ([db4d8a7](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/db4d8a742ca36c8dd2de6936b9cf2912c72d4b9f)), closes [#57](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/57)
### Build System
* update develop environment ([9fcf169](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/9fcf169cd3ced519611b2ede7f98ad4d678027c6))
### Features
* add menu to import sample ([b8b1827](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/b8b18273185769235101da01f5bbadbac188e387))
* add samples test ([287b5cc](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/287b5cc832f2899796227520bda4d11ad8e4fae9))
* **editor:** add osc package (portable mode) ([6c7f880](https://github.com/mob-sakai/ParticleEffectForUGUI/commit/6c7f8804350112505949c5c296f9e0340877a3e8))
### BREAKING CHANGES
* update develop environment to Unity 2018.3.
Unity 2018.2 will continue to be supported.
# Changelog
## [v2.3.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.3.0) (2019-05-12)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.2.1...v2.3.0)
World simulation bug due to transform movement have been fixed
**Fixed bugs:**
- World simulation bug due to transform movement [\#47](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/47)
## [v2.2.1](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.2.1) (2019-02-26)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.2.0...v2.2.1)
**Fixed bugs:**
- v2.2.0 has 2 warnings [\#44](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/44)
- Disable ParticleSystemRenderer on reset [\#45](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/45)
## [v2.2.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.2.0) (2019-02-23)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.1.1...v2.2.0)
**Implemented enhancements:**
- Display warning when material does not support Mask [\#43](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/43)
- Support changing material property by AnimationClip [\#42](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/42)
**Fixed bugs:**
- UV Animation is not work. [\#41](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/41)
## [v2.1.1](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.1.1) (2019-02-15)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.1.0...v2.1.1)
## [v2.1.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.1.0) (2019-02-07)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v2.0.0...v2.1.0)
World simulation bug is fixed.
![](https://user-images.githubusercontent.com/12690315/52386223-71a56000-2ac8-11e9-9cdb-93175d24febe.gif)
**Fixed bugs:**
- When moving the transform in world simulation mode, particles don't behave as expected [\#37](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/37)
## [v2.0.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v2.0.0) (2019-01-17)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v1.3.3...v2.0.0)
**Install UIParticle with Unity Package Manager!**
Find the manifest.json file in the Packages folder of your project and edit it to look like this:
```js
{
"dependencies": {
"com.coffee.ui-particle": "https://github.com/mob-sakai/ParticleEffectForUGUI.git#2.0.0",
...
},
}
```
To update the package, change `#2.0.0` to the target version.
**Implemented enhancements:**
- Integrate with UnityPackageManager [\#30](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/30)
## [v1.3.3](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v1.3.3) (2019-01-16)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v1.3.2...v1.3.3)
**Fixed bugs:**
- On prefab edit mode, unnecessary UIParticleOverlayCamera is generated in the scene [\#35](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/35)
- With 'Screen Space - Camera' render mode, sorting is incorrect [\#34](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/34)
## [v1.3.2](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v1.3.2) (2018-12-29)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v1.3.1...v1.3.2)
**Implemented enhancements:**
- Use shared material during play mode [\#29](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/29)
**Fixed bugs:**
- Particle not showing on Android, while on editor it works [\#31](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/31)
## [v1.3.1](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v1.3.1) (2018-12-24)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v1.3.0...v1.3.1)
**Fixed bugs:**
- OnSceneGUI has errors in Unity 2018.2 [\#27](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/27)
- Demo scene crashes in Unity 2018.2 [\#26](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/26)
## [v1.3.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v1.3.0) (2018-12-21)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v1.2.1...v1.3.0)
With Gizmo you can control the scaled Shape.
![](https://user-images.githubusercontent.com/12690315/50343861-f31e4e80-056b-11e9-8f60-8bd0a8ff7adb.gif)
**Fixed bugs:**
- In overlay, particle size is too small [\#23](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/23)
- UIParticle.Scale does not affect the gizmo of shape module [\#21](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/21)
## [v1.2.1](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v1.2.1) (2018-12-13)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v1.2.0...v1.2.1)
**Fixed bugs:**
- Rect mask 2D doesn't work on WebGL [\#20](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/20)
## [v1.2.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v1.2.0) (2018-12-13)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v1.1.0...v1.2.0)
New scaling system solves the particle effect scaling problem in most cases.
* All ParticleSystem.ScalingModes are supported
* All Canvas.RenderModes are supported
* They look almost the same in all modes
New scaling system scales particle effect well even if you change the following parameters:
* Camera.FieldOfView
* CanvasScaler.MatchWidthOrHeight
* Canvas.PlaneDistance
![](https://user-images.githubusercontent.com/12690315/49866926-6c22f500-fe4c-11e8-8393-d5a546e9e2d3.gif)
**NOTE: If upgrading from v1.1.0, readjust the UIParticle.Scale property.**
**Implemented enhancements:**
- New scaling system [\#18](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/18)
**Fixed bugs:**
- Rect mask 2D doesn't work [\#17](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/17)
- Using prefab view will cause a lot of errors [\#16](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/16)
- Canvas.scaleFactor not take into account [\#15](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/15)
## [v1.1.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v1.1.0) (2018-11-28)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v1.0.0...v1.1.0)
Easily to use, easily to set up.
* Adjust the Scale property to change the size of the effect.
![](https://user-images.githubusercontent.com/12690315/49148937-19c1de80-f34c-11e8-87fc-138192777540.gif)
* If your effect consists of multiple ParticleSystems, you can quickly set up UIParticles by clicking "Fix".
![](https://user-images.githubusercontent.com/12690315/49148942-1c243880-f34c-11e8-9cf5-d871d65c4dbe.png)
**Implemented enhancements:**
- Easy setup in editor [\#11](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/11)
- Add a scale property independent of transform [\#10](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/10)
**Fixed bugs:**
- Raycast blocking is unnecessary [\#12](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/12)
## [v1.0.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v1.0.0) (2018-07-13)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v0.1.0...v1.0.0)
Let's use particle for your UI!
UIParticle is use easy.
The particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.
![](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
**Implemented enhancements:**
- Supports sprites [\#5](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/5)
- Use Canvas.willRenderCanvases event instead of LateUpdate [\#4](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/4)
## [v0.1.0](https://github.com/mob-sakai/ParticleEffectForUGUI/tree/v0.1.0) (2018-06-22)
[Full Changelog](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/6b89c14a5144e290e55d041bc0ad03756a113ae0...v0.1.0)
![](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
This plugin uses new APIs `MeshBake/MashTrailBake` (added with Unity 2018.2) to render particles by CanvasRenderer.
You can mask and sort particles for uGUI without Camera, RenderTexture, Canvas.
**Implemented enhancements:**
- Bake particle mesh to render by CanvasRenderer [\#1](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/1)
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f69dd9b54399641dfb767c86736e80e0
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,84 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at sakai861104@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of actions.
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: dced951d19ddf4b2c8f4a6053d82125a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
# Contributing
## How to Contribute
#### Code of Conduct
This repository has adopted the Contributor Covenant as it's
Code of Conduct. It is expected that participants adhere to it.
#### Proposing a Change
If you are unsure about whether or not a change is desired,
you can create an issue. This is useful because it creates
the possibility for a discussion that's visible to everyone.
When fixing a bug it is fine to submit a pull request right away.
#### Sending a Pull Request
Steps to be performed to submit a pull request:
1. Fork the repository and create your branch from `develop`.
2. If you have fixed a bug or added code that should be tested, add tests.
3. Click `Window > Generals > Test Runner` to test
4. Commit with a massage based on [Angular Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153).
5. Fill out the description, link any related issues and submit your pull request.
#### License
By contributing to this repository, you agree that your contributions will be licensed under its MIT license.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: dbeb9a981ffa640d7a1e88a19b66efb5
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
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:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ad82da1cf120442c7950d301ea3c1543
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,455 @@
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&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)
<< [Description](#Description) | [Demo](#demo) | [Installation](#installation) | [Usage](#usage) | [Development Note](#development-note) | [Change log](https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md) >>
<br><br><br><br>
## Description
![](https://user-images.githubusercontent.com/12690315/41771577-8da4b968-7650-11e8-9524-cd162c422d9d.gif)
This plugin uses new APIs `MeshBake/MashTrailBake` (added with Unity 2018.2) to render particles by CanvasRenderer.
You can mask and sort particles for uGUI without Camera, RenderTexture, Canvas.
Compares this "Baking mesh" approach with the conventional approach:
[Performance test results](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/193#issuecomment-1160028374)
|Approach|Good|Bad|Screenshot|
|-|-|-|-|
|Baking mesh<br>**\(UIParticle\)**|Rendered as is.<br>Maskable.<br>Sortable.<br>Less objects.|[Not support `TEXCOORD*.zw` components for custom vertex stream](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/191#issuecomment-1043409186)|<img src="https://user-images.githubusercontent.com/12690315/41765089-0302b9a2-763e-11e8-88b3-b6ffa306bbb0.gif" width="500px">|
|Do nothing|Rendered as is.|**Looks like a glitch.**<br>Not maskable.<br>Not sortable.|<img src="https://user-images.githubusercontent.com/12690315/41765090-0329828a-763e-11e8-8d8a-f1d269ea3bc7.gif" width="500px">|
|Convert particle to UIVertex<br>[\(UIParticleSystem\)](https://forum.unity.com/threads/free-script-particle-systems-in-ui-screen-space-overlay.406862/)|Maskable.<br>Sortable.<br>Less objects.|**Adjustment is difficult.**<br>Requires UI shaders.<br>Difficult to adjust scale.<br>Force hierarchy scalling.<br>Simulation results are incorrect.<br>Trail, rotation of transform, time scaling are not supported.<br>Generate heavy GC every frame.|<img src="https://user-images.githubusercontent.com/12690315/41765088-02deb9c6-763e-11e8-98d0-9e0c1766ef39.gif" width="500px">|
|Use Canvas to sort|Rendered as is.<br>Sortable.|**You must to manage sorting orders.**<br>Not maskable.<br>More batches.|<img src="https://user-images.githubusercontent.com/12690315/41765087-02b866ea-763e-11e8-8c33-081c9ad852f8.gif" width="500px">|
|Use RenderTexture|Maskable.<br>Sortable.|**Requires Camera and RenderTexture.**<br>Difficult to adjust position and size.<br>Quality depends on the RenderTexture's setting.|<img src="https://user-images.githubusercontent.com/12690315/41765085-0291b3e2-763e-11e8-827b-72e5ee9bc556.gif" width="500px">|
|Approach|FPS on Editor|FPS on iPhone6|FPS on Xperia XZ|
|--|--|--|--|
|Particle System|43|57|22|
|UIParticleSystem|4|3|0 (unmeasurable)|
|Sorting By Canvas|43|44|18|
|UIParticle|17|12|4|
|UIParticle with MeshSharing|44|45|30|
<br><br>
#### Features
* Easy to use: the package is out-of-the-box
* Sort particle effects and UI by sibling index
* No Camera, RenderTexture or Canvas are required
* Masking by Mask or RectMask2D
* Support Trail module
* 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
* [4.0.0+] Correct world space particle position when changing window size for standalone platforms (Windows, MacOSX and Linux)
* [4.0.0+] Adaptive scaling for UI
* [4.0.0+] Mesh sharing group to improve performance
![](https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif)
* [4.0.0+] Particle attractor component
![](https://user-images.githubusercontent.com/12690315/174311027-462929a4-13f0-4ec4-86ea-9c832f2eecf1.gif)
* [4.1.0+] Relative/Absolute particle position mode
![](https://user-images.githubusercontent.com/12690315/175751579-5a2357e8-2ecf-4afd-83c8-66e9771bde39.gif)
<br><br><br><br>
## Demo
* [WebGL Demo](https://mob-sakai.github.io/demos/UIParticle_Demo/index.html)
> ![](https://user-images.githubusercontent.com/12690315/174311768-1843a5f2-f776-491b-aaa8-2a131a8b6a16.gif)
* [WebGL Demo (Cartoon FX & War FX)](https://mob-sakai.github.io/Demos/ParticleEffectForUGUI_CFX)
* [Cartoon FX Free][CFX] & [War FX][WFX] (by [Jean Moreno (JMO)][JMO]) with UIParticle
> ![](https://user-images.githubusercontent.com/12690315/91664766-3e07ac00-eb2c-11ea-978b-ef723be80619.gif)
[CFX]: https://assetstore.unity.com/packages/vfx/particles/cartoon-fx-free-109565
[WFX]: https://assetstore.unity.com/packages/vfx/particles/war-fx-5669
[JMO]: https://assetstore.unity.com/publishers/1669
<br><br><br><br>
## Installation
### Requirement
Unity 2018.2 or later
### Install via OpenUPM
This package is available on [OpenUPM](https://openupm.com).
It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
```
openupm add com.coffee.ui-particle
```
### Install via Package Manager Window (using Git URL)
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)
Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package.
### Install via manifest.json (using Git URL)
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 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>
## How to play demo
### For Unity 2019.1 or later
1. Open `Package Manager` window
2. Select `UI Particle` package in package list
3. Click `Import Sample` button
![demo](https://user-images.githubusercontent.com/12690315/95017806-83bd1480-0696-11eb-8c24-c56f45ab1ac2.png)
4. The demo project is imported into `Assets/Samples/UI Particle/{version}/Demo`
5. Open `UIParticle_Demo` scene and play it
### For Unity 2018.4 or earlier
1. Select `Assets/Samples/UI Particle Demo` from menu
2. The demo project is imported into `Assets/Samples/UI Particle/{version}/Demo`
3. Open `UIParticle_Demo` scene and play it
### About `Cartoon FX & War Fx Demo`
* It requires free assets ([Cartoon FX Free][CFX] & [War FX][WFX])
* by [Jean Moreno (JMO)][JMO]
<br><br><br><br>
## Usage
### UIParticle component
`UIParticle` controls the ParticleSystems that is attached to its own game objects and child game objects.
![](https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/3559df45-63e7-4c4c-9233-f455779efa29)
| Properties | Description |
| -- | -- |
| Maskable | Does this graphic allow masking. |
| 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. |
| 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.
<br><br>
### Basically usage
1. Select `Game Object/UI/ParticleSystem` to create UIParticle with a ParticleSystem.
![particle](https://user-images.githubusercontent.com/12690315/95007361-cad0e880-0649-11eb-8835-f145d62c5977.png)
2. Adjust the ParticleSystem as you like.
![particle1](https://user-images.githubusercontent.com/12690315/95007359-ca385200-0649-11eb-8383-627c9750bda8.png)
<br><br>
### With your existing ParticleSystem prefab
1. Select `Game Object/UI/ParticleSystem (Empty)` to create UIParticle.
![empty](https://user-images.githubusercontent.com/12690315/95007362-cb697f00-0649-11eb-8a09-29b0a13791e4.png)
2. Drag & drop your ParticleSystem prefab on UIParticle.
![particle3](https://user-images.githubusercontent.com/12690315/95007356-c6a4cb00-0649-11eb-9316-562f4bce3f31.png)
<br><br>
### With `Mask` or `RectMask2D` component
If you want to mask particles, set a stencil supported shader (such as `UI/UIAdditive`) to material for ParticleSystem.
If you use some custom shaders, see [How to make a custom shader to support Mask/RectMask2D component](#how-to-make-a-custom-shader-to-support-maskrectmask2d-component) section.
![](https://user-images.githubusercontent.com/12690315/95017591-3b512700-0695-11eb-864e-04166ea1809a.png)
<br><br>
### Script usage
```cs
// Instant ParticleSystem prefab with UIParticle on runtime.
var go = GameObject.Instantiate(prefab);
var uiParticle = go.AddComponent<UIParticle>();
// Control by ParticleSystem.
particleSystem.Play();
particleSystem.Emit(10);
// Control by UIParticle.
uiParticle.Play();
uiParticle.Stop();
```
<br><br>
### UIParticleAttractor component
`UIParticleAttractor` attracts particles generated by the specified ParticleSystem.
![](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 |
| -- | -- |
| Particle System | Attracts particles generated by the specified particle system. |
| Distination Radius | Once the particle is within the radius, the particle lifetime will become 0 and `OnAttracted` will be called. |
| 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>
## Development Note
### FAQ: Why are my particle effects not displayed correctly?
If `ParticleSystem` alone displays particles correctly but `UIParticle` does not, please check the following points:
* [Shader Limitation](https://github.com/mob-sakai/ParticleEffectForUGUI#shader-limitation)
* Most cases can be solved by using `UI/Additive` or `UI/Default`.
* Particles are masked
* `UIParticle` is maskable.
* Set `Mask` or `RectMask2D` component properly.
* Particles are too small
* If particles are small enough, they will not appear on the screen.
* Increase the `Scale` value.
* If you don't want to change the apparent size depending on the resolution, try `Auto Scaling` option.
* Particles are too many
* No more than 65535 vertices can be displayed (for mesh combination limitations).
* Please set `Emission` module and `Max Particles` of ParticleSystem properly.
* Particles are emitted off-screen.
* When `Position Mode = Relative`, particles are emitted from scaled position of the ParticleSystem, not from the screen point of the ParticleSystem.
* Place the ParticleSystem in the proper position or try `Position Mode = Absolute`.
* Attaching `UIParticle` to the same object as `ParticleSystem`
* `Transform.localScale` will be overridden by `Auto Scaling` option.
* It is recommended to place `ParticleSystem` under `UIParticle`.
<br>
### Shader Limitation
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
UIParticle has some overheads and the batching depends on uGUI.
When improving performance, keep the following in mind:
- If you are displaying a large number of the same effect, consider `Mesh Sharing` feature in [UIParticle Component](#uiparticle-component).
- If you don't like the uniform output, consider `Random Group` feature.
![](https://user-images.githubusercontent.com/12690315/174311048-c882df81-6c34-4eba-b0aa-5645457692f1.gif)
- If you are using multiple materials, you will have more draw calls.
- Consider single material, atlasing the sprites, and using `Sprite` mode in the `Texture Sheet Animation` module in ParticleSystem.
### How to make a custom shader to support Mask/RectMask2D component
<details>
<summary>Shader tips</summary>
```ShaderLab
Shader "Your/Custom/Shader"
{
Properties
{
// ...
// #### required for Mask ####
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
// ...
}
// #### required for Mask ####
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
ColorMask [_ColorMask]
// ...
Pass
{
// ...
// #### required for RectMask2D ####
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_CLIP_RECT
float4 _ClipRect;
// #### required for Mask ####
#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t
{
// ...
};
struct v2f
{
// ...
// #### required for RectMask2D ####
float4 worldPosition : TEXCOORD1;
};
v2f vert(appdata_t v)
{
v2f OUT;
// ...
// #### required for RectMask2D ####
OUT.worldPosition = v.vertex;
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
// ...
// #### required for RectMask2D ####
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
// #### required for Mask ####
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}
```
</details>
<br><br><br><br>
## Contributing
### Issues
Issues are very valuable to this project.
- Ideas are a valuable source of contributions others can make
- Problems show where this project is lacking
- With a question you show where contributors can improve the user experience
### Pull Requests
Pull requests are, a great way to get your ideas into this repository.
See [CONTRIBUTING.md](/../../blob/develop/CONTRIBUTING.md).
### Support
This is an open source project that I am developing in my spare time.
If you like it, please support me.
With your support, I can spend more time on development. :)
[![](https://user-images.githubusercontent.com/12690315/50731629-3b18b480-11ad-11e9-8fad-4b13f27969c1.png)](https://www.patreon.com/join/mob_sakai?)
[![](https://user-images.githubusercontent.com/12690315/66942881-03686280-f085-11e9-9586-fc0b6011029f.png)](https://github.com/users/mob-sakai/sponsorship)
<br><br><br><br>
## License
* MIT
## Author
* ![](https://user-images.githubusercontent.com/12690315/96986908-434a0b80-155d-11eb-8275-85138ab90afa.png) [mob-sakai](https://github.com/mob-sakai) [![](https://img.shields.io/twitter/follow/mob_sakai.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=mob_sakai) ![GitHub followers](https://img.shields.io/github/followers/mob-sakai?style=social)
## See Also
* GitHub page : https://github.com/mob-sakai/ParticleEffectForUGUI
* Releases : https://github.com/mob-sakai/ParticleEffectForUGUI/releases
* Issue tracker : https://github.com/mob-sakai/ParticleEffectForUGUI/issues
* Change log : https://github.com/mob-sakai/ParticleEffectForUGUI/blob/upm/CHANGELOG.md

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c0ba14a84a98844a68c60835d602a332
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2b8609eb7c2ee47f489e2dbca1f6fd4c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,78 @@
using System;
using UnityEngine;
namespace Coffee.UIExtensions
{
[Serializable]
public class AnimatableProperty : ISerializationCallbackReceiver
{
public enum ShaderPropertyType
{
Color,
Vector,
Float,
Range,
Texture
}
[SerializeField] private string m_Name = "";
[SerializeField] private ShaderPropertyType m_Type = ShaderPropertyType.Vector;
public int id { get; private set; }
public ShaderPropertyType type
{
get { return m_Type; }
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
id = Shader.PropertyToID(m_Name);
}
public void UpdateMaterialProperties(Material material, MaterialPropertyBlock mpb)
{
if (!material.HasProperty(id)) return;
switch (type)
{
case ShaderPropertyType.Color:
var color = mpb.GetColor(id);
if (color != default)
{
material.SetColor(id, color);
}
break;
case ShaderPropertyType.Vector:
var vector = mpb.GetVector(id);
if (vector != default)
{
material.SetVector(id, vector);
}
break;
case ShaderPropertyType.Float:
case ShaderPropertyType.Range:
var value = mpb.GetFloat(id);
if (!Mathf.Approximately(value, 0))
{
material.SetFloat(id, value);
}
break;
case ShaderPropertyType.Texture:
var tex = mpb.GetTexture(id);
if (tex != default(Texture))
{
material.SetTexture(id, tex);
}
break;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c434da72184404a0cbdf8e7a529a41bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
{
"name": "Coffee.UIParticle",
"references": [],
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7793e5cd8d2e94e21b56de41db6606bb
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f479867169fb04929b98c38e646b83c5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,143 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Coffee.UIExtensions
{
internal static class AnimatablePropertyEditor
{
private static readonly GUIContent s_ContentNothing = new GUIContent("Nothing");
private static readonly List<string> s_ActiveNames = new List<string>();
private static readonly StringBuilder s_Sb = new StringBuilder();
private static readonly HashSet<string> s_Names = new HashSet<string>();
private static string CollectActiveNames(SerializedProperty sp, List<string> result)
{
result.Clear();
for (var i = 0; i < sp.arraySize; i++)
{
var spName = sp.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name");
if (spName == null) continue;
result.Add(spName.stringValue);
}
s_Sb.Length = 0;
if (result.Count == 0)
{
s_Sb.Append("Nothing");
}
else
{
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
s_Sb.Length -= 2;
}
return s_Sb.ToString();
}
public static void Draw(SerializedProperty sp, Material[] mats)
{
bool isClicked;
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
{
var pos = EditorGUILayout.GetControlRect(true);
var label = new GUIContent(sp.displayName, sp.tooltip);
var rect = EditorGUI.PrefixLabel(pos, label);
var text = sp.hasMultipleDifferentValues
? "-"
: CollectActiveNames(sp, s_ActiveNames);
isClicked = GUI.Button(rect, text, EditorStyles.popup);
}
if (!isClicked) return;
var gm = new GenericMenu();
gm.AddItem(s_ContentNothing, s_ActiveNames.Count == 0, () =>
{
sp.ClearArray();
sp.serializedObject.ApplyModifiedProperties();
});
if (!sp.hasMultipleDifferentValues)
{
for (var i = 0; i < sp.arraySize; i++)
{
var p = sp.GetArrayElementAtIndex(i);
var name = p.FindPropertyRelative("m_Name").stringValue;
var type = (AnimatableProperty.ShaderPropertyType)p.FindPropertyRelative("m_Type").intValue;
AddMenu(gm, sp, new ShaderProperty(name, type), false);
}
}
s_Names.Clear();
for (var j = 0; j < mats.Length; j++)
{
var mat = mats[j];
if (!mat || !mat.shader) continue;
for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++)
{
var name = ShaderUtil.GetPropertyName(mat.shader, i);
var type = (AnimatableProperty.ShaderPropertyType)ShaderUtil.GetPropertyType(mat.shader, i);
if (s_Names.Contains(name)) continue;
s_Names.Add(name);
AddMenu(gm, sp, new ShaderProperty(name, type), true);
if (type != AnimatableProperty.ShaderPropertyType.Texture) continue;
AddMenu(gm, sp, new ShaderProperty($"{name}_ST"), true);
AddMenu(gm, sp, new ShaderProperty($"{name}_HDR"), true);
AddMenu(gm, sp, new ShaderProperty($"{name}_TexelSize"), true);
}
}
gm.ShowAsContext();
}
private static void AddMenu(GenericMenu menu, SerializedProperty sp, ShaderProperty prop, bool add)
{
if (add && s_ActiveNames.Contains(prop.name)) return;
var label = new GUIContent($"{prop.name} ({prop.type})");
menu.AddItem(label, s_ActiveNames.Contains(prop.name), () =>
{
var index = s_ActiveNames.IndexOf(prop.name);
if (0 <= index)
{
sp.DeleteArrayElementAtIndex(index);
}
else
{
sp.InsertArrayElementAtIndex(sp.arraySize);
var p = sp.GetArrayElementAtIndex(sp.arraySize - 1);
p.FindPropertyRelative("m_Name").stringValue = prop.name;
p.FindPropertyRelative("m_Type").intValue = (int)prop.type;
}
sp.serializedObject.ApplyModifiedProperties();
});
}
private struct ShaderProperty
{
public readonly string name;
public readonly AnimatableProperty.ShaderPropertyType type;
public ShaderProperty(string name)
{
this.name = name;
type = AnimatableProperty.ShaderPropertyType.Vector;
}
public ShaderProperty(string name, AnimatableProperty.ShaderPropertyType type)
{
this.name = name;
this.type = type;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 60feb9aeb134e4ec789c0e63b017997f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "Coffee.UIParticle.Editor",
"references": [
"Coffee.UIParticle"
],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": []
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 69deabfe8eed7495886c9daa69c9826a
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,102 @@
#if !UNITY_2019_1_OR_NEWER
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
namespace Coffee.UIExtensions
{
internal static class ImportSampleMenu_UIParticle
{
private const string k_DisplayName = "UI Particle";
private const string k_JsonGuid = "823dc693d087a4b559c7e1547274cc7d";
[MenuItem("Assets/Samples/" + k_DisplayName + "/Demo")]
private static void ImportSample()
{
ImportSample(k_JsonGuid, "Demo");
}
[MenuItem("Assets/Samples/" + k_DisplayName + "/Cartoon FX & War FX Demo")]
private static void ImportSample_CFX()
{
ImportSample(k_JsonGuid, "Cartoon FX & War FX Demo");
}
[MenuItem("Assets/Samples/" + k_DisplayName + "/Cartoon FX & War FX Demo")]
private static void ImportSample_PerformanceDemo()
{
ImportSample(k_JsonGuid, "Performance Demo");
}
private static void ImportSample(string jsonGuid, string sampleName)
{
var jsonPath = AssetDatabase.GUIDToAssetPath(jsonGuid);
if (string.IsNullOrEmpty(jsonPath)) return;
var jsonDir = Path.GetDirectoryName(jsonPath);
if (string.IsNullOrEmpty(jsonDir)) return;
var packageRoot = jsonDir.Replace('\\', '/');
var json = File.ReadAllText(jsonPath);
var version = Regex.Match(json, "\"version\"\\s*:\\s*\"([^\"]+)\"").Groups[1].Value;
var src = $"{packageRoot}/Samples~/{sampleName}";
var dst = $"Assets/Samples/{k_DisplayName}/{version}/{sampleName}";
var previousPath = GetPreviousSamplePath(k_DisplayName, sampleName);
// Remove the previous sample directory.
if (!string.IsNullOrEmpty(previousPath))
{
var msg = "A different version of the sample is already imported at\n\n"
+ previousPath
+ "\n\nIt will be deleted when you update. Are you sure you want to continue?";
if (!EditorUtility.DisplayDialog("Sample Importer", msg, "OK", "Cancel"))
{
return;
}
FileUtil.DeleteFileOrDirectory(previousPath);
var metaFile = previousPath + ".meta";
if (File.Exists(metaFile))
{
FileUtil.DeleteFileOrDirectory(metaFile);
}
}
if (!Directory.Exists(dst))
{
FileUtil.DeleteFileOrDirectory(dst);
}
var dstDir = Path.GetDirectoryName(dst);
if (!string.IsNullOrEmpty(dstDir) && !Directory.Exists(dstDir))
{
Directory.CreateDirectory(dstDir);
}
if (Directory.Exists(src))
{
FileUtil.CopyFileOrDirectory(src, dst);
}
else
{
throw new DirectoryNotFoundException(src);
}
AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
}
private static string GetPreviousSamplePath(string displayName, string sampleName)
{
var sampleRoot = $"Assets/Samples/{displayName}";
var sampleRootInfo = new DirectoryInfo(sampleRoot);
if (!sampleRootInfo.Exists) return null;
return sampleRootInfo.GetDirectories()
.Select(versionDir => Path.Combine(versionDir.ToString(), sampleName))
.FirstOrDefault(Directory.Exists);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07047cbd3c4af489fbd41f4303a26fe2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,597 @@
#if UNITY_2021_2_OR_NEWER
using UnityEditor.Overlays;
#else
using System.Reflection;
#endif
#if UNITY_2021_2_OR_NEWER
using UnityEditor.SceneManagement;
#elif UNITY_2018_3_OR_NEWER
using UnityEditor.Experimental.SceneManagement;
#endif
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Coffee.UIParticleExtensions;
using UnityEditor;
using UnityEditor.UI;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace Coffee.UIExtensions
{
[CustomEditor(typeof(UIParticle))]
[CanEditMultipleObjects]
internal class UIParticleEditor : GraphicEditor
{
#if UNITY_2021_2_OR_NEWER
#if UNITY_2022_1_OR_NEWER
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true,
defaultDockPosition = DockPosition.Bottom,
defaultDockZone = DockZone.Floating,
defaultLayout = Layout.Panel)]
#else
[Overlay(typeof(SceneView), "Scene View/UI Particles", "UI Particles", true)]
#endif
private class UIParticleOverlay : IMGUIOverlay, ITransientOverlay
{
public bool visible => s_SerializedObject != null;
public override void OnGUI()
{
if (visible)
{
WindowFunction(null, null);
}
}
}
#endif
//################################
// Constant or Static Members.
//################################
private static readonly GUIContent s_ContentRenderingOrder = new GUIContent("Rendering Order");
private static readonly GUIContent s_ContentRefresh = new GUIContent("Refresh");
private static readonly GUIContent s_ContentFix = new GUIContent("Fix");
private static readonly GUIContent s_ContentMaterial = new GUIContent("Material");
private static readonly GUIContent s_ContentTrailMaterial = new GUIContent("Trail Material");
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 SerializedObject s_SerializedObject;
private static bool s_XYZMode;
private SerializedProperty _maskable;
private SerializedProperty _scale3D;
private SerializedProperty _animatableProperties;
private SerializedProperty _meshSharing;
private SerializedProperty _groupId;
private SerializedProperty _groupMaxId;
private SerializedProperty _positionMode;
private SerializedProperty _autoScaling;
private ReorderableList _ro;
private bool _showMax;
private static readonly HashSet<Shader> s_Shaders = new HashSet<Shader>();
private static readonly List<ParticleSystemVertexStream> s_Streams = new List<ParticleSystemVertexStream>();
private static readonly List<string> s_MaskablePropertyNames = new List<string>
{
"_Stencil",
"_StencilComp",
"_StencilOp",
"_StencilWriteMask",
"_StencilReadMask",
"_ColorMask"
};
[InitializeOnLoadMethod]
private static void Init()
{
#if !UNITY_2021_2_OR_NEWER
var miSceneViewOverlayWindow = Type.GetType("UnityEditor.SceneViewOverlay, UnityEditor")
?.GetMethods(BindingFlags.Public | BindingFlags.Static)
.First(x => x.Name == "Window" && 5 <= x.GetParameters().Length);
var windowFunction = (Action<Object, SceneView>)WindowFunction;
var windowFunctionType = Type.GetType("UnityEditor.SceneViewOverlay+WindowFunction, UnityEditor");
var windowFunctionDelegate = Delegate.CreateDelegate(windowFunctionType, windowFunction.Method);
var windowTitle = new GUIContent(ObjectNames.NicifyVariableName(nameof(UIParticle)));
#if UNITY_2019_2_OR_NEWER
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option, EditorWindow window = null)
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2, null };
#else
//public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option)
var sceneViewArgs = new object[] { windowTitle, windowFunctionDelegate, 599, null, 2 };
#endif
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui += _ =>
#else
SceneView.onSceneGUIDelegate += _ =>
#endif
{
if (s_SerializedObject != null)
{
miSceneViewOverlayWindow.Invoke(null, sceneViewArgs);
}
};
#endif
SerializedObject CreateSerializeObject()
{
var uiParticles = Selection.gameObjects.Select(x => x.GetComponent<ParticleSystem>())
.Where(x => x)
.Select(x => x.GetComponentInParent<UIParticle>(true))
.Where(x => x && x.canvas)
.Concat(Selection.gameObjects.Select(x => x.GetComponent<UIParticle>())
.Where(x => x && x.canvas))
.Distinct()
.ToArray();
return 0 < uiParticles.Length ? new SerializedObject(uiParticles) : null;
}
s_SerializedObject = CreateSerializeObject();
Selection.selectionChanged += () => s_SerializedObject = CreateSerializeObject();
}
//################################
// Public/Protected Members.
//################################
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
_maskable = serializedObject.FindProperty("m_Maskable");
_scale3D = serializedObject.FindProperty("m_Scale3D");
_animatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
_meshSharing = serializedObject.FindProperty("m_MeshSharing");
_groupId = serializedObject.FindProperty("m_GroupId");
_groupMaxId = serializedObject.FindProperty("m_GroupMaxId");
_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)
{
elementHeight = EditorGUIUtility.singleLineHeight * 3 + 4,
elementHeightCallback = _ => 3 * (EditorGUIUtility.singleLineHeight + 2),
drawElementCallback = (rect, index, _, __) =>
{
EditorGUI.BeginDisabledGroup(sp.hasMultipleDifferentValues);
rect.y += 1;
rect.height = EditorGUIUtility.singleLineHeight;
var p = sp.GetArrayElementAtIndex(index);
EditorGUI.ObjectField(rect, p, GUIContent.none);
rect.x += 15;
rect.width -= 15;
var ps = p.objectReferenceValue as ParticleSystem;
var materials = ps
? new SerializedObject(ps.GetComponent<ParticleSystemRenderer>()).FindProperty("m_Materials")
: null;
rect.y += rect.height + 1;
MaterialField(rect, s_ContentMaterial, materials, 0);
rect.y += rect.height + 1;
MaterialField(rect, s_ContentTrailMaterial, materials, 1);
EditorGUI.EndDisabledGroup();
if (materials != null && materials.serializedObject.hasModifiedProperties)
{
materials.serializedObject.ApplyModifiedProperties();
}
},
drawHeaderCallback = rect =>
{
#if !UNITY_2019_3_OR_NEWER
rect.y -= 1;
#endif
var pos = new Rect(rect.x, rect.y, 150, rect.height);
EditorGUI.LabelField(pos, s_ContentRenderingOrder);
pos = new Rect(rect.width - 35, rect.y, 60, rect.height);
if (GUI.Button(pos, s_ContentRefresh, EditorStyles.miniButton))
{
foreach (var uip in targets.OfType<UIParticle>())
{
uip.RefreshParticles();
EditorUtility.SetDirty(uip);
}
}
}
};
// On select UIParticle, refresh particles.
if (!Application.isPlaying)
{
foreach (var uip in targets.OfType<UIParticle>())
{
if (PrefabUtility.GetPrefabAssetType(uip) != PrefabAssetType.NotAPrefab) continue;
uip.RefreshParticles(uip.particles);
}
}
}
private static void MaterialField(Rect rect, GUIContent label, SerializedProperty sp, int index)
{
if (sp == null || sp.arraySize <= index)
{
EditorGUI.BeginDisabledGroup(true);
EditorGUI.ObjectField(rect, label, null, typeof(Material), true);
EditorGUI.EndDisabledGroup();
}
else
{
EditorGUI.PropertyField(rect, sp.GetArrayElementAtIndex(index), label);
}
}
/// <summary>
/// Implement this function to make a custom inspector.
/// </summary>
public override void OnInspectorGUI()
{
var current = target as UIParticle;
if (!current) return;
serializedObject.Update();
// Maskable
EditorGUILayout.PropertyField(_maskable);
// Scale
EditorGUI.BeginDisabledGroup(!_meshSharing.hasMultipleDifferentValues && _meshSharing.intValue == 4);
s_XYZMode = DrawFloatOrVector3Field(_scale3D, s_XYZMode);
EditorGUI.EndDisabledGroup();
// AnimatableProperties
var mats = current.particles
.Where(x => x)
.Select(x => x.GetComponent<ParticleSystemRenderer>().sharedMaterial)
.Where(x => x)
.ToArray();
AnimatablePropertyEditor.Draw(_animatableProperties, mats);
// Mesh sharing
EditorGUI.BeginChangeCheck();
_showMax = DrawMeshSharing(_meshSharing, _groupId, _groupMaxId, _showMax);
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
foreach (var uip in targets.OfType<UIParticle>())
{
uip.ResetGroupId();
}
}
// Position Mode
EditorGUILayout.PropertyField(_positionMode);
// Auto Scaling
DrawAutoScaling(_autoScaling, targets.OfType<UIParticle>());
// Target ParticleSystems.
EditorGUI.BeginChangeCheck();
EditorGUI.BeginDisabledGroup(targets.OfType<UIParticle>().Any(x => !x.canvas));
_ro.DoLayoutList();
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
if (EditorGUI.EndChangeCheck())
{
foreach (var uip in targets.OfType<UIParticle>())
{
uip.RefreshParticles(uip.particles);
}
}
// Non-UI built-in shader is not supported.
foreach (var mat in current.materials)
{
if (!mat || !mat.shader) continue;
var shader = mat.shader;
if (IsBuiltInObject(shader) && !shader.name.StartsWith("UI/"))
{
EditorGUILayout.HelpBox(
$"Built-in shader '{shader.name}' in '{mat.name}' is not supported.\n" +
"Use UI shaders instead.",
MessageType.Error);
}
}
// Does the shader support UI masks?
if (current.maskable && current.GetComponentInParent<Mask>(false))
{
foreach (var mat in current.materials)
{
if (!mat || !mat.shader) continue;
var shader = mat.shader;
if (s_Shaders.Contains(shader)) continue;
s_Shaders.Add(shader);
foreach (var propName in s_MaskablePropertyNames)
{
if (mat.HasProperty(propName)) continue;
EditorGUILayout.HelpBox(
$"Shader '{shader.name}' doesn't have '{propName}' property." +
"\nThis graphic cannot be masked.",
MessageType.Warning);
break;
}
}
}
s_Shaders.Clear();
// UIParticle for trail should be removed.
var label = "This UIParticle component should be removed. The UIParticle for trails is no longer needed.";
if (FixButton(current.m_IsTrail, label))
{
DestroyUIParticle(current);
}
// #203: When using linear color space, the particle colors are not output correctly.
// To fix, set 'Apply Active Color Space' in renderer module to false.
var allPsRenderers = targets.OfType<UIParticle>()
.SelectMany(x => x.particles)
.Where(x => x)
.Select(x => x.GetComponent<ParticleSystemRenderer>())
.ToArray();
if (0 < allPsRenderers.Length)
{
var so = new SerializedObject(allPsRenderers);
var sp = so.FindProperty("m_ApplyActiveColorSpace");
label = "When using linear color space, the particle colors are not output correctly.\n" +
"To fix, set 'Apply Active Color Space' in renderer module to false.";
if (FixButton(sp.boolValue || sp.hasMultipleDifferentValues, label))
{
sp.boolValue = false;
so.ApplyModifiedProperties();
}
// Check to use 'TEXCOORD*.zw' components as custom vertex stream.
foreach (var psr in allPsRenderers)
{
if (!new SerializedObject(psr).FindProperty("m_UseCustomVertexStreams").boolValue) continue;
if (psr.activeVertexStreamsCount == 0) continue;
psr.GetActiveVertexStreams(s_Streams);
if (2 < s_Streams.Select(GetUsedComponentCount).Sum())
{
EditorGUILayout.HelpBox(
$"ParticleSystem '{psr.name}' uses 'TEXCOORD*.zw' components as custom vertex stream.\n" +
"UIParticle does not support it (See README.md).",
MessageType.Warning);
}
s_Streams.Clear();
}
}
}
private bool IsBuiltInObject(Object obj)
{
return AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)
&& Regex.IsMatch(guid, "^0{16}.0{15}$", RegexOptions.Compiled);
}
private static int GetUsedComponentCount(ParticleSystemVertexStream s)
{
switch (s)
{
case ParticleSystemVertexStream.Position:
case ParticleSystemVertexStream.Normal:
case ParticleSystemVertexStream.Tangent:
case ParticleSystemVertexStream.Color:
return 0;
case ParticleSystemVertexStream.UV:
case ParticleSystemVertexStream.UV2:
case ParticleSystemVertexStream.UV3:
case ParticleSystemVertexStream.UV4:
case ParticleSystemVertexStream.SizeXY:
case ParticleSystemVertexStream.StableRandomXY:
case ParticleSystemVertexStream.VaryingRandomXY:
case ParticleSystemVertexStream.Custom1XY:
case ParticleSystemVertexStream.Custom2XY:
case ParticleSystemVertexStream.NoiseSumXY:
case ParticleSystemVertexStream.NoiseImpulseXY:
return 2;
case ParticleSystemVertexStream.AnimBlend:
case ParticleSystemVertexStream.AnimFrame:
case ParticleSystemVertexStream.VertexID:
case ParticleSystemVertexStream.SizeX:
case ParticleSystemVertexStream.Rotation:
case ParticleSystemVertexStream.RotationSpeed:
case ParticleSystemVertexStream.Velocity:
case ParticleSystemVertexStream.Speed:
case ParticleSystemVertexStream.AgePercent:
case ParticleSystemVertexStream.InvStartLifetime:
case ParticleSystemVertexStream.StableRandomX:
case ParticleSystemVertexStream.VaryingRandomX:
case ParticleSystemVertexStream.Custom1X:
case ParticleSystemVertexStream.Custom2X:
case ParticleSystemVertexStream.NoiseSumX:
case ParticleSystemVertexStream.NoiseImpulseX:
return 1;
case ParticleSystemVertexStream.Center:
case ParticleSystemVertexStream.SizeXYZ:
case ParticleSystemVertexStream.Rotation3D:
case ParticleSystemVertexStream.RotationSpeed3D:
case ParticleSystemVertexStream.StableRandomXYZ:
case ParticleSystemVertexStream.VaryingRandomXYZ:
case ParticleSystemVertexStream.Custom1XYZ:
case ParticleSystemVertexStream.Custom2XYZ:
case ParticleSystemVertexStream.NoiseSumXYZ:
case ParticleSystemVertexStream.NoiseImpulseXYZ:
return 3;
case ParticleSystemVertexStream.StableRandomXYZW:
case ParticleSystemVertexStream.VaryingRandomXYZW:
case ParticleSystemVertexStream.Custom1XYZW:
case ParticleSystemVertexStream.Custom2XYZW:
return 4;
}
return 3;
}
private static bool DrawMeshSharing(SerializedProperty spMeshSharing, SerializedProperty spGroupId,
SerializedProperty spGroupMaxId, bool showMax)
{
showMax |= spGroupId.intValue != spGroupMaxId.intValue ||
spGroupId.hasMultipleDifferentValues ||
spGroupMaxId.hasMultipleDifferentValues;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(spMeshSharing);
EditorGUI.BeginChangeCheck();
showMax = GUILayout.Toggle(showMax, s_ContentRandom, EditorStyles.miniButton, GUILayout.Width(60));
if (EditorGUI.EndChangeCheck() && !showMax)
{
spGroupMaxId.intValue = spGroupId.intValue;
}
EditorGUILayout.EndHorizontal();
EditorGUI.BeginDisabledGroup(spMeshSharing.intValue == 0);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(spGroupId);
if (showMax)
{
EditorGUILayout.PropertyField(spGroupMaxId);
}
else if (spMeshSharing.intValue == 1 || spMeshSharing.intValue == 4)
{
EditorGUI.BeginDisabledGroup(true);
var obj = UIParticleUpdater.GetPrimary(spGroupId.intValue);
EditorGUILayout.ObjectField("Primary", obj, typeof(UIParticle), false);
EditorGUI.EndDisabledGroup();
}
EditorGUI.indentLevel--;
EditorGUI.EndDisabledGroup();
return showMax;
}
private static void DrawAutoScaling(SerializedProperty prop, IEnumerable<UIParticle> uiParticles)
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(prop);
if (!EditorGUI.EndChangeCheck()) return;
// on changed true->false, reset scale.
EditorApplication.delayCall += () =>
{
foreach (var uip in uiParticles)
{
if (!uip || uip.autoScaling) continue;
uip.transform.localScale = Vector3.one;
}
};
}
private static void WindowFunction(Object target, SceneView sceneView)
{
try
{
if (s_SerializedObject == null || !s_SerializedObject.targetObject) 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)))
{
var labelWidth = EditorGUIUtility.labelWidth;
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_PositionMode"));
DrawAutoScaling(s_SerializedObject.FindProperty("m_AutoScaling"), uiParticles);
EditorGUIUtility.labelWidth = labelWidth;
}
s_SerializedObject.ApplyModifiedProperties();
}
catch
{
// ignored
}
}
private void DestroyUIParticle(UIParticle p, bool ignoreCurrent = false)
{
if (!p || (ignoreCurrent && target == p)) return;
var cr = p.canvasRenderer;
DestroyImmediate(p);
DestroyImmediate(cr);
#if UNITY_2018_3_OR_NEWER
var stage = PrefabStageUtility.GetCurrentPrefabStage();
if (stage != null && stage.scene.isLoaded)
{
#if UNITY_2020_1_OR_NEWER
string prefabAssetPath = stage.assetPath;
#else
var prefabAssetPath = stage.prefabAssetPath;
#endif
PrefabUtility.SaveAsPrefabAsset(stage.prefabContentsRoot, prefabAssetPath);
}
#endif
}
private static bool FixButton(bool show, string text)
{
if (!show) return false;
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(true)))
{
EditorGUILayout.HelpBox(text, MessageType.Warning, true);
using (new EditorGUILayout.VerticalScope())
{
return GUILayout.Button(s_ContentFix, GUILayout.Width(30));
}
}
}
private static bool DrawFloatOrVector3Field(SerializedProperty sp, bool showXyz)
{
var x = sp.FindPropertyRelative("x");
var y = sp.FindPropertyRelative("y");
var z = sp.FindPropertyRelative("z");
showXyz |= !Mathf.Approximately(x.floatValue, y.floatValue) ||
!Mathf.Approximately(y.floatValue, z.floatValue) ||
y.hasMultipleDifferentValues ||
z.hasMultipleDifferentValues;
EditorGUILayout.BeginHorizontal();
if (showXyz)
{
EditorGUILayout.PropertyField(sp);
}
else
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(x, s_ContentScale);
if (EditorGUI.EndChangeCheck())
{
y.floatValue = z.floatValue = x.floatValue;
}
}
EditorGUI.BeginChangeCheck();
showXyz = GUILayout.Toggle(showXyz, s_Content3D, EditorStyles.miniButton, GUILayout.Width(30));
if (EditorGUI.EndChangeCheck() && !showXyz)
{
z.floatValue = y.floatValue = x.floatValue;
}
EditorGUILayout.EndHorizontal();
return showXyz;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 37cdd12f98487483aba53394d2174e31
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
namespace Coffee.UIExtensions
{
internal class UIParticleMenu
{
[MenuItem("GameObject/UI/Particle System (Empty)", false, 2018)]
private static void AddParticleEmpty(MenuCommand menuCommand)
{
// Create empty UI element.
EditorApplication.ExecuteMenuItem("GameObject/UI/Image");
var ui = Selection.activeGameObject;
Object.DestroyImmediate(ui.GetComponent<Image>());
// Add UIParticle.
var uiParticle = ui.AddComponent<UIParticle>();
uiParticle.name = "UIParticle";
uiParticle.scale = 10;
uiParticle.rectTransform.sizeDelta = Vector2.zero;
}
[MenuItem("GameObject/UI/Particle System", false, 2019)]
private static void AddParticle(MenuCommand menuCommand)
{
// Create empty UIEffect.
AddParticleEmpty(menuCommand);
var uiParticle = Selection.activeGameObject.GetComponent<UIParticle>();
// Create ParticleSystem.
EditorApplication.ExecuteMenuItem("GameObject/Effects/Particle System");
var ps = Selection.activeGameObject;
ps.transform.SetParent(uiParticle.transform, false);
ps.transform.localPosition = Vector3.zero;
// Assign default material (UIAdditive).
var renderer = ps.GetComponent<ParticleSystemRenderer>();
var path = AssetDatabase.GUIDToAssetPath("9944483a3e009401ba5dcc42f14d5c63");
renderer.material = AssetDatabase.LoadAssetAtPath<Material>(path);
// Refresh particles.
uiParticle.RefreshParticles();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ad158a8abf7646d6b540eed4a91a2dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
using System.Collections.Generic;
using UnityEngine;
namespace Coffee.UIParticleExtensions
{
internal class ModifiedMaterial
{
private static readonly List<MatEntry> s_Entries = new List<MatEntry>();
public static Material Add(Material baseMat, Texture texture, int id)
{
MatEntry e;
for (var i = 0; i < s_Entries.Count; i++)
{
e = s_Entries[i];
if (e.baseMat != baseMat || e.texture != texture || e.id != id) continue;
++e.count;
return e.customMat;
}
e = new MatEntry
{
count = 1,
baseMat = baseMat,
texture = texture,
id = id,
customMat = new Material(baseMat)
{
name = $"{baseMat.name}_{id}",
hideFlags = HideFlags.HideAndDontSave,
mainTexture = texture ? texture : null
}
};
s_Entries.Add(e);
//Debug.LogFormat(">>>> ModifiedMaterial.Add -> count = count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count, baseMat, texture, id);
return e.customMat;
}
public static void Remove(Material customMat)
{
if (!customMat) return;
for (var i = 0; i < s_Entries.Count; ++i)
{
var e = s_Entries[i];
if (e.customMat != customMat) continue;
if (--e.count == 0)
{
//Debug.LogFormat(">>>> ModifiedMaterial.Remove -> count:{0}, mat:{1}, tex:{2}, id:{3}", s_Entries.Count - 1, e.customMat, e.texture, e.id);
Misc.DestroyImmediate(e.customMat);
e.customMat = null;
e.baseMat = null;
e.texture = null;
s_Entries.RemoveAt(i);
}
break;
}
}
private class MatEntry
{
public Material baseMat;
public int count;
public Material customMat;
public int id;
public Texture texture;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b0beae5bb1cb142b9ab90dc0d371f026
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,629 @@
#if UNITY_2019_3_11 || UNITY_2019_3_12 || UNITY_2019_3_13 || UNITY_2019_3_14 || UNITY_2019_3_15 || UNITY_2019_4_OR_NEWER
#define SERIALIZE_FIELD_MASKABLE
#endif
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Coffee.UIParticleExtensions;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
using UnityEngine.UI;
[assembly: InternalsVisibleTo("Coffee.UIParticle.Editor")]
namespace Coffee.UIExtensions
{
/// <summary>
/// Render maskable and sortable particle effect ,without Camera, RenderTexture or Canvas.
/// </summary>
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
public class UIParticle : MaskableGraphic, ISerializationCallbackReceiver
{
public enum MeshSharing
{
None,
Auto,
Primary,
PrimarySimulator,
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);
[Tooltip("Animatable material properties.\n" +
"If you want to change the material properties of the ParticleSystem in Animation, enable it.")]
[SerializeField]
internal AnimatableProperty[] m_AnimatableProperties = new AnimatableProperty[0];
[Tooltip("Particles")]
[SerializeField]
private List<ParticleSystem> m_Particles = new List<ParticleSystem>();
[Tooltip("Mesh sharing.\n" +
"None: disable mesh sharing.\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" +
"Replica: render simulation results provided by the primary.")]
[SerializeField]
private MeshSharing m_MeshSharing = MeshSharing.None;
[Tooltip("Mesh sharing group ID.\n" +
"If non-zero is specified, particle simulation results are shared within the group.")]
[SerializeField]
private int m_GroupId;
[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]
private PositionMode m_PositionMode = PositionMode.Relative;
[SerializeField]
[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]
private bool m_Maskable = true;
#endif
private readonly List<UIParticleRenderer> _renderers = new List<UIParticleRenderer>();
private int _groupId;
private Camera _orthoCamera;
private DrivenRectTransformTracker _tracker;
/// <summary>
/// Should this graphic be considered a target for ray-casting?
/// </summary>
public override bool raycastTarget
{
get { return false; }
set { }
}
/// <summary>
/// Mesh sharing.
/// 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.
/// </summary>
public MeshSharing meshSharing
{
get { return m_MeshSharing; }
set { m_MeshSharing = value; }
}
/// <summary>
/// Mesh sharing group ID.
/// If non-zero is specified, particle simulation results are shared within the group.
/// </summary>
public int groupId
{
get { return _groupId; }
set
{
if (m_GroupId == value) return;
m_GroupId = value;
if (m_GroupId != m_GroupMaxId)
{
ResetGroupId();
}
}
}
public int groupMaxId
{
get { return m_GroupMaxId; }
set
{
if (m_GroupMaxId == value) return;
m_GroupMaxId = value;
ResetGroupId();
}
}
/// <summary>
/// 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 PositionMode positionMode
{
get { return m_PositionMode; }
set { m_PositionMode = value; }
}
/// <summary>
/// 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.
/// </summary>
public bool autoScaling
{
get { return m_AutoScaling; }
set
{
if (m_AutoScaling == value) return;
m_AutoScaling = value;
UpdateTracker();
}
}
internal bool useMeshSharing
{
get { return m_MeshSharing != MeshSharing.None; }
}
internal bool isPrimary
{
get
{
return m_MeshSharing == MeshSharing.Primary
|| m_MeshSharing == MeshSharing.PrimarySimulator;
}
}
internal bool canSimulate
{
get
{
return m_MeshSharing == MeshSharing.None
|| m_MeshSharing == MeshSharing.Auto
|| m_MeshSharing == MeshSharing.Primary
|| m_MeshSharing == MeshSharing.PrimarySimulator;
}
}
internal bool canRender
{
get
{
return m_MeshSharing == MeshSharing.None
|| m_MeshSharing == MeshSharing.Auto
|| m_MeshSharing == MeshSharing.Primary
|| m_MeshSharing == MeshSharing.Replica;
}
}
/// <summary>
/// Particle effect scale.
/// </summary>
public float scale
{
get { return m_Scale3D.x; }
set { m_Scale3D = new Vector3(value, value, value); }
}
/// <summary>
/// Particle effect scale.
/// </summary>
public Vector3 scale3D
{
get { return m_Scale3D; }
set { m_Scale3D = value; }
}
public List<ParticleSystem> particles
{
get { return 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
{
get { return null; }
}
/// <summary>
/// Paused.
/// </summary>
public bool isPaused { get; private set; }
public Vector3 parentScale { get; private set; }
protected override void OnEnable()
{
#if !SERIALIZE_FIELD_MASKABLE
maskable = m_Maskable;
#endif
ResetGroupId();
UpdateTracker();
UIParticleUpdater.Register(this);
RegisterDirtyMaterialCallback(UpdateRendererMaterial);
if (0 < particles.Count)
{
RefreshParticles(particles);
}
else
{
RefreshParticles();
}
base.OnEnable();
}
/// <summary>
/// This function is called when the behaviour becomes disabled.
/// </summary>
protected override void OnDisable()
{
UpdateTracker();
UIParticleUpdater.Unregister(this);
_renderers.ForEach(r => r.Reset());
UnregisterDirtyMaterialCallback(UpdateRendererMaterial);
base.OnDisable();
}
/// <summary>
/// Callback for when properties have been changed by animation.
/// </summary>
protected override void OnDidApplyAnimationProperties()
{
}
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
UpdateTracker();
}
#endif
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (m_IgnoreCanvasScaler)
{
m_IgnoreCanvasScaler = false;
m_AutoScaling = false;
}
if (m_AbsoluteMode)
{
m_AbsoluteMode = false;
m_PositionMode = PositionMode.Absolute;
}
}
public void Play()
{
particles.Exec(p => p.Simulate(0, false, true));
isPaused = false;
}
public void Pause()
{
particles.Exec(p => p.Pause());
isPaused = true;
}
public void Resume()
{
isPaused = false;
}
public void Stop()
{
particles.Exec(p => p.Stop());
isPaused = true;
}
public void StartEmission()
{
particles.Exec(p =>
{
var emission = p.emission;
emission.enabled = true;
});
}
public void StopEmission()
{
particles.Exec(p =>
{
var emission = p.emission;
emission.enabled = false;
});
}
public void Clear()
{
particles.Exec(p => p.Clear());
isPaused = true;
}
public void SetParticleSystemInstance(GameObject instance)
{
SetParticleSystemInstance(instance, true);
}
public void SetParticleSystemInstance(GameObject instance, bool destroyOldParticles)
{
if (!instance) return;
foreach (Transform child in transform)
{
var go = child.gameObject;
go.SetActive(false);
if (destroyOldParticles)
{
Misc.Destroy(go);
}
}
var tr = instance.transform;
tr.SetParent(transform, false);
tr.localPosition = Vector3.zero;
RefreshParticles(instance);
}
public void SetParticleSystemPrefab(GameObject prefab)
{
if (!prefab) return;
SetParticleSystemInstance(Instantiate(prefab.gameObject), true);
}
public void RefreshParticles()
{
RefreshParticles(gameObject);
}
private void RefreshParticles(GameObject root)
{
if (!root) return;
root.GetComponentsInChildren(true, particles);
particles.RemoveAll(x => x.GetComponentInParent<UIParticle>(true) != this);
for (var i = 0; i < particles.Count; i++)
{
var ps = particles[i];
var tsa = ps.textureSheetAnimation;
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
{
tsa.uvChannelMask = UVChannelFlags.UV0;
}
}
RefreshParticles(particles);
}
public void RefreshParticles(List<ParticleSystem> particles)
{
// #246: Nullptr exceptions when using nested UIParticle components in hierarchy
_renderers.Clear();
foreach (Transform child in transform)
{
var uiParticleRenderer = child.GetComponent<UIParticleRenderer>();
if (uiParticleRenderer != null)
{
_renderers.Add(uiParticleRenderer);
}
}
for (var i = 0; i < _renderers.Count; i++)
{
_renderers[i].Reset(i);
}
var j = 0;
for (var i = 0; i < particles.Count; i++)
{
var ps = particles[i];
if (!ps) continue;
GetRenderer(j++).Set(this, ps, false);
if (ps.trails.enabled)
{
GetRenderer(j++).Set(this, ps, true);
}
}
}
internal void UpdateTransformScale()
{
parentScale = transform.parent.lossyScale;
if (!autoScaling) return;
var newScale = parentScale.Inverse();
if (transform.localScale != newScale)
{
transform.localScale = newScale;
}
}
internal void UpdateRenderers()
{
if (!isActiveAndEnabled) return;
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (!r)
{
RefreshParticles(particles);
break;
}
}
var bakeCamera = GetBakeCamera();
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (!r) continue;
r.UpdateMesh(bakeCamera);
}
}
internal void UpdateParticleCount()
{
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (!r) continue;
r.UpdateParticleCount();
}
}
internal void ResetGroupId()
{
_groupId = m_GroupId == m_GroupMaxId
? m_GroupId
: Random.Range(m_GroupId, m_GroupMaxId + 1);
}
protected override void UpdateMaterial()
{
}
/// <summary>
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
/// </summary>
protected override void UpdateGeometry()
{
}
private void UpdateRendererMaterial()
{
for (var i = 0; i < _renderers.Count; i++)
{
var r = _renderers[i];
if (!r) continue;
r.maskable = maskable;
r.SetMaterialDirty();
}
}
internal UIParticleRenderer GetRenderer(int index)
{
if (_renderers.Count <= index)
{
_renderers.Add(UIParticleRenderer.AddRenderer(this, index));
}
if (!_renderers[index])
{
_renderers[index] = UIParticleRenderer.AddRenderer(this, index);
}
return _renderers[index];
}
private Camera GetBakeCamera()
{
if (!canvas) return Camera.main;
// When render mode is ScreenSpaceCamera or WorldSpace, use world camera.
var root = canvas.rootCanvas;
if (root.renderMode != RenderMode.ScreenSpaceOverlay)
{
return root.worldCamera ? root.worldCamera : Camera.main;
}
// When render mode is ScreenSpaceOverlay, use ortho-camera.
if (!_orthoCamera)
{
// Find existing ortho-camera.
foreach (Transform child in transform)
{
var cam = child.GetComponent<Camera>();
if (cam && cam.name == "[generated] UIParticleOverlayCamera")
{
_orthoCamera = cam;
break;
}
}
// Create ortho-camera.
if (!_orthoCamera)
{
var go = new GameObject("[generated] UIParticleOverlayCamera") { hideFlags = HideFlags.DontSave };
go.SetActive(false);
go.transform.SetParent(transform, false);
_orthoCamera = go.AddComponent<Camera>();
_orthoCamera.enabled = false;
}
}
//
var size = ((RectTransform)root.transform).rect.size;
_orthoCamera.orthographicSize = Mathf.Max(size.x, size.y) * root.scaleFactor;
_orthoCamera.transform.SetPositionAndRotation(new Vector3(0, 0, -1000), Quaternion.identity);
_orthoCamera.orthographic = true;
_orthoCamera.farClipPlane = 2000f;
return _orthoCamera;
}
private void UpdateTracker()
{
if (!enabled || !autoScaling)
{
_tracker.Clear();
}
else
{
_tracker.Add(this, rectTransform, DrivenTransformProperties.Scale);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16f0b0b6d0b7542bfbd20a3e05b04ff1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,324 @@
using System;
using Coffee.UIParticleExtensions;
using UnityEngine;
using UnityEngine.Events;
namespace Coffee.UIExtensions
{
[ExecuteAlways]
public class UIParticleAttractor : MonoBehaviour
{
public enum Movement
{
Linear,
Smooth,
Sphere
}
public enum UpdateMode
{
Normal,
UnscaledTime
}
[SerializeField]
private ParticleSystem m_ParticleSystem;
[Range(0.1f, 10f)]
[SerializeField]
private float m_DestinationRadius = 1;
[Range(0f, 0.95f)]
[SerializeField]
private float m_DelayRate = 0.4f;
[Range(0.001f, 100f)]
[SerializeField]
private float m_MaxSpeed = 1;
[SerializeField]
private Movement m_Movement;
[SerializeField]
private UpdateMode m_UpdateMode;
[SerializeField]
private UnityEvent m_OnAttracted;
[SerializeField]
private UnityEvent m_OnAttractedStart;
[SerializeField]
private UnityEvent m_OnAttractedEnd;
private UIParticle _uiParticle;
public float destinationRadius
{
get { return m_DestinationRadius; }
set { m_DestinationRadius = Mathf.Clamp(value, 0.1f, 10f); }
}
public float delay
{
get { return m_DelayRate; }
set { m_DelayRate = value; }
}
public float maxSpeed
{
get { return m_MaxSpeed; }
set { m_MaxSpeed = value; }
}
public Movement movement
{
get { return m_Movement; }
set { m_Movement = value; }
}
public UpdateMode updateMode
{
get { return m_UpdateMode; }
set { m_UpdateMode = value; }
}
public UnityEvent onAttracted
{
get { return m_OnAttracted; }
set { m_OnAttracted = value; }
}
public UnityEvent onAttractedStart
{
get { return m_OnAttractedStart; }
set { m_OnAttractedStart = value; }
}
public UnityEvent onAttractedEnd
{
get { return m_OnAttractedEnd; }
set { m_OnAttractedEnd = value; }
}
#if UNITY_EDITOR
public new ParticleSystem particleSystem
#else
public ParticleSystem particleSystem
#endif
{
get { return m_ParticleSystem; }
set
{
m_ParticleSystem = value;
ApplyParticleSystem();
}
}
private void OnEnable()
{
ApplyParticleSystem();
UIParticleUpdater.Register(this);
}
private void OnDisable()
{
if (m_OnAttractedEnd != null)
{
try
{
m_OnAttractedEnd.Invoke();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
UIParticleUpdater.Unregister(this);
}
private void OnDestroy()
{
_uiParticle = null;
m_ParticleSystem = null;
}
/// <summary>
/// 多个粒子飞向同一个target时,隐藏前一个粒子
/// </summary>
public void Clear()
{
if (m_ParticleSystem != null)
{
m_ParticleSystem.Clear();
}
}
internal void Attract()
{
if (m_ParticleSystem == null) return;
var count = m_ParticleSystem.particleCount;
if (count == 0) return;
var particles = ParticleSystemExtensions.GetParticleArray(count);
m_ParticleSystem.GetParticles(particles, count);
var dstPos = GetDestinationPosition();
for (var i = 0; i < count; i++)
{
// Attracted
var p = particles[i];
if (0f < p.remainingLifetime && Vector3.Distance(p.position, dstPos) < m_DestinationRadius)
{
p.remainingLifetime = 0f;
particles[i] = p;
if (m_OnAttracted != null)
{
try
{
m_OnAttracted.Invoke();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
if (i == 0)
{
if (m_OnAttractedStart != null)
{
try
{
m_OnAttractedStart.Invoke();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
}
if (i == count - 1)
{
if (m_OnAttractedEnd != null)
{
try
{
m_OnAttractedEnd.Invoke();
}
catch (Exception e)
{
Debug.LogException(e);
}
}
}
continue;
}
// Calc attracting time
var delayTime = p.startLifetime * m_DelayRate;
var duration = p.startLifetime - delayTime;
var time = Mathf.Max(0, p.startLifetime - p.remainingLifetime - delayTime);
// Delay
if (time <= 0) continue;
// Attract
p.position = GetAttractedPosition(p.position, dstPos, duration, time);
p.velocity *= 0.5f;
particles[i] = p;
}
m_ParticleSystem.SetParticles(particles, count);
}
private Vector3 GetDestinationPosition()
{
var isUI = _uiParticle && _uiParticle.enabled;
var psPos = m_ParticleSystem.transform.position;
var attractorPos = transform.position;
var dstPos = attractorPos;
var isLocalSpace = m_ParticleSystem.IsLocalSpace();
if (isLocalSpace)
{
dstPos = m_ParticleSystem.transform.InverseTransformPoint(dstPos);
}
if (isUI)
{
var inverseScale = _uiParticle.parentScale.Inverse();
dstPos = dstPos.GetScaled(inverseScale, _uiParticle.scale3D.Inverse());
// Relative mode
if (_uiParticle.positionMode == UIParticle.PositionMode.Relative)
{
var diff = _uiParticle.transform.position - psPos;
diff.Scale(_uiParticle.scale3D - inverseScale);
diff.Scale(_uiParticle.scale3D.Inverse());
dstPos += diff;
}
#if UNITY_EDITOR
if (!Application.isPlaying && !isLocalSpace)
{
dstPos += psPos - psPos.GetScaled(inverseScale, _uiParticle.scale3D.Inverse());
}
#endif
}
return dstPos;
}
private Vector3 GetAttractedPosition(Vector3 current, Vector3 target, float duration, float time)
{
var speed = m_MaxSpeed;
switch (m_UpdateMode)
{
case UpdateMode.Normal:
speed *= 60 * Time.deltaTime;
break;
case UpdateMode.UnscaledTime:
speed *= 60 * Time.unscaledDeltaTime;
break;
}
switch (m_Movement)
{
case Movement.Linear:
speed /= duration;
break;
case Movement.Smooth:
target = Vector3.Lerp(current, target, time / duration);
break;
case Movement.Sphere:
target = Vector3.Slerp(current, target, time / duration);
break;
}
return Vector3.MoveTowards(current, target, speed);
}
private void ApplyParticleSystem()
{
_uiParticle = null;
if (m_ParticleSystem == null)
{
//#if UNITY_EDITOR
// if (Application.isPlaying)
// {
// Debug.LogError("No particle system attached to particle attractor script", this);
// }
//#endif
return;
}
_uiParticle = m_ParticleSystem.GetComponentInParent<UIParticle>(true);
if (_uiParticle && !_uiParticle.particles.Contains(m_ParticleSystem))
{
_uiParticle = null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 00e55ae1441ff4583859c55384964d86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,666 @@
using System;
using System.Collections.Generic;
using Coffee.UIParticleExtensions;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.UI;
namespace Coffee.UIExtensions
{
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasRenderer))]
[AddComponentMenu("")]
internal class UIParticleRenderer : MaskableGraphic
{
private static readonly CombineInstance[] s_CombineInstances = { new CombineInstance() };
private static readonly List<Material> s_Materials = new List<Material>(2);
private static MaterialPropertyBlock s_Mpb;
private static readonly List<UIParticleRenderer> s_Renderers = new List<UIParticleRenderer>();
private static readonly Vector3[] s_Corners = new Vector3[4];
private Material _currentMaterialForRendering;
private bool _delay;
private int _index;
private bool _isTrail;
private Bounds _lastBounds;
private Material _modifiedMaterial;
private UIParticle _parent;
private ParticleSystem _particleSystem;
private int _prevParticleCount;
private Vector3 _prevPsPos;
private Vector3 _prevScale;
private Vector2Int _prevScreenSize;
private bool _prewarm;
private ParticleSystemRenderer _renderer;
public override Texture mainTexture
{
get { return _isTrail ? null : _particleSystem.GetTextureForSprite(); }
}
public override bool raycastTarget
{
get { return false; }
}
private Rect rootCanvasRect
{
get
{
s_Corners[0] = transform.TransformPoint(_lastBounds.min.x, _lastBounds.min.y, 0);
s_Corners[1] = transform.TransformPoint(_lastBounds.min.x, _lastBounds.max.y, 0);
s_Corners[2] = transform.TransformPoint(_lastBounds.max.x, _lastBounds.max.y, 0);
s_Corners[3] = transform.TransformPoint(_lastBounds.max.x, _lastBounds.min.y, 0);
if (canvas)
{
var worldToLocalMatrix = canvas.rootCanvas.transform.worldToLocalMatrix;
for (var i = 0; i < 4; ++i)
{
s_Corners[i] = worldToLocalMatrix.MultiplyPoint(s_Corners[i]);
}
}
var corner1 = (Vector2)s_Corners[0];
var corner2 = (Vector2)s_Corners[0];
for (var i = 1; i < 4; ++i)
{
if (s_Corners[i].x < corner1.x)
{
corner1.x = s_Corners[i].x;
}
else if (s_Corners[i].x > corner2.x)
{
corner2.x = s_Corners[i].x;
}
if (s_Corners[i].y < corner1.y)
{
corner1.y = s_Corners[i].y;
}
else if (s_Corners[i].y > corner2.y)
{
corner2.y = s_Corners[i].y;
}
}
return new Rect(corner1, corner2 - corner1);
}
}
public void Reset(int index = -1)
{
if (_renderer)
{
_renderer.enabled = true;
}
_parent = null;
_particleSystem = null;
_renderer = null;
_prevParticleCount = 0;
if (0 <= index)
{
_index = index;
}
//_emitter = null;
if (this && isActiveAndEnabled)
{
material = null;
workerMesh.Clear();
canvasRenderer.SetMesh(workerMesh);
_lastBounds = new Bounds();
enabled = false;
}
else
{
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
_currentMaterialForRendering = null;
}
}
protected override void OnEnable()
{
base.OnEnable();
if (!s_CombineInstances[0].mesh)
{
s_CombineInstances[0].mesh = new Mesh
{
name = "[UIParticleRenderer] Combine Instance Mesh",
hideFlags = HideFlags.HideAndDontSave
};
}
_currentMaterialForRendering = null;
raycastTarget = false;
}
protected override void OnDisable()
{
base.OnDisable();
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
_currentMaterialForRendering = null;
}
public static UIParticleRenderer AddRenderer(UIParticle parent, int index)
{
// Create renderer object.
var go = new GameObject("[generated] UIParticleRenderer", typeof(UIParticleRenderer))
{
hideFlags = HideFlags.DontSave,
layer = parent.gameObject.layer
};
// Set parent.
var transform = go.transform;
transform.SetParent(parent.transform, false);
transform.localPosition = Vector3.zero;
transform.localRotation = Quaternion.identity;
transform.localScale = Vector3.one;
// Add renderer component.
var renderer = go.GetComponent<UIParticleRenderer>();
renderer._parent = parent;
renderer._index = index;
return renderer;
}
/// <summary>
/// Perform material modification in this function.
/// </summary>
public override Material GetModifiedMaterial(Material baseMaterial)
{
_currentMaterialForRendering = null;
if (!IsActive() || !_parent)
{
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
return baseMaterial;
}
var modifiedMaterial = base.GetModifiedMaterial(baseMaterial);
//
var texture = mainTexture;
if (texture == null && _parent.m_AnimatableProperties.Length == 0)
{
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = null;
return modifiedMaterial;
}
//
var id = _parent.m_AnimatableProperties.Length == 0 ? 0 : GetInstanceID();
modifiedMaterial = ModifiedMaterial.Add(modifiedMaterial, texture, id);
ModifiedMaterial.Remove(_modifiedMaterial);
_modifiedMaterial = modifiedMaterial;
return modifiedMaterial;
}
public void Set(UIParticle parent, ParticleSystem ps, bool isTrail)
{
_parent = parent;
maskable = parent.maskable;
gameObject.layer = parent.gameObject.layer;
_particleSystem = ps;
_prewarm = _particleSystem.main.prewarm;
#if UNITY_EDITOR
if (Application.isPlaying)
#endif
{
if (_particleSystem.isPlaying || _prewarm)
{
_particleSystem.Clear();
_particleSystem.Pause();
}
}
_renderer = ps.GetComponent<ParticleSystemRenderer>();
_renderer.enabled = false;
//_emitter = emitter;
_isTrail = isTrail;
_renderer.GetSharedMaterials(s_Materials);
material = s_Materials[isTrail ? 1 : 0];
s_Materials.Clear();
// Support sprite.
var tsa = ps.textureSheetAnimation;
if (tsa.mode == ParticleSystemAnimationMode.Sprites && tsa.uvChannelMask == 0)
{
tsa.uvChannelMask = UVChannelFlags.UV0;
}
_prevScale = GetWorldScale();
_prevPsPos = _particleSystem.transform.position;
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
_delay = true;
_prevParticleCount = 0;
canvasRenderer.SetTexture(null);
enabled = true;
}
public void UpdateMesh(Camera bakeCamera)
{
// No particle to render: Clear mesh.
if (
!isActiveAndEnabled || !_particleSystem || !_parent
|| !canvasRenderer || !canvas || !bakeCamera
|| _parent.meshSharing == UIParticle.MeshSharing.Replica
|| !transform.lossyScale.GetScaled(_parent.scale3D).IsVisible() // Scale is not visible.
|| (!_particleSystem.IsAlive() && !_particleSystem.isPlaying) // No particle.
|| (_isTrail && !_particleSystem.trails.enabled) // Trail, but it is not enabled.
#if UNITY_2018_3_OR_NEWER
|| canvasRenderer.GetInheritedAlpha() <
0.01f // #102: Do not bake particle system to mesh when the alpha is zero.
#endif
)
{
Profiler.BeginSample("[UIParticleRenderer] Clear Mesh");
workerMesh.Clear();
canvasRenderer.SetMesh(workerMesh);
_lastBounds = new Bounds();
Profiler.EndSample();
return;
}
var main = _particleSystem.main;
var scale = GetWorldScale();
var psPos = _particleSystem.transform.position;
// Simulate particles.
Profiler.BeginSample("[UIParticle] Bake Mesh > Simulate Particles");
if (!_isTrail && _parent.canSimulate)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
SimulateForEditor(psPos - _prevPsPos, scale);
}
else
#endif
{
ResolveResolutionChange(psPos, scale);
Simulate(scale, _parent.isPaused || _delay);
if (_delay && !_parent.isPaused)
{
Simulate(scale, _parent.isPaused);
}
// When the ParticleSystem simulation is complete, stop it.
if (!main.loop
&& main.duration <= _particleSystem.time
&& (_particleSystem.IsAlive() || _particleSystem.particleCount == 0)
)
{
_particleSystem.Stop(false);
}
}
_prevScale = scale;
_prevPsPos = psPos;
_delay = false;
}
Profiler.EndSample();
// Bake mesh.
Profiler.BeginSample("[UIParticleRenderer] Bake Mesh");
if (_isTrail && _parent.canSimulate && 0 < s_CombineInstances[0].mesh.vertexCount)
{
_renderer.BakeTrailsMesh(s_CombineInstances[0].mesh, bakeCamera, true);
}
else if (_renderer.CanBakeMesh())
{
_renderer.BakeMesh(s_CombineInstances[0].mesh, bakeCamera, true);
}
else
{
s_CombineInstances[0].mesh.Clear(false);
}
// Too many vertices to render.
if (65535 <= s_CombineInstances[0].mesh.vertexCount)
{
s_CombineInstances[0].mesh.Clear(false);
Debug.LogErrorFormat(this,
"Too many vertices to render. index={0}, isTrail={1}, vertexCount={2}(>=65535)",
_index,
_isTrail,
s_CombineInstances[0].mesh.vertexCount
);
s_CombineInstances[0].mesh.Clear(false);
}
Profiler.EndSample();
// Combine mesh to transform. ([ParticleSystem local ->] world -> renderer local)
Profiler.BeginSample("[UIParticleRenderer] Combine Mesh");
if (_parent.canSimulate)
{
if (_parent.positionMode == UIParticle.PositionMode.Absolute)
{
s_CombineInstances[0].transform =
canvasRenderer.transform.worldToLocalMatrix
* GetWorldMatrix(psPos, scale);
}
else
{
var diff = _particleSystem.transform.position - _parent.transform.position;
s_CombineInstances[0].transform =
canvasRenderer.transform.worldToLocalMatrix
* Matrix4x4.Translate(diff.GetScaled(scale - Vector3.one))
* GetWorldMatrix(psPos, scale);
}
workerMesh.CombineMeshes(s_CombineInstances, true, true);
workerMesh.RecalculateBounds();
var bounds = workerMesh.bounds;
var center = bounds.center;
center.z = 0;
bounds.center = center;
var extents = bounds.extents;
extents.z = 0;
bounds.extents = extents;
workerMesh.bounds = bounds;
_lastBounds = bounds;
}
Profiler.EndSample();
// Get grouped renderers.
s_Renderers.Clear();
if (_parent.useMeshSharing)
{
UIParticleUpdater.GetGroupedRenderers(_parent.groupId, _index, s_Renderers);
}
// Set mesh to the CanvasRenderer.
Profiler.BeginSample("[UIParticleRenderer] Set Mesh");
for (var i = 0; i < s_Renderers.Count; i++)
{
if (s_Renderers[i] == this) continue;
s_Renderers[i].canvasRenderer.SetMesh(workerMesh);
s_Renderers[i]._lastBounds = _lastBounds;
}
if (!_parent.canRender)
{
workerMesh.Clear();
}
canvasRenderer.SetMesh(workerMesh);
Profiler.EndSample();
// Update animatable material properties.
Profiler.BeginSample("[UIParticleRenderer] Update Animatable Material Properties");
UpdateMaterialProperties();
if (!_parent.useMeshSharing)
{
if (!_currentMaterialForRendering)
{
_currentMaterialForRendering = materialForRendering;
}
for (var i = 0; i < s_Renderers.Count; i++)
{
if (s_Renderers[i] == this) continue;
s_Renderers[i].canvasRenderer.materialCount = 1;
s_Renderers[i].canvasRenderer.SetMaterial(_currentMaterialForRendering, 0);
}
}
Profiler.EndSample();
s_Renderers.Clear();
}
internal void UpdateParticleCount()
{
if (!_particleSystem) return;
_prevParticleCount = _particleSystem.particleCount;
}
/// <summary>
/// Call to update the geometry of the Graphic onto the CanvasRenderer.
/// </summary>
protected override void UpdateGeometry()
{
}
public override void Cull(Rect clipRect, bool validRect)
{
var cull = _lastBounds.extents == Vector3.zero
|| !validRect
|| !clipRect.Overlaps(rootCanvasRect, true);
if (canvasRenderer.cull == cull) return;
canvasRenderer.cull = cull;
UISystemProfilerApi.AddMarker("MaskableGraphic.cullingChanged", this);
onCullStateChanged.Invoke(cull);
OnCullingChanged();
}
private Vector3 GetWorldScale()
{
Profiler.BeginSample("[UIParticleRenderer] GetWorldScale");
var scale = _parent.scale3D.GetScaled(_parent.parentScale);
Profiler.EndSample();
return scale;
}
private Matrix4x4 GetWorldMatrix(Vector3 psPos, Vector3 scale)
{
var space = _particleSystem.GetActualSimulationSpace();
if (_isTrail && _particleSystem.trails.worldSpace)
{
space = ParticleSystemSimulationSpace.World;
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
switch (space)
{
case ParticleSystemSimulationSpace.World:
return Matrix4x4.Translate(psPos)
* Matrix4x4.Scale(scale)
* Matrix4x4.Translate(-psPos);
}
}
#endif
switch (space)
{
case ParticleSystemSimulationSpace.Local:
return Matrix4x4.Translate(psPos)
* Matrix4x4.Scale(scale);
case ParticleSystemSimulationSpace.World:
return Matrix4x4.Scale(scale);
case ParticleSystemSimulationSpace.Custom:
return Matrix4x4.Translate(_particleSystem.main.customSimulationSpace.position.GetScaled(scale))
//* Matrix4x4.Translate(wpos)
* Matrix4x4.Scale(scale)
//* Matrix4x4.Translate(-wpos)
;
default:
throw new NotSupportedException();
}
}
/// <summary>
/// For world simulation, interpolate particle positions when the screen size is changed.
/// </summary>
/// <param name="psPos"></param>
/// <param name="scale"></param>
private void ResolveResolutionChange(Vector3 psPos, Vector3 scale)
{
var screenSize = new Vector2Int(Screen.width, Screen.height);
var isWorldSpace = _particleSystem.IsWorldSpace();
var resolutionChanged = _prevScreenSize != screenSize || _prevScale != scale;
if (resolutionChanged && isWorldSpace)
{
// Update particle array size and get particles.
var size = _particleSystem.particleCount;
var particles = ParticleSystemExtensions.GetParticleArray(size);
_particleSystem.GetParticles(particles, size);
// Resolusion resolver:
// (psPos / scale) / (prevPsPos / prevScale) -> psPos * scale.inv * prevPsPos.inv * prevScale
var modifier = psPos.GetScaled(
scale.Inverse(),
_prevPsPos.Inverse(),
_prevScale);
for (var i = 0; i < size; i++)
{
var particle = particles[i];
particle.position = particle.position.GetScaled(modifier);
particles[i] = particle;
}
_particleSystem.SetParticles(particles, size);
// Delay: Do not progress in the frame where the resolution has been changed.
_delay = true;
_prevScale = scale;
_prevPsPos = psPos;
}
_prevScreenSize = screenSize;
}
private void Simulate(Vector3 scale, bool paused)
{
var main = _particleSystem.main;
var deltaTime = paused
? 0
: main.useUnscaledTime
? Time.unscaledDeltaTime
: Time.deltaTime;
// Prewarm:
if (0 < deltaTime && _prewarm)
{
deltaTime += main.duration;
_prewarm = false;
}
// (COMMENT OUT) #231: Sub Emitters option is not work in editor playing
/*
// Emitted particles found.
if (_prevParticleCount != _particleSystem.particleCount)
{
var size = _particleSystem.particleCount;
var particles = ParticleSystemExtensions.GetParticleArray(size);
_particleSystem.GetParticles(particles, size);
for (var i = _prevParticleCount; i < size; i++)
{
var p = particles[i];
p.position = p.position.GetScaled(scale.Inverse());
particles[i] = p;
}
_particleSystem.SetParticles(particles, size);
}
*/
// get world position.
var isLocalSpace = _particleSystem.IsLocalSpace();
var psTransform = _particleSystem.transform;
var originWorldPosition = psTransform.position;
var originWorldRotation = psTransform.rotation;
var emission = _particleSystem.emission;
var rateOverDistance = emission.enabled
&& 0 < emission.rateOverDistance.constant
&& 0 < emission.rateOverDistanceMultiplier;
if (rateOverDistance && !paused)
{
// (For rate-over-distance emission,) Move to previous scaled position, simulate (delta = 0).
var prevScaledPos = isLocalSpace
? _prevPsPos
: _prevPsPos.GetScaled(_prevScale.Inverse());
psTransform.SetPositionAndRotation(prevScaledPos, originWorldRotation);
_particleSystem.Simulate(0, false, false, false);
}
// Move to scaled position, simulate, revert to origin position.
var scaledPos = isLocalSpace
? originWorldPosition
: originWorldPosition.GetScaled(scale.Inverse());
psTransform.SetPositionAndRotation(scaledPos, originWorldRotation);
_particleSystem.Simulate(deltaTime, false, false, false);
psTransform.SetPositionAndRotation(originWorldPosition, originWorldRotation);
}
#if UNITY_EDITOR
private void SimulateForEditor(Vector3 diffPos, Vector3 scale)
{
// Extra world simulation.
var isWorldSpace = _particleSystem.IsWorldSpace();
if (isWorldSpace && 0 < Vector3.SqrMagnitude(diffPos))
{
Profiler.BeginSample("[UIParticle] Bake Mesh > Extra world simulation");
diffPos.x *= 1f - 1f / Mathf.Max(0.001f, scale.x);
diffPos.y *= 1f - 1f / Mathf.Max(0.001f, scale.y);
diffPos.z *= 1f - 1f / Mathf.Max(0.001f, scale.z);
var size = _particleSystem.particleCount;
var particles = ParticleSystemExtensions.GetParticleArray(size);
_particleSystem.GetParticles(particles, size);
for (var i = 0; i < size; i++)
{
var p = particles[i];
p.position += diffPos;
particles[i] = p;
}
_particleSystem.SetParticles(particles, size);
Profiler.EndSample();
}
}
#endif
private void UpdateMaterialProperties()
{
if (_parent.m_AnimatableProperties.Length == 0) return;
if (s_Mpb == null)
{
s_Mpb = new MaterialPropertyBlock();
}
_renderer.GetPropertyBlock(s_Mpb);
if (s_Mpb.isEmpty) return;
// #41: Copy the value from MaterialPropertyBlock to CanvasRenderer
if (!_modifiedMaterial) return;
for (var i = 0; i < _parent.m_AnimatableProperties.Length; i++)
{
var ap = _parent.m_AnimatableProperties[i];
ap.UpdateMaterialProperties(_modifiedMaterial, s_Mpb);
}
s_Mpb.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0e66d2d1ba43c4cc4bc3e754e403297b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,134 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Coffee.UIExtensions
{
internal static class UIParticleUpdater
{
private static readonly List<UIParticle> s_ActiveParticles = new List<UIParticle>();
private static readonly List<UIParticleAttractor> s_ActiveAttractors = new List<UIParticleAttractor>();
private static readonly HashSet<int> s_UpdatedGroupIds = new HashSet<int>();
private static int s_FrameCount;
public static int uiParticleCount
{
get { return s_ActiveParticles.Count; }
}
public static void Register(UIParticle particle)
{
if (!particle) return;
s_ActiveParticles.Add(particle);
}
public static void Unregister(UIParticle particle)
{
if (!particle) return;
s_ActiveParticles.Remove(particle);
}
public static void Register(UIParticleAttractor attractor)
{
if (!attractor) return;
s_ActiveAttractors.Add(attractor);
}
public static void Unregister(UIParticleAttractor attractor)
{
if (!attractor) return;
s_ActiveAttractors.Remove(attractor);
}
#if UNITY_EDITOR
[InitializeOnLoadMethod]
#endif
[RuntimeInitializeOnLoadMethod]
private static void InitializeOnLoad()
{
Canvas.willRenderCanvases -= Refresh;
Canvas.willRenderCanvases += Refresh;
}
private static void Refresh()
{
// Do not allow it to be called in the same frame.
if (s_FrameCount == Time.frameCount) return;
s_FrameCount = Time.frameCount;
// Simulate -> Primary
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (!uip || !uip.canvas || !uip.isPrimary || s_UpdatedGroupIds.Contains(uip.groupId)) continue;
s_UpdatedGroupIds.Add(uip.groupId);
uip.UpdateTransformScale();
uip.UpdateRenderers();
}
// Simulate -> Others
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (!uip || !uip.canvas) continue;
uip.UpdateTransformScale();
if (!uip.useMeshSharing)
{
uip.UpdateRenderers();
}
else if (!s_UpdatedGroupIds.Contains(uip.groupId))
{
s_UpdatedGroupIds.Add(uip.groupId);
uip.UpdateRenderers();
}
}
s_UpdatedGroupIds.Clear();
// Attract
for (var i = 0; i < s_ActiveAttractors.Count; i++)
{
s_ActiveAttractors[i].Attract();
}
// UpdateParticleCount.
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (!uip || !uip.canvas) continue;
uip.UpdateParticleCount();
}
}
public static void GetGroupedRenderers(int groupId, int index, List<UIParticleRenderer> results)
{
results.Clear();
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (uip.useMeshSharing && uip.groupId == groupId)
{
results.Add(uip.GetRenderer(index));
}
}
}
internal static UIParticle GetPrimary(int groupId)
{
UIParticle primary = null;
for (var i = 0; i < s_ActiveParticles.Count; i++)
{
var uip = s_ActiveParticles[i];
if (!uip.useMeshSharing || uip.groupId != groupId) continue;
if (uip.isPrimary) return uip;
if (!primary && uip.canSimulate) primary = uip;
}
return primary;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a0e708dc2e3034ba9a5c51db4252c7e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -100
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Coffee.UIParticleExtensions
{
public static class Vector3Extensions
{
public static Vector3 Inverse(this Vector3 self)
{
self.x = Mathf.Approximately(self.x, 0) ? 1 : 1 / self.x;
self.y = Mathf.Approximately(self.y, 0) ? 1 : 1 / self.y;
self.z = Mathf.Approximately(self.z, 0) ? 1 : 1 / self.z;
return self;
}
public static Vector3 GetScaled(this Vector3 self, Vector3 other1)
{
self.Scale(other1);
return self;
}
public static Vector3 GetScaled(this Vector3 self, Vector3 other1, Vector3 other2)
{
self.Scale(other1);
self.Scale(other2);
return self;
}
public static Vector3 GetScaled(this Vector3 self, Vector3 other1, Vector3 other2, Vector3 other3)
{
self.Scale(other1);
self.Scale(other2);
self.Scale(other3);
return self;
}
public static bool IsVisible(this Vector3 self)
{
return 0 < Mathf.Abs(self.x * self.y * self.z);
}
}
internal static class SpriteExtensions
{
#if UNITY_EDITOR
private static readonly Type s_SpriteEditorExtensionType =
Type.GetType("UnityEditor.Experimental.U2D.SpriteEditorExtension, UnityEditor")
?? Type.GetType("UnityEditor.U2D.SpriteEditorExtension, UnityEditor");
private static readonly MethodInfo s_GetActiveAtlasTextureMethodInfo = s_SpriteEditorExtensionType
.GetMethod("GetActiveAtlasTexture", BindingFlags.Static | BindingFlags.NonPublic);
public static Texture2D GetActualTexture(this Sprite self)
{
if (!self) return null;
if (Application.isPlaying) return self.texture;
var ret = s_GetActiveAtlasTextureMethodInfo.Invoke(null, new object[] { self }) as Texture2D;
return ret
? ret
: self.texture;
}
#else
internal static Texture2D GetActualTexture(this Sprite self)
{
return self ? self.texture : null;
}
#endif
}
public static class ParticleSystemExtensions
{
private static ParticleSystem.Particle[] s_TmpParticles = new ParticleSystem.Particle[2048];
public static ParticleSystem.Particle[] GetParticleArray(int size)
{
if (s_TmpParticles.Length < size)
{
while (s_TmpParticles.Length < size)
{
size = Mathf.NextPowerOfTwo(size);
}
s_TmpParticles = new ParticleSystem.Particle[size];
}
return s_TmpParticles;
}
public static bool CanBakeMesh(this ParticleSystemRenderer self)
{
// #69: Editor crashes when mesh is set to null when `ParticleSystem.RenderMode = Mesh`
if (self.renderMode == ParticleSystemRenderMode.Mesh && self.mesh == null) return false;
// #61: When `ParticleSystem.RenderMode = None`, an error occurs
if (self.renderMode == ParticleSystemRenderMode.None) return false;
return true;
}
public static ParticleSystemSimulationSpace GetActualSimulationSpace(this ParticleSystem self)
{
var main = self.main;
var space = main.simulationSpace;
if (space == ParticleSystemSimulationSpace.Custom && !main.customSimulationSpace)
{
space = ParticleSystemSimulationSpace.Local;
}
return space;
}
public static bool IsLocalSpace(this ParticleSystem self)
{
return GetActualSimulationSpace(self) == ParticleSystemSimulationSpace.Local;
}
public static bool IsWorldSpace(this ParticleSystem self)
{
return GetActualSimulationSpace(self) == ParticleSystemSimulationSpace.World;
}
public static void SortForRendering(this List<ParticleSystem> self, Transform transform, bool sortByMaterial)
{
self.Sort((a, b) =>
{
var aRenderer = a.GetComponent<ParticleSystemRenderer>();
var bRenderer = b.GetComponent<ParticleSystemRenderer>();
// Render queue: ascending
var aMat = aRenderer.sharedMaterial ? aRenderer.sharedMaterial : aRenderer.trailMaterial;
var bMat = bRenderer.sharedMaterial ? bRenderer.sharedMaterial : bRenderer.trailMaterial;
if (!aMat && !bMat) return 0;
if (!aMat) return -1;
if (!bMat) return 1;
if (sortByMaterial)
{
return aMat.GetInstanceID() - bMat.GetInstanceID();
}
if (aMat.renderQueue != bMat.renderQueue)
{
return aMat.renderQueue - bMat.renderQueue;
}
// Sorting layer: ascending
if (aRenderer.sortingLayerID != bRenderer.sortingLayerID)
{
return SortingLayer.GetLayerValueFromID(aRenderer.sortingLayerID) -
SortingLayer.GetLayerValueFromID(bRenderer.sortingLayerID);
}
// Sorting order: ascending
if (aRenderer.sortingOrder != bRenderer.sortingOrder)
{
return aRenderer.sortingOrder - bRenderer.sortingOrder;
}
// Z position & sortingFudge: descending
var aTransform = a.transform;
var bTransform = b.transform;
var aPos = transform.InverseTransformPoint(aTransform.position).z + aRenderer.sortingFudge;
var bPos = transform.InverseTransformPoint(bTransform.position).z + bRenderer.sortingFudge;
if (!Mathf.Approximately(aPos, bPos))
{
return (int)Mathf.Sign(bPos - aPos);
}
return (int)Mathf.Sign(GetIndex(self, a) - GetIndex(self, b));
});
}
private static int GetIndex(IList<ParticleSystem> list, Object ps)
{
for (var i = 0; i < list.Count; i++)
{
if (list[i].GetInstanceID() == ps.GetInstanceID())
{
return i;
}
}
return 0;
}
public static Texture2D GetTextureForSprite(this ParticleSystem self)
{
if (!self) return null;
// Get sprite's texture.
var tsaModule = self.textureSheetAnimation;
if (!tsaModule.enabled || tsaModule.mode != ParticleSystemAnimationMode.Sprites) return null;
for (var i = 0; i < tsaModule.spriteCount; i++)
{
var sprite = tsaModule.GetSprite(i);
if (!sprite) continue;
return sprite.GetActualTexture();
}
return null;
}
public static void Exec(this List<ParticleSystem> self, Action<ParticleSystem> action)
{
self.RemoveAll(p => !p);
self.ForEach(action);
}
}
internal static class Misc
{
public static void Destroy(Object obj)
{
if (!obj) return;
#if UNITY_EDITOR
if (!Application.isPlaying)
{
Object.DestroyImmediate(obj);
}
else
#endif
{
Object.Destroy(obj);
}
}
public static void DestroyImmediate(Object obj)
{
if (!obj) return;
#if UNITY_EDITOR
if (Application.isEditor)
{
Object.DestroyImmediate(obj);
}
else
#endif
{
Object.Destroy(obj);
}
}
#if !UNITY_2021_2_OR_NEWER || UNITY_2020_3_45 || UNITY_2020_3_46 || UNITY_2020_3_47 || UNITY_2020_3_48
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;
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d188d31b140094ebc84a9caafbc7ac71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b127af87b412b46b8bb96174d10b16de
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,85 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIAdditive
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _Stencil: 0
- _StencilComp: 8
- _StencilOp: 0
- _StencilReadMask: 255
- _StencilWriteMask: 255
- _UVSec: 0
- _UseUIAlphaClip: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9944483a3e009401ba5dcc42f14d5c63
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,117 @@
Shader "UI/Additive"
{
Properties
{
_MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Fog { Mode Off }
Blend One One
ColorMask [_ColorMask]
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_CLIP_RECT
#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = v.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
OUT.color = v.color * _Color;
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
color.rgb *= color.a;
return color;
}
ENDCG
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ecfa8f5732b504ef98fba10aa18d0326
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
{
"name": "com.coffee.ui-particle",
"displayName": "UI Particle",
"description": "This plugin provide a component to render particle effect for uGUI.\nThe particle rendering is maskable and sortable, without Camera, RenderTexture or Canvas.",
"version": "4.2.1",
"unity": "2018.2",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/mob-sakai/ParticleEffectForUGUI.git"
},
"author": "mob-sakai <sakai861104@gmail.com> (https://github.com/mob-sakai)",
"dependencies": {},
"keywords": [
"ui",
"particle"
],
"samples": [
{
"displayName": "Demo",
"description": "UI Particle Demo",
"path": "Samples~/Demo"
},
{
"displayName": "Cartoon FX & War FX Demo",
"description": "Cartoon FX & War FX Demo",
"path": "Samples~/Cartoon FX & War FX Demo"
},
{
"displayName": "Performance Demo",
"description": "Performance Demo",
"path": "Samples~/Performance Demo"
}
]
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 823dc693d087a4b559c7e1547274cc7d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: