学习游戏制作记录(音频的制作和使用)8.28

发布于:2025-08-30 ⋅ 阅读:(19) ⋅ 点赞:(0)

1.音频管理器

创建管理器对象

创建AudioManager脚本:

public static AudioManager instance;

[SerializeField] private AudioSource[] SFX;//音效
[SerializeField] private AudioSource[] BGM;//bgm


public bool playBGM;//是否播放bgm
private int bgmIndex;//bgm的索引

public void Awake()
{
    if (instance != null)
    {
        Destroy(instance.gameObject);
    }
    else
    {
        instance = this;
    }
}
void Update()
{
    if(!playBGM)//确保bgm的正确播放
        StopAllBGM();
     else
    {
        if (!BGM[bgmIndex].isPlaying)
            PlayBGM(bgmIndex);
    }
}

public void PlaySFX(int _SFXindex)
{
    if(_SFXindex<SFX.Length)

        {

         SFX[_SFXindex].pitch = Random.Range(.85f, 1.1f);//每次音效的效果不同
                SFX[_SFXindex].Play();//播放指定音效
                }


}

public void StopSFX(int _SFXindex) => SFX[_SFXindex].Stop();

public void PlayRandomBGM()//播放随机bgm
{
    bgmIndex =Random.Range(0, BGM.Length);
    PlayBGM(bgmIndex);
}
public void PlayBGM(int _BGMindex)//播放指定bgm
{
    bgmIndex= _BGMindex;

    StopAllBGM();

    BGM[bgmIndex].Play();

}
public void StopAllBGM()
{
    for(int i = 0; i < BGM.Length; i++)
    {

        BGM[i].Stop();
    
    }

}

2.音频的距离限制

AudioManager脚本:

    [SerializeField] private float sfxMinDistance;

    public void PlaySFX(int _SFXindex,Transform _source)//传入声源的位置
    {
        if (SFX[bgmIndex].isPlaying)//防止重复播放
            return;

        if (_source != null && Vector2.Distance(PlayerManage.instance.player.transform.position, _source.position) > sfxMinDistance)//检测距离
            return;


        if(_SFXindex<SFX.Length)
        {
            SFX[_SFXindex].pitch = Random.Range(.85f, 1.1f);
            SFX[_SFXindex].Play();
        }
    }

SkeletonIdleState脚本:

    public override void Exit()
    {
        base.Exit();

        AudioManager.instance.PlaySFX(14,enemy.transform);//敌人退出待机状态时播放音乐
    }

3.更多音频的设置

 PlayerMoveState脚本:

    public override void Enter()
    {
        base.Enter();

        AudioManager.instance.PlaySFX(14, null);//播放脚步声
    }

    public override void Exit()
    {
        base.Exit();

        AudioManager.instance.StopSFX(14);
    }

Checkpoint脚本:
 

    public void ActiveCheckPoints()
    {
        if(activeStatus==false)
        {
        AudioManager.instance.PlaySFX(5, transform);//播放检查点激活的音效

        }
        activeStatus=true;
        anim.SetBool("active", true);
    }

ItemObject脚本:

    public void PickupObject()
    {
        if (!Inventory.instance.canAddItem() && itemData.itemType==ItemType.Equipment)
        {
            rb.velocity = new Vector2(0, 7);
            return;
        }
            Inventory.instance.AddItem(itemData);
        AudioManager.instance.PlaySFX(18, transform);//物品拾取的音效
        Destroy(gameObject);
    }

Blackhole_Skill脚本:

    public override void UseSkill()
    {
        base.UseSkill();
       
        GameObject newblackhole = Instantiate(blackholePrefab,player.transform.position,Quaternion.identity);

        currentBlackholeScript = newblackhole.GetComponent<Blackhole_Skill_Control>();

        currentBlackholeScript.SetupBlackhole(maxSize, growSpeed, shrinkSpeed, cloneAttackCooldown, amountofAttack,blackholeDuration);

        AudioManager.instance.PlaySFX(3,player.transform);//播放黑洞的声音
        AudioManager.instance.PlaySFX(6, player.transform);
    }

