using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using UnityEditor.Experimental.SceneManagement; using BF; using UnityEditor.SceneManagement; namespace BFEditor { [InitializeOnLoad] [CustomEditor(typeof(EffectHelper))] public class EffectHelperInspector : Editor { EffectHelper helper; private bool playing; private float runningTime; private float speed = 1.0f; private const float millisecond = 1 / 60f; private float maxDuration = 30f; private bool isPause = false; private bool isStop = true; private ParticleSystem rootParticle; static EffectHelperInspector() { PrefabStage.prefabSaving += OnPrefabSaved; } public static void OnPrefabSaved(GameObject go) { var effectHelper = go.GetComponent(); if (effectHelper != null) { updateEffectHelper(go, effectHelper); } } private static void updateEffectHelper(GameObject go, EffectHelper effectHelper) { Transform t = effectHelper.transform; float dur = getParticleSystemLength(t); bool drity = false; if (effectHelper.EffectDuration != dur) { effectHelper.EffectDuration = dur; EditorUtility.SetDirty(effectHelper); drity = true; } var animators = t.GetComponentsInChildren(true); int animatorCount = animators.Length; if (effectHelper.AnimatorCount != animatorCount) { effectHelper.AnimatorCount = animatorCount; EditorUtility.SetDirty(effectHelper); drity = true; } var trailRenderers = t.GetComponentsInChildren(true); int trailRendererCount = trailRenderers.Length; if (effectHelper.TrailRendererCount != trailRendererCount) { effectHelper.TrailRendererCount = trailRendererCount; EditorUtility.SetDirty(effectHelper); drity = true; } ParticleSystem rootP = t.GetComponentInChildren(true); if (rootP != null && effectHelper.RootParticle != rootP) { effectHelper.RootParticle = rootP; EditorUtility.SetDirty(effectHelper); drity = true; } if (drity) { var prefabStage = PrefabStageUtility.GetPrefabStage(go); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } } void OnEnable() { EditorApplication.update += inspectorUpdate; helper = target as EffectHelper; } void OnDisable() { EditorApplication.update -= inspectorUpdate; } public override void OnInspectorGUI() { updateEffectHelper(helper.gameObject, helper); Transform t = helper.gameObject.transform; ParticleSystem rootP = t.GetComponentInChildren(true); if (!ReferenceEquals(rootP, helper.RootParticle)) { helper.RootParticle = rootP; } this.rootParticle = helper.RootParticle; maxDuration = getParticleSystemLength(t); EditorGUILayout.BeginHorizontal(); if (isStop) { if (GUILayout.Button("Play")) { play(); } } else { if (isPause) { if (GUILayout.Button("Continue")) { continuePlay(); } } else { if (GUILayout.Button("Pause")) { pause(); } } } if (GUILayout.Button("Stop")) { stop(); } EditorGUILayout.EndHorizontal(); speed = EditorGUILayout.Slider("Speed:", speed, 1f, 0f); showParticleInfo(); manualUpdate(); } private void showParticleInfo() { GUILayout.Space(10); GUILayout.BeginHorizontal(); GUILayout.Label("主粒子:", EditorStyles.label); EditorGUI.BeginDisabledGroup(true); if(helper.RootParticle == null) { GameObject go = (GameObject)EditorGUILayout.ObjectField("", null, typeof(GameObject), true, GUILayout.Width(140)); } else { GameObject go = (GameObject)EditorGUILayout.ObjectField("", helper.RootParticle.gameObject, typeof(GameObject), true, GUILayout.Width(140)); } EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("粒子总持续时间: " + System.Convert.ToString(helper.EffectDuration) + "s", EditorStyles.label); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Animator数量: " + System.Convert.ToString(helper.AnimatorCount), EditorStyles.label); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("拖尾数量: " + System.Convert.ToString(helper.TrailRendererCount), EditorStyles.label); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); var toggleResult = EditorGUILayout.Toggle("使用角度来翻转特效: ", helper.EulerAnglesFlip); if (toggleResult != helper.EulerAnglesFlip) { Undo.RecordObject(helper, helper.name + "Toggle EulerAnglesFlip"); helper.EulerAnglesFlip = toggleResult; EditorUtility.SetDirty(helper); } GUILayout.EndHorizontal(); } private void manualUpdate() { if (this.rootParticle && !playing) { this.rootParticle.Simulate(millisecond * speed, true, false); SceneView.RepaintAll(); } } private void play() { if (Application.isPlaying || this.rootParticle == null) { return; } playing = true; isPause = false; isStop = false; this.rootParticle.Simulate(0, true, true); } private void continuePlay() { if (Application.isPlaying || this.rootParticle == null) { return; } playing = true; isPause = false; isStop = false; } private void stop() { if (Application.isPlaying || this.rootParticle == null) { return; } playing = false; isPause = false; isStop = true; runningTime = 0; this.rootParticle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); } private void pause() { if (Application.isPlaying || this.rootParticle == null) { return; } playing = false; isPause = true; this.rootParticle.Stop(true); } private void inspectorUpdate() { if (!Application.isPlaying && playing) { runningTime = runningTime + millisecond * speed; update(); } } private void update() { if (Application.isPlaying || this.rootParticle == null) { return; } if (maxDuration > 0 && runningTime >= maxDuration) { this.stop(); return; } this.rootParticle.Simulate(millisecond * speed, true, false, true); SceneView.RepaintAll(); Repaint(); } private static float getParticleSystemLength(Transform transform) { ParticleSystem[] particleSystems = transform.GetComponentsInChildren(true); float maxDuration = -1; foreach (ParticleSystem ps in particleSystems) { if (ps.emission.enabled) { if (ps.main.loop) { continue; } float dunration = ps.main.duration; if (ps.main.startDelay.mode == ParticleSystemCurveMode.TwoConstants) { dunration += ps.main.startDelay.constantMax; } else { dunration += ps.main.startDelay.constant; } if (dunration > maxDuration) { maxDuration = dunration; } } } return maxDuration; } } }