mcpField
P
particle-systems

particle-systems

github.com/pluginagentmarketplace创意与媒体45177 次安装42 周前更新
代码仓库

关于 particle-systems

面向游戏与视觉效果开发的粒子系统技能,提供效果设计、Unity 实现和性能优化参考。内容还涵盖 GPU 粒子、效果池及 Unity、Unreal 和 Godot 的工具。

主要功能

  1. 01粒子生命周期与发射设计
  2. 02爆炸等常见效果配方
  3. 03Unity 粒子控制器示例
  4. 04GPU 粒子与计算着色器
  5. 05性能预算与效果池
  6. 06Unity、Unreal、Godot 工具概览

适用场景

  1. 01为游戏制作爆炸和烟雾效果
  2. 02在 Unity 中配置粒子效果
  3. 03使用 GPU 粒子实现效果
  4. 04优化粒子数量并复用效果实例

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/pluginagentmarketplace/custom-plugin-game-developer --skill particle-systems

安装后在 Claude Code 中输入/particle-systems确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
particles_config.yaml
references/
PARTICLES_GUIDE.md
scripts/
particle_designer.py

详细介绍

粒子系统

粒子系统架构

┌─────────────────────────────────────────────────────────────┐
│                    PARTICLE LIFECYCLE                        │
├─────────────────────────────────────────────────────────────┤
│  EMISSION                                                    │
│  ├─ Spawn Rate (particles/second)                           │
│  ├─ Burst (instant spawn count)                             │
│  └─ Shape (point, sphere, cone, mesh)                       │
│                    ↓                                         │
│  SIMULATION                                                  │
│  ├─ Velocity (initial + over lifetime)                      │
│  ├─ Forces (gravity, wind, turbulence)                      │
│  ├─ Collision (world, depth buffer)                         │
│  └─ Noise (procedural movement)                             │
│                    ↓                                         │
│  RENDERING                                                   │
│  ├─ Billboard (camera-facing quads)                         │
│  ├─ Mesh (3D geometry per particle)                         │
│  ├─ Trail (ribbon following path)                           │
│  └─ GPU Instancing (batched draw)                           │
│                    ↓                                         │
│  DEATH                                                       │
│  └─ Lifetime expired → recycle or destroy                   │
└─────────────────────────────────────────────────────────────┘

常见效果配方

EXPLOSION EFFECT:
┌─────────────────────────────────────────────────────────────┐
│  LAYERS:                                                     │
│  1. Flash (instant, bright, 0.1s)                           │
│  2. Core fireball (expanding sphere, 0.3s)                  │
│  3. Debris (physics-enabled chunks, 1-2s)                   │
│  4. Smoke (slow rising, fade out, 2-3s)                     │
│  5. Sparks (fast, gravity-affected, 0.5-1s)                 │
│  6. Shockwave (expanding ring, 0.2s)                        │
│                                                              │
│  SETTINGS:                                                   │
│  • Emission: Burst only (no rate)                           │
│  • Start speed: 5-20 (varies by layer)                      │
│  • Gravity: -9.8 for debris, 0 for smoke                    │
│  • Color: Orange→Red→Black over lifetime                    │
│  • Size: Start large, shrink (fireball) or grow (smoke)     │
└─────────────────────────────────────────────────────────────┘

FIRE EFFECT:
┌─────────────────────────────────────────────────────────────┐
│  LAYERS:                                                     │
│  1. Core flame (upward, orange-yellow, looping)             │
│  2. Ember particles (small, floating up)                    │
│  3. Smoke (dark, rises above flame)                         │
│  4. Light source (flickering point light)                   │
│                                                              │
│  SETTINGS:                                                   │
│  • Emission: Continuous (50-100/sec)                        │
│  • Velocity: Upward (2-5 units/sec)                         │
│  • Noise: Turbulence for natural movement                   │
│  • Color: White→Yellow→Orange→Red over lifetime             │
│  • Size: Start small, grow, then shrink                     │
│  • Blend: Additive for glow effect                          │
└─────────────────────────────────────────────────────────────┘

MAGIC SPELL EFFECT:
┌─────────────────────────────────────────────────────────────┐
│  LAYERS:                                                     │
│  1. Core glow (pulsing, bright center)                      │
│  2. Orbiting particles (circle around core)                 │
│  3. Trail particles (follow movement path)                  │
│  4. Impact burst (on hit/destination)                       │
│  5. Residual sparkles (lingering after effect)              │
│                                                              │
│  SETTINGS:                                                   │
│  • Emission: Rate + burst on cast/impact                    │
│  • Velocity: Custom curves for orbiting                     │
│  • Trails: Enable for mystical streaks                      │
│  • Color: Themed to element (blue=ice, red=fire)            │
│  • Blend: Additive for ethereal glow                        │
└─────────────────────────────────────────────────────────────┘

Unity 粒子系统设置

// ✅ Production-Ready: Particle Effect Controller
public class ParticleEffectController : MonoBehaviour
{
    [Header("Effect Settings")]
    [SerializeField] private ParticleSystem mainEffect;
    [SerializeField] private ParticleSystem[] subEffects;
    [SerializeField] private AudioSource audioSource;
    [SerializeField] private Light effectLight;