4.音频混合器的设置

UI_VolumeSlider脚本:

  public Slider slider;//滑块
  public string pamater;//音频混合器的参数

  [SerializeField] private AudioMixer audioMixer;//音频混合器
  [SerializeField] private float mutiplier;//乘数
  private const string delayedMethodName = "DelayedSetVolume";
  private float pendingValue;

  public void SliderValue(float _value)
  {

      if (IsInvoking(delayedMethodName))
      {
          CancelInvoke(delayedMethodName);
      }

      pendingValue = _value;

      Invoke(delayedMethodName, 0.01f);//延迟调用声音调整
  }

  private void DelayedSetVolume()
  {
      float dB = Mathf.Log10(pendingValue) * mutiplier;
      audioMixer.SetFloat(pamater, dB);//修改音频混合器

  }


  public void LoadSlider(float _value)//加载数据
  {

      if (_value >= 0.001f)
          slider.value = _value;
  }

GameData脚本:

    public SerializbleDictionary<string, float> volumeSettings;//需要保存的数据

UI脚本:

public class UI : MonoBehaviour,ISaveManager实现保存接口

 [SerializeField] public UI_VolumeSlider[] volumeSettings;

    public void LoadDate(GameData gameData)//加载声音的调整
    {
        foreach (KeyValuePair<string,float> pair in gameData.volumeSettings)
        {
            foreach(UI_VolumeSlider item in volumeSettings)
            {
                if(item.pamater==pair.Key)
                    item.LoadSlider(pair.Value);
            }
        }
    }

    public void SaveDate(ref GameData gameData)//保存声音的调整
    {
        gameData.volumeSettings.Clear();

        foreach(UI_VolumeSlider volumeSlider in volumeSettings)
        {
            gameData.volumeSettings.Add(volumeSlider.pamater, volumeSlider.slider.value);
        }

    }‘

5.音频时间限制器

AudioManager脚本:

    private bool canPlaySFX;//是否可以播放音效

   public void PlaySFX(int _SFXindex, Transform _source)
   {
       if(canPlaySFX==false)//不能则直接返回
       {
           return;
       }
       //if (SFX[bgmIndex].isPlaying)
       //return;

       if (_source != null && Vector2.Distance(PlayerManage.instance.player.transform.position, _source.position) > sfxMinDistance)
           return;


       if (_SFXindex < SFX.Length)
       {
           SFX[_SFXindex].pitch = Random.Range(.85f, 1.1f);
           SFX[_SFXindex].Play();
       }
   }

private void AllowSFXPlay()=>canPlaySFX = true;//启用音效

    public void Awake()
    {
        if (instance != null)
        {
            Destroy(instance.gameObject);
        }
        else
        {
            instance = this;
        }

        Invoke("AllowSFXPlay", 1f); //延迟调用
     }

6.区域音效制作

创建AreaSound脚本并挂载在一片空对象上:

    [SerializeField] private int areaSoundIndex;//该区域对应的音效索引

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.GetComponent<Player>() != null)
            AudioManager.instance.PlaySFX(areaSoundIndex,null);//进入播放
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.GetComponent<Player>() != null)
            AudioManager.instance.StopSFXWithTime(areaSoundIndex);//退出时缓慢的关闭音乐
    }

AudioManager脚本:

    public void StopSFXWithTime(int _index)
    {
        StartCoroutine(DecreaseVolume(SFX[_index]));
    }

    private IEnumerator DecreaseVolume(AudioSource _audio)//延迟关闭,并且缓慢较小音效的音调大小
    {
        float defualtVolume=_audio.volume;

        while(_audio.volume > .1f)
        {
            _audio.volume -= _audio.volume * .2f;
            yield return new WaitForSeconds(.6f);

            if(_audio.volume <.1f)
            {
                _audio.Stop();
                _audio.volume=defualtVolume;
                break;
            }

        }
    }