用于统计粒子特效信息,比如粒子个数、三角面数
 
一般粒子需要统计的信息有
| 1
2
3
4
5
 | public int triangles;
public bool prewarm = false;
public int distortion;
public int particleCount;
public int materialCount;
 | 
 
粒子中可能包含一些模型,所以先要获取所有的 MeshFilter, MeshRenderer, SkinnedMeshRenderer,从里面得到 mesh 和 material。然后得到所有的 ParticleSystem ,以及它的 Renderer 模块 ParticleSystemRenderer,从中获取剩余的 sharedMaterials。最后用 CurveUtil 计算出 ParticleSystem 的 particleCount 和剩余的 trianglesCount。一般 mesh 的 triangleCount 计算方法为
| 1
 | triangles += mesh.triangles.Length / 3;
 | 
 
注意判断 renderer 和 emission 模块是否开启,否则粒子信息无效。
|   1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
 | using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class CurveUtil
{
    public static int GetForecastParticleCount(this ParticleSystem particleSystem)
    {
        float rateOverTime = particleSystem.GetRateOverTimeMax();
        return Mathf.CeilToInt(Mathf.Min(particleSystem.main.startLifetime.GetMaxVal() * rateOverTime, particleSystem.main.maxParticles));
    }
    public static int GetForecastTrianglesCount(this ParticleSystem particleSystem)
    {
        int count = particleSystem.GetForecastParticleCount();
        ParticleSystemRenderer renderer = particleSystem.GetComponent<ParticleSystemRenderer>();
        if(renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.mesh != null)
        {
            return count * renderer.mesh.triangles.Length / 3;
        }
        else
        {
            return count *  2;
        }
    }
    public static ParticleSystemRenderMode GetRenderMode(this ParticleSystem particleSystem)
    {
        ParticleSystemRenderer renderer = particleSystem.GetComponent<ParticleSystemRenderer>();
        return renderer.renderMode;
    }
    public static string GetMeshName(this ParticleSystem particleSystem)
    {
        ParticleSystemRenderer renderer = particleSystem.GetComponent<ParticleSystemRenderer>();
        if (renderer.renderMode == ParticleSystemRenderMode.Mesh)
        {
#if UNITY_EDITOR
            return UnityEditor.AssetDatabase.GetAssetPath(renderer.mesh);
#endif
            return renderer.mesh.name;
        }
        else
        {
            return renderer.renderMode.ToString();
        }
    }
    public static float GetRateOverTimeMax(this ParticleSystem particleSystem)
    {
        float rateOverTime = particleSystem.emission.rateOverTime.GetMaxVal();
        return Mathf.Max(rateOverTime, particleSystem.GetBurstMax());
    }
    public static int GetBurstMax(this ParticleSystem particleSystem)
    {
        int val = 0;
        ParticleSystem.Burst[]  bursts = new ParticleSystem.Burst[particleSystem.emission.burstCount];
        particleSystem.emission.GetBursts(bursts);
        foreach (ParticleSystem.Burst burst in bursts)
        {
            val = Mathf.Max(val, burst.maxCount);
            val = Mathf.Max(val, burst.minCount);
            if(burst.cycleCount == 0 && burst.repeatInterval > 0)
            {
                val = Mathf.Max(val, Mathf.CeilToInt(1f / burst.repeatInterval) * val);
            }
        }
        return val;
    }
    public static float GetMaxVal(this ParticleSystem.MinMaxCurve minMaxCurve)
    {
        switch (minMaxCurve.mode)
        {
            case ParticleSystemCurveMode.TwoConstants:
                return Mathf.Max(minMaxCurve.constantMax, minMaxCurve.constantMin);
            case ParticleSystemCurveMode.Curve:
                return minMaxCurve.curve.GetMaxVal();
            case ParticleSystemCurveMode.TwoCurves:
                return Mathf.Max( minMaxCurve.curveMax.GetMaxVal(), minMaxCurve.curveMax.GetMaxVal());
            case ParticleSystemCurveMode.Constant:
            default:
                return minMaxCurve.constant;
        }
    }
    public static float GetMaxVal(this AnimationCurve animationCurve)
    {
        float maxVal = int.MinValue;
        foreach (Keyframe keyframe in animationCurve.keys)
        {
            if (maxVal < keyframe.value)
            {
                maxVal = keyframe.value;
            }
        }
        return maxVal;
    }
    public static float GetMinVal(this AnimationCurve animationCurve)
    {
        float minVal = int.MaxValue;
        foreach (Keyframe keyframe in animationCurve.keys)
        {
            if (minVal > keyframe.value)
            {
                minVal = keyframe.value;
            }
        }
        return minVal;
    }
}
 |