using System; using System.Collections.Generic; using UnityEngine; [ExecuteInEditMode] public class ParticleUVAnimation : MonoBehaviour { public ParticleSystem particle; private ParticleSystemRenderer particleRender; private MaterialPropertyBlock materialProperty; private Action animFunc; [Header("[textST.xy : tile, textST.zw : offset]")] public Vector4 texST; public bool running = false; public float fps; private float fpsStep; private Func calcuateTime; private bool init = false; private int frameCount; private int frameIndex; private int tilesX; private float wStart; void Init() { if (particle == null) particle = GetComponent(); particleRender = GetComponent(); materialProperty = new MaterialPropertyBlock(); particleRender.GetPropertyBlock(materialProperty); var sheetAnim = particle.textureSheetAnimation; if (sheetAnim.animation == ParticleSystemAnimationType.SingleRow) animFunc = SingleRowUpdate; else animFunc = WholeSheetUpdate; switch (sheetAnim.timeMode) { case ParticleSystemAnimationTimeMode.FPS: fps = sheetAnim.fps; fpsStep = 1.0f / fps; break; case ParticleSystemAnimationTimeMode.Lifetime: //临时写一下 fps = sheetAnim.fps; fpsStep = 1.0f / fps; break; case ParticleSystemAnimationTimeMode.Speed: fps = sheetAnim.fps; fpsStep = 1.0f / fps; break; } frameCount = sheetAnim.numTilesX * sheetAnim.numTilesY; frameIndex = 0; tilesX = sheetAnim.numTilesX; texST.x = 1.0f / sheetAnim.numTilesX; texST.y = 1.0f / sheetAnim.numTilesY; texST.z = 0; texST.w = wStart = 1 - texST.y; materialProperty.SetVector("_MainTex_ST", texST); particleRender.SetPropertyBlock(materialProperty); lastTime = 0f; init = true; } public void Play() { running = true; //lastTime = Time.time; } void Awake() { Init(); } void Update() { if (!running) return; if (!init) Init(); animFunc(); } private void WholeSheetUpdate() { CalculateOffset(); materialProperty.SetVector("_MainTex_ST", texST); particleRender.SetPropertyBlock(materialProperty); } float lastTime; private void SingleRowUpdate() { //texST.z = CalculateXOffset(texST.z); } private void CalculateOffset() { if (Time.time > lastTime) { if (lastTime == 0) lastTime = Time.time + fpsStep; else lastTime += fpsStep; ++frameIndex; if (frameIndex >= frameCount) frameIndex -= frameCount; texST.z = (frameIndex % tilesX) * texST.x; texST.w = wStart - (frameIndex / tilesX) * texST.y; } } }