Pepper.SFX
All Guidance pages

Guidance / Cookbook

Weapons & Combat

Recipe: Weapon Fire Sound

📋 What: Weapon shot with variations and instance limiting

🎯 Use Case: Guns, projectile weapons

Asset Setup

1. Create Container:

  • Random Container: “Weapon_RifleShot_RnC”
  • Audio Clips: 3-5 firing variations
  • Avoid Repeat Last: 1
  • Volume: 1.0
  • Volume Randomization: ±1 dB
  • Pitch Randomization: ±75 cents
  • Is3D: ✓
  • Min Distance: 5
  • Max Distance: 50

2. Create Event:

  • Event: “Play_Weapon_RifleShot”
  • Priority: High
  • Max Instances: 8
  • Steal Behavior: Oldest
  • Actions: Play Weapon_RifleShot_RnC → Weapons_Bus

Code

using UnityEngine;
using AudioSystem;

public class WeaponAudio : MonoBehaviour
{
    [Header("Audio Events")]
    [SerializeField] private AudioEvent fireEvent;
    [SerializeField] private AudioEvent reloadEvent;
    [SerializeField] private AudioEvent emptyEvent;
    [SerializeField] private AudioEvent equipEvent;

    public void OnFire()
    {
        if (fireEvent != null)
        {
            fireEvent.Post(gameObject, transform.position);
        }
    }

    public void OnReload()
    {
        if (reloadEvent != null)
        {
            reloadEvent.Post(gameObject, transform.position);
        }
    }

    public void OnEmpty()
    {
        if (emptyEvent != null)
        {
            emptyEvent.Post(gameObject, transform.position);
        }
    }

    public void OnEquip()
    {
        if (equipEvent != null)
        {
            equipEvent.Post(gameObject, transform.position);
        }
    }
}

Integration:

// In your weapon controller
public class WeaponController : MonoBehaviour
{
    private WeaponAudio weaponAudio;

    void Start()
    {
        weaponAudio = GetComponent<WeaponAudio>();
    }

    void Fire()
    {
        if (HasAmmo())
        {
            // Fire logic...
            weaponAudio?.OnFire();
        }
        else
        {
            weaponAudio?.OnEmpty();
        }
    }

    void Reload()
    {
        // Reload logic...
        weaponAudio?.OnReload();
    }
}

✅ Result: Professional weapon audio with variations!


Recipe: Impact Sounds by Material

📋 What: Different impact sounds based on hit material

🎯 Use Case: Bullet impacts, melee hits, projectile collisions

Asset Setup

1. Create Material Containers:

  • “Impact_Metal_RnC” (5-6 metal impact clips)
  • “Impact_Wood_RnC” (5-6 wood impact clips)
  • “Impact_Concrete_RnC” (5-6 concrete clips)
  • “Impact_Flesh_RnC” (4-5 flesh/organic clips)
  • “Impact_Default_RnC” (generic impacts)

2. Create Switch Container:

  • Switch Container: “Impact_Switch_SwC”
  • Switch Group Name: “ImpactMaterial”
  • Entries:
    • “Metal” → Impact_Metal_RnC
    • “Wood” → Impact_Wood_RnC
    • “Concrete” → Impact_Concrete_RnC
    • “Flesh” → Impact_Flesh_RnC
  • Default: Impact_Default_RnC

3. Create Event:

  • Event: “Play_Impact”
  • Priority: Medium
  • Max Instances: 12
  • Actions: Play Impact_Switch_SwC → SFX_Bus

Code

using UnityEngine;
using AudioSystem;

public class ProjectileImpact : MonoBehaviour
{
    [SerializeField] private AudioEvent impactEvent;
    [SerializeField] private GameObject impactVFXPrefab;

    void OnCollisionEnter(Collision collision)
    {
        HandleImpact(collision);
    }

    void HandleImpact(Collision collision)
    {
        // Determine material
        string material = GetMaterialType(collision.collider);

        // Set switch
        AudioManager.Instance.SetSwitch("ImpactMaterial", material);

        // Play impact sound at contact point
        if (impactEvent != null && collision.contacts.Length > 0)
        {
            Vector3 impactPoint = collision.contacts[0].point;
            impactEvent.Post(gameObject, impactPoint);
        }

        // Spawn VFX
        if (impactVFXPrefab != null && collision.contacts.Length > 0)
        {
            Instantiate(impactVFXPrefab, collision.contacts[0].point,
                       Quaternion.LookRotation(collision.contacts[0].normal));
        }

        // Destroy projectile
        Destroy(gameObject);
    }

    string GetMaterialType(Collider hitCollider)
    {
        // Method 1: Check tag
        if (hitCollider.CompareTag("Metal")) return "Metal";
        if (hitCollider.CompareTag("Wood")) return "Wood";
        if (hitCollider.CompareTag("Enemy") || hitCollider.CompareTag("Player"))
            return "Flesh";

        // Method 2: Check layer
        int layer = hitCollider.gameObject.layer;
        if (layer == LayerMask.NameToLayer("Metal")) return "Metal";
        if (layer == LayerMask.NameToLayer("Wood")) return "Wood";

        // Method 3: Custom component
        var surfaceID = hitCollider.GetComponent<SurfaceIdentifier>();
        if (surfaceID != null)
            return surfaceID.MaterialType;

        return "Default";
    }
}

// Optional: Attach to surfaces for explicit material identification
public class SurfaceIdentifier : MonoBehaviour
{
    public string MaterialType = "Concrete";
}

✅ Result: Dynamic impact sounds matching hit materials!

From the Pepper.SFX 3.1 guides (USER_GUIDE.md). Something wrong or unclear? Tell me.