    [Header("Pooling")]
    [SerializeField] private bool usePooling = true;
    [SerializeField] private float autoReturnDelay = 3f;

    private ParticleSystem.MainModule _mainModule;
    private float _originalLightIntensity;

    public event Action OnEffectComplete;

    private void Awake()
    {
        _mainModule = mainEffect.main;
        if (effectLight != null)
            _originalLightIntensity = effectLight.intensity;
    }

    public void Play(Vector3 position, Quaternion rotation)
    {
        transform.SetPositionAndRotation(position, rotation);

        // Play all particle systems
        mainEffect.Play();
        foreach (var effect in subEffects)
        {
            effect.Play();
        }

        // Play audio
        if (audioSource != null)
            audioSource.Play();

        // Animate light
        if (effectLight != null)
            StartCoroutine(AnimateLight());

        // Auto-return to pool
        if (usePooling)
            StartCoroutine(ReturnToPoolAfterDelay());
    }

    public void Stop()
    {
        mainEffect.Stop(true, ParticleSystemStopBehavior.StopEmitting);
        foreach (var effect in subEffects)
        {
            effect.Stop(true, ParticleSystemStopBehavior.StopEmitting);
        }
    }

    private IEnumerator AnimateLight()
    {
        effectLight.intensity = _originalLightIntensity;
        effectLight.enabled = true;

        float duration = _mainModule.duration;
        float elapsed = 0f;

        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;
            float t = elapsed / duration;
            effectLight.intensity = Mathf.Lerp(_originalLightIntensity, 0f, t);
            yield return null;
        }

        effectLight.enabled = false;
    }

    private IEnumerator ReturnToPoolAfterDelay()
    {
        yield return new WaitForSeconds(autoReturnDelay);

        OnEffectComplete?.Invoke();

        // Reset for reuse
        Stop();
        if (effectLight != null)
        {
            effectLight.enabled = false;
            effectLight.intensity = _originalLightIntensity;
        }
    }

    public void SetColor(Color color)
    {
        var startColor = _mainModule.startColor;
        startColor.color = color;
        _mainModule.startColor = startColor;

        if (effectLight != null)
            effectLight.color = color;
    }

    public void SetScale(float scale)
    {
        transform.localScale = Vector3.one * scale;
    }
}

GPU 粒子(计算着色器)

// ✅ Production-Ready: GPU Particle Compute Shader
#pragma kernel UpdateParticles

struct Particle
{
    float3 position;
    float3 velocity;
    float4 color;
    float size;
    float lifetime;
    float maxLifetime;
};

RWStructuredBuffer<Particle> particles;
float deltaTime;
float3 gravity;
float3 windDirection;
float windStrength;
float turbulenceStrength;
float time;

float noise3D(float3 p)
{
    // Simple 3D noise for turbulence
    return frac(sin(dot(p, float3(12.9898, 78.233, 45.164))) * 43758.5453);
}

[numthreads(256, 1, 1)]
void UpdateParticles(uint3 id : SV_DispatchThreadID)
{
    Particle p = particles[id.x];

    if (p.lifetime <= 0)
        return;

    // Apply forces
    float3 acceleration = gravity;

    // Wind
    acceleration += windDirection * windStrength;

    // Turbulence
    float3 turbulence = float3(
        noise3D(p.position + time) - 0.5,
        noise3D(p.position + time + 100) - 0.5,
        noise3D(p.position + time + 200) - 0.5
    ) * turbulenceStrength;
    acceleration += turbulence;

    // Update velocity and position
    p.velocity += acceleration * deltaTime;
    p.position += p.velocity * deltaTime;

    // Update lifetime
    p.lifetime -= deltaTime;

    // Fade out
    float lifetimeRatio = p.lifetime / p.maxLifetime;
    p.color.a = lifetimeRatio;
    p.size *= (0.5 + 0.5 * lifetimeRatio);

    particles[id.x] = p;
}

性能优化

PARTICLE BUDGET GUIDELINES:
┌─────────────────────────────────────────────────────────────┐
│  PLATFORM      │ MAX PARTICLES │ MAX DRAW CALLS │ NOTES    │
├────────────────┼───────────────┼────────────────┼──────────┤
│  Mobile Low    │ 500           │ 5              │ Simple   │
│  Mobile High   │ 2,000         │ 10             │ Moderate │
│  Console       │ 50,000        │ 50             │ Complex  │
│  PC Low        │ 10,000        │ 20             │ Moderate │
│  PC High       │ 1,000,000+    │ 100+           │ GPU sim  │
│  VR            │ 5,000         │ 15             │ 90 FPS!  │
└────────────────┴───────────────┴────────────────┴──────────┘

