在unity官方论坛看到的一个解决方案,可以将Particle直接转换成CanvasRenderer元素显示。
新建一个UIParticleSystem.cs脚本,将以下代码复制进去:
using UnityEngine; using UnityEngine.UI; using System.Collections.Generic;[ExecuteInEditMode] [RequireComponent(typeof(CanvasRenderer))] [RequireComponent(typeof(ParticleSystem))] public class UIParticleSystem : MaskableGraphic {public Texture particleTexture;public Sprite particleSprite;private Transform _transform;private ParticleSystem _particleSystem;private ParticleSystem.Particle[] _particles;private UIVertex[] _quad = new UIVertex[4];private Vector4 _uv = Vector4.zero;private ParticleSystem.TextureSheetAnimationModule _textureSheetAnimation;private int _textureSheetAnimationFrames;private Vector2 _textureSheedAnimationFrameSize;public override Texture mainTexture{get{if (particleTexture){return particleTexture;}if (particleSprite){return particleSprite.texture;}return null;}}protected bool Initialize(){// initialize membersif (_transform == null){_transform = transform;}// prepare particle systemParticleSystemRenderer renderer = GetComponent<ParticleSystemRenderer>();bool setParticleSystemMaterial = false;if (_particleSystem == null){_particleSystem = GetComponent<ParticleSystem>();if (_particleSystem == null){return false;}// get current particle textureif (renderer == null){renderer = _particleSystem.gameObject.AddComponent<ParticleSystemRenderer>();}Material currentMaterial = renderer.sharedMaterial;if (currentMaterial && currentMaterial.HasProperty("_MainTex")){particleTexture = currentMaterial.mainTexture;}// automatically set scaling_particleSystem.scalingMode = ParticleSystemScalingMode.Local;_particles = null;setParticleSystemMaterial = true;}else{if (Application.isPlaying){setParticleSystemMaterial = (renderer.material == null);} #if UNITY_EDITORelse{setParticleSystemMaterial = (renderer.sharedMaterial == null);} #endif}// automatically set material to UI/Particles/Hidden shader, and get previous textureif (setParticleSystemMaterial){Material material = new Material(Shader.Find("UI/Particles/Hidden"));if (Application.isPlaying){renderer.material = material;} #if UNITY_EDITORelse{material.hideFlags = HideFlags.DontSave;renderer.sharedMaterial = material;} #endif}// prepare particles arrayif (_particles == null){_particles = new ParticleSystem.Particle[_particleSystem.maxParticles];}// prepare uvsif (particleTexture){_uv = new Vector4(0, 0, 1, 1);}else if (particleSprite){_uv = UnityEngine.Sprites.DataUtility.GetOuterUV(particleSprite);}// prepare texture sheet animation_textureSheetAnimation = _particleSystem.textureSheetAnimation;_textureSheetAnimationFrames = 0;_textureSheedAnimationFrameSize = Vector2.zero;if (_textureSheetAnimation.enabled){_textureSheetAnimationFrames = _textureSheetAnimation.numTilesX * _textureSheetAnimation.numTilesY;_textureSheedAnimationFrameSize = new Vector2(1f / _textureSheetAnimation.numTilesX, 1f / _textureSheetAnimation.numTilesY);}return true;}protected override void Awake(){base.Awake();if (!Initialize()){enabled = false;}}protected override void OnPopulateMesh(VertexHelper vh){ #if UNITY_EDITORif (!Application.isPlaying){if (!Initialize()){return;}} #endif// prepare verticesvh.Clear();if (!gameObject.activeInHierarchy){return;}// iterate through current particlesint count = _particleSystem.GetParticles(_particles);for (int i = 0; i < count; ++i){ParticleSystem.Particle particle = _particles[i];// get particle propertiesVector2 position = (_particleSystem.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));float rotation = -particle.rotation * Mathf.Deg2Rad;float rotation90 = rotation + Mathf.PI / 2;Color32 color = particle.GetCurrentColor(_particleSystem);float size = particle.GetCurrentSize(_particleSystem) * 0.5f;// apply scaleif (_particleSystem.scalingMode == ParticleSystemScalingMode.Shape){position /= canvas.scaleFactor;}// apply texture sheet animationVector4 particleUV = _uv;if (_textureSheetAnimation.enabled){float frameProgress = 1 - (particle.lifetime / particle.startLifetime);// float frameProgress = textureSheetAnimation.frameOverTime.curveMin.Evaluate(1 - (particle.lifetime / particle.startLifetime)); // TODO - once Unity allows MinMaxCurve readingframeProgress = Mathf.Repeat(frameProgress * _textureSheetAnimation.cycleCount, 1);int frame = 0;switch (_textureSheetAnimation.animation){case ParticleSystemAnimationType.WholeSheet:frame = Mathf.FloorToInt(frameProgress * _textureSheetAnimationFrames);break;case ParticleSystemAnimationType.SingleRow:frame = Mathf.FloorToInt(frameProgress * _textureSheetAnimation.numTilesX);int row = _textureSheetAnimation.rowIndex;// if (textureSheetAnimation.useRandomRow) { // FIXME - is this handled internally by rowIndex?// row = Random.Range(0, textureSheetAnimation.numTilesY, using: particle.randomSeed);// }frame += row * _textureSheetAnimation.numTilesX;break;}frame %= _textureSheetAnimationFrames;particleUV.x = (frame % _textureSheetAnimation.numTilesX) * _textureSheedAnimationFrameSize.x;particleUV.y = Mathf.FloorToInt(frame / _textureSheetAnimation.numTilesX) * _textureSheedAnimationFrameSize.y;particleUV.z = particleUV.x + _textureSheedAnimationFrameSize.x;particleUV.w = particleUV.y + _textureSheedAnimationFrameSize.y;}_quad[0] = UIVertex.simpleVert;_quad[0].color = color;_quad[0].uv0 = new Vector2(particleUV.x, particleUV.y);_quad[1] = UIVertex.simpleVert;_quad[1].color = color;_quad[1].uv0 = new Vector2(particleUV.x, particleUV.w);_quad[2] = UIVertex.simpleVert;_quad[2].color = color;_quad[2].uv0 = new Vector2(particleUV.z, particleUV.w);_quad[3] = UIVertex.simpleVert;_quad[3].color = color;_quad[3].uv0 = new Vector2(particleUV.z, particleUV.y);if (rotation == 0){// no rotationVector2 corner1 = new Vector2(position.x - size, position.y - size);Vector2 corner2 = new Vector2(position.x + size, position.y + size);_quad[0].position = new Vector2(corner1.x, corner1.y);_quad[1].position = new Vector2(corner1.x, corner2.y);_quad[2].position = new Vector2(corner2.x, corner2.y);_quad[3].position = new Vector2(corner2.x, corner1.y);}else{// apply rotationVector2 right = new Vector2(Mathf.Cos(rotation), Mathf.Sin(rotation)) * size;Vector2 up = new Vector2(Mathf.Cos(rotation90), Mathf.Sin(rotation90)) * size;_quad[0].position = position - right - up;_quad[1].position = position - right + up;_quad[2].position = position + right + up;_quad[3].position = position + right - up;}vh.AddUIVertexQuad(_quad);}}void Update(){if (Application.isPlaying){// unscaled animation within UI_particleSystem.Simulate(Time.unscaledDeltaTime, false, false);SetAllDirty();}}#if UNITY_EDITORvoid LateUpdate(){if (!Application.isPlaying){SetAllDirty();}} #endif}
脚本依赖ParticleSystem控件,只能挂载在Paricle物体上。新建一个ParticleSystem将脚本拖上去就能用了!
https://blog.csdn.net/dark00800/article/details/73729947