【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/
本章节添加了更多的音效细节
音频管理器
AudioManager.cs
使得多个音效可以同时播放,注释掉以下代码
cs
public void PlaySFX(int _sfxIndex,Transform _source)//播放音效
{
//if(sfx[_sfxIndex].isPlaying)//如果音效正在播放
// return;
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioManager : MonoBehaviour
{
public static AudioManager instance;
[SerializeField] private float sfxMinimumDistance;//音效最小距离
[SerializeField] private AudioSource[] sfx;//音效
[SerializeField] private AudioSource[] bgm;//背景音乐
public bool playBgm;
private int bgmIndex;
private void Awake()
{
if(instance != null)
Destroy(instance.gameObject);
else
instance = this;
}
private void Update()
{
if (!playBgm)
StopAllBGM();
else
{
if(!bgm[bgmIndex].isPlaying)//如果背景音乐没有播放
PlayBGM(bgmIndex);
}
}
public void PlaySFX(int _sfxIndex,Transform _source)//播放音效
{
//if(sfx[_sfxIndex].isPlaying)//如果音效正在播放
// return;
if(_source!=null && Vector2.Distance(PlayerManager.instance.player.transform.position, _source.position) > sfxMinimumDistance)//距离过远不播放
return;
if (_sfxIndex < sfx.Length)
{
sfx[_sfxIndex].pitch = Random.Range(.85f, 1.15f);//设置音效的音调
sfx[_sfxIndex].Play();
}
}
public void StopSFX(int _index) => sfx[_index].Stop();//停止音效
public void PlayRandomBGM()//播放随机背景音乐
{
bgmIndex = Random.Range(0, bgm.Length);
PlayBGM(bgmIndex);
}
public void PlayBGM(int _bgmIndex)//播放背景音乐
{
bgmIndex = _bgmIndex;
StopAllBGM();
bgm[bgmIndex].Play();
}
public void StopAllBGM()
{
for (int i = 0; i < bgm.Length; i++)
{
bgm[i].Stop();
}
}
}
Blackhole_Skill.cs
加上了释放技能的玩家语音和技能音效
cs
AudioManager.instance.PlaySFX(3, player.transform);
AudioManager.instance.PlaySFX(6, player.transform);
cs
using UnityEngine;
using UnityEngine.UI;
public class Blackhole_Skill : Skill
{
[SerializeField] private UI_SkillTreeSlot blackHoleUnlockButton;
public bool blackHoleUnlocked { get; private set; }
[SerializeField] private int amountOfAttacks;
[SerializeField] private float cloneCooldown;
[SerializeField] private float blackholeDuration;
[Space]
[SerializeField] private GameObject blackHolePrefab;
[SerializeField] private float maxSize;
[SerializeField] private float growSpeed;
[SerializeField] private float shrinkSpeed;
BlackHole_Skill_Controller currentBlackhole;//当前的黑洞
private void UnlockBlackHole()
{
if (blackHoleUnlockButton.unlocked)
blackHoleUnlocked =true;
}
public override bool CanUseSkill()
{
return base.CanUseSkill();
}
public override void UseSkill()
{
base.UseSkill();//调用了基类 Skill中的 UseSkill 方法
GameObject newBlackHole = Instantiate(blackHolePrefab, player.transform.position, Quaternion.identity); //这行代码使用 Instantiate 方法在玩家当前位置生成一个新的黑洞对象
currentBlackhole = newBlackHole.GetComponent<BlackHole_Skill_Controller>();
currentBlackhole.SetupBlackhole(maxSize, growSpeed, shrinkSpeed, amountOfAttacks, cloneCooldown,blackholeDuration);//调用SetupBlackhole,传递一系列参数来配置黑洞的行为,包括最大尺寸、增长速度、缩小速度、攻击次数和克隆冷却时间
AudioManager.instance.PlaySFX(3, player.transform);
AudioManager.instance.PlaySFX(6, player.transform);
}
protected override void Start()
{
base.Start();
blackHoleUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockBlackHole);
}
protected override void Update()
{
base.Update();
}
public bool SkillCompeleted()
{
if(!currentBlackhole)
{
return false;
}
if (currentBlackhole.playerCanExitState)
{
currentBlackhole = null;
return true;
}
return false;
}
public float GetBlackholeRadius()//解决水晶黑洞的攻击范围问题
{
return maxSize / 2;
}
protected override void CheckUnlock()
{
base.CheckUnlock();
UnlockBlackHole();
}
}
ItemObject.cs
添加了拾取物品的音效
cs
public void PickupItem()//将物品添加到背包,然后销毁
{
//11月12日改
if (!Inventory.instance.CanAddItem() && itemData.itemType == ItemType.Equipment)//如果不能添加物品并且物品类型是装备
{
rb.velocity = new Vector2(0, 7);
return;
}
AudioManager.instance.PlaySFX(18, transform);
Inventory.instance.AddItem(itemData);
Destroy(gameObject);
}
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//创建一个物体,放入这个脚本
public class ItemObject : MonoBehaviour
{
[SerializeField] private Rigidbody2D rb;
[SerializeField] private ItemData itemData;//就是你放入的图标
private void SetupVisuals()//设置物品的图标和名称
{
if (itemData == null)
return;
SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
if (spriteRenderer == null)
{
Debug.LogError("SpriteRenderer component is missing");
return;
}
GetComponent<SpriteRenderer>().sprite = itemData.icon;//在编辑器中显示图标
gameObject.name = "Item object - " + itemData.itemName;//直接在编辑器中显示名字
}
public void SetupItem(ItemData _itemData,Vector2 _velocity)//配置物品的数据和掉落的初始速度
{
itemData = _itemData;
rb.velocity = _velocity;
SetupVisuals();
}
public void PickupItem()//将物品添加到背包,然后销毁
{
//11月12日改
if (!Inventory.instance.CanAddItem() && itemData.itemType == ItemType.Equipment)//如果不能添加物品并且物品类型是装备
{
rb.velocity = new Vector2(0, 7);
return;
}
AudioManager.instance.PlaySFX(18, transform);
Inventory.instance.AddItem(itemData);
Destroy(gameObject);
}
}
Checkpoint.cs
到检查点如果火堆未启动过,加个点亮火堆的音效
cs
if(activationStatus==false)
AudioManager.instance.PlaySFX(5, transform);
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//2024.11.28 19:38 疑似有点生病
//
public class Checkpoint : MonoBehaviour
{
private Animator anim;
public string id;
public bool activationStatus;
private void Awake()
{
anim = GetComponent<Animator>();
}
[ContextMenu("产生检查点ID")]//在编辑器中生成一个按钮
private void GenerateId()
{
id = System.Guid.NewGuid().ToString();
}
private void OnTriggerEnter2D(Collider2D collision)//检测到碰撞
{
if (collision.GetComponent<Player>()!=null)//检测到玩家
{
ActivateCheckPoint();//激活检查点
}
}
public void ActivateCheckPoint()//激活检查点
{
if(activationStatus==false)
AudioManager.instance.PlaySFX(5, transform);
activationStatus = true;
anim.SetBool("active", true);
}
}
PlayerMoveState.cs
移动会产生脚步声
cs
public override void Enter()
{
base.Enter();
AudioManager.instance.PlaySFX(14,null);
}
public override void Exit()
{
base.Exit();
AudioManager.instance.StopSFX(14);
}
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMoveState : PlayerGroundedState
{
public PlayerMoveState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
{
}
public override void Enter()
{
base.Enter();
AudioManager.instance.PlaySFX(14,null);
}
public override void Exit()
{
base.Exit();
AudioManager.instance.StopSFX(14);
}
public override void Update()
{
base.Update();
player.SetVelocity(xInput * player.moveSpeed, rb.velocity.y);
if (xInput == 0 || player.IsWallDetected())
stateMachine.ChangeState(player.idleState);//如果玩家没有按下左箭头键或右箭头键,我们将切换到Idle状态
}
}