OPTIMIZATION TECHNIQUES:
┌─────────────────────────────────────────────────────────────┐
│  REDUCE COUNT:                                               │
│  • LOD system (fewer particles at distance)                 │
│  • Cull off-screen emitters                                 │
│  • Limit max particles per system                           │
│                                                              │
│  REDUCE OVERDRAW:                                            │
│  • Use smaller particle sizes                               │
│  • Reduce transparency layers                               │
│  • Use cutout instead of transparent                        │
│                                                              │
│  BATCH DRAWS:                                                │
│  • Share materials between systems                          │
│  • Use texture atlases                                      │
│  • Enable GPU instancing                                    │
│                                                              │
│  GPU SIMULATION:                                             │
│  • Use compute shaders for >10K particles                   │
│  • Move physics to GPU                                      │
│  • VFX Graph (Unity) / Niagara (Unreal)                    │
└─────────────────────────────────────────────────────────────┘

效果池系统

// ✅ Production-Ready: VFX Pool Manager
public class VFXPoolManager : MonoBehaviour
{
    public static VFXPoolManager Instance { get; private set; }

    [System.Serializable]
    public class EffectPool
    {
        public string effectName;
        public ParticleEffectController prefab;
        public int initialSize = 5;
        public int maxSize = 20;
    }

    [SerializeField] private EffectPool[] effectPools;

    private Dictionary<string, Queue<ParticleEffectController>> _pools;
    private Dictionary<string, EffectPool> _poolConfigs;

    private void Awake()
    {
        Instance = this;
        InitializePools();
    }

    private void InitializePools()
    {
        _pools = new Dictionary<string, Queue<ParticleEffectController>>();
        _poolConfigs = new Dictionary<string, EffectPool>();

        foreach (var pool in effectPools)
        {
            _pools[pool.effectName] = new Queue<ParticleEffectController>();
            _poolConfigs[pool.effectName] = pool;

            // Pre-warm pool
            for (int i = 0; i < pool.initialSize; i++)
            {
                var effect = CreateEffect(pool);
                _pools[pool.effectName].Enqueue(effect);
            }
        }
    }

    private ParticleEffectController CreateEffect(EffectPool pool)
    {
        var effect = Instantiate(pool.prefab, transform);
        effect.gameObject.SetActive(false);
        effect.OnEffectComplete += () => ReturnToPool(pool.effectName, effect);
        return effect;
    }

    public ParticleEffectController SpawnEffect(
        string effectName,
        Vector3 position,
        Quaternion rotation)
    {
        if (!_pools.ContainsKey(effectName))
        {
            Debug.LogError($"Effect pool '{effectName}' not found!");
            return null;
        }

        var pool = _pools[effectName];
        ParticleEffectController effect;

        if (pool.Count > 0)
        {
            effect = pool.Dequeue();
        }
        else if (_poolConfigs[effectName].maxSize > pool.Count)
        {
            effect = CreateEffect(_poolConfigs[effectName]);
        }
        else
        {
            Debug.LogWarning($"Pool '{effectName}' exhausted!");
            return null;
        }

        effect.gameObject.SetActive(true);
        effect.Play(position, rotation);
        return effect;
    }

    private void ReturnToPool(string effectName, ParticleEffectController effect)
    {
        effect.gameObject.SetActive(false);
        _pools[effectName].Enqueue(effect);
    }
}

// Usage
public class WeaponController : MonoBehaviour
{
    public void OnHit(Vector3 hitPoint, Vector3 hitNormal)
    {
        VFXPoolManager.Instance.SpawnEffect(
            "ImpactSparks",
            hitPoint,
            Quaternion.LookRotation(hitNormal));
    }
}

🔧 故障排除

┌─────────────────────────────────────────────────────────────┐
│ PROBLEM: Particles popping in/out                           │
├─────────────────────────────────────────────────────────────┤
│ SOLUTIONS:                                                   │
│ → Add fade-in at birth (size/alpha over lifetime)           │
│ → Increase soft particle distance                           │
│ → Check culling settings                                    │
│ → Extend lifetime with fade-out                             │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ PROBLEM: Low frame rate with particles                      │
├─────────────────────────────────────────────────────────────┤
│ SOLUTIONS:                                                   │
│ → Reduce max particle count                                 │
│ → Use LOD (fewer particles at distance)                     │
│ → Switch to GPU simulation                                  │
│ → Reduce overdraw (smaller/fewer particles)                 │
│ → Use simpler shaders                                       │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ PROBLEM: Particles clipping through geometry                │
├─────────────────────────────────────────────────────────────┤
│ SOLUTIONS:                                                   │
│ → Enable collision module                                   │
│ → Use depth fade/soft particles                             │
│ → Adjust near clip plane                                    │
│ → Position emitter away from surfaces                       │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ PROBLEM: Effect looks different in build                    │
├─────────────────────────────────────────────────────────────┤
│ SOLUTIONS:                                                   │
│ → Check quality settings (particle raycast budget)          │
│ → Verify shader compatibility                               │
│ → Test on target hardware                                   │
│ → Check for editor-only components                          │
└─────────────────────────────────────────────────────────────┘

引擎专用工具

引擎系统GPU 支持可视化编辑器
UnityShurikenVFX Graph是(VFX Graph)
UnityVFX Graph原生是
UnrealCascade有限是
UnrealNiagara原生是
GodotGPUParticles是检查器

使用此技能:创建视觉效果、打磨游戏玩法或优化粒子性能时。

评论

支持 Markdown