在 Unity 中播放音频有几种不同的方法,每种方法都有其独特的优势和用例,在本文中,将详细解释每种方法的工作原理,并提供一些可以在游戏中播放音频使用的示例。
如何在 Unity 中播放音频
播放音频有5种方法
- audioSource.Play – 从脚本开始单个剪辑
- audioSource.PlayOneShot – 播放重叠、重复和非循环的声音
- AudioSource.PlayClipAtPoint – 在 3D 位置播放剪辑,无需音频源
- audioSource.PlayDelayed 或 audioSource.Playscheduled – 以在将来一次播放剪辑
- 或者通过在音频源上选择 Play on Awake 以在加载对象时自动播放剪辑
如何使用播放
//播放音频源
audioSource.Play();
从脚本调用 Play 以启动音频源:
public class PlayAudio : MonoBehaviour
{
public AudioSource audioSource;
void Start()
{
audioSource.Play();
}
}
调用 Play 将触发在音频源上设置的任何音频剪辑,这是最常见的触发音频的方法,最适合播放循环声音和音乐。
这是因为其他一些方法,例如 Play One Shot,无法触发循环声音,还因为使用 Play 将只允许从该音频源一次播放一个剪辑。
在已播放的音频源上调用 Play 将停止音频源并重新开始剪辑。
如何使用 Play One Shot
//在音频源上播放特定剪辑一次
audioSource.PlayOneShot(AudioClip audioClip, Float volumeScale);
Play One Shot 可能是在音频源上触发声音的鲜为人知的方法,但对于触发声音效果非常有用。
public class PlayAudio : MonoBehaviour
{
public AudioSource audioSource;
public AudioClip clip;
public float volume=0.5f;
void Start()
{
audioSource.PlayOneShot(clip, volume);
}
}
在 Audio Source 上调用 Play One Shot,并获取要播放的音频剪辑的参数。这意味着必须在调用 PlayOneShot 时指定要播放的剪辑。
但是,如果只想播放音频源上的任何剪辑,那么可以像这样传递对该剪辑的引用:
audioSource.PlayOneShot(audioSource.clip, volume);
还可以在调用 Play One Shot 时设置可选的音量比例。这需要一个介于 0 和 1 之间的浮点值,并将相对于音频源的音量调整剪辑的音量。
这对于变化非常有用,因为这意味着可以传入一个随机的音量值,或者以不同的音量播放两个不同的剪辑,而无需更改音频源本身的整体音量。
Play One Shot 是音效的理想选择,尤其是重复的声音。在已经播放的音频源上触发 Play One Shot 将重叠声音,而不是像 Play 那样中断它。
这使得 Play One Shot 特别适合重复声音,但要注意,尽量不要让太多的声音同时重叠。
尽管仅从一个音频源播放,但通过 Play One Shot 触发的两个声音将计为两个声音。尽管最大语音限制可以从默认的 32 个语音增加,但不同平台有不同的限制,因此最好尽量保持语音总数尽可能低,以避免声音被剔除。
如何使用 Play Clip At Point
//在特定位置播放一次剪辑,没有音频源
AudioSource.PlayClipAtPoint(AudioClip clip, Vector3 playPosition, Float volume);
Play Clip at Point 的工作方式与 Play One Shot 类似,但有很大不同。它不需要音频源即可工作。
这对于一次性声音非常有用,因为不需要向对象添加音频源组件,只需从场景中的指定位置触发一次声音,而无需模糊不透。
public class PlayAudio : MonoBehaviour
{
public AudioClip clip;
public float volume=1;
void Start()
{
AudioSource.PlayClipAtPoint(clip, transform.position, volume);
}
}
请注意 AudioSource 中的大写 A,因为 Play Clip at Point 使用 Audio Source 类,而不是 Audio Source 的实例。
还必须传递音频剪辑将从其播放的位置。在这个例子中,使用了这个脚本附加到的对象的位置。
那么这到底是如何工作的呢?

在后端 Unity音频 会创建一个新的临时源来播放剪辑,并在剪辑完成后将其处理掉,在编辑器中,会看到一个新的游戏对象出现并在这种情况下消失,这使得 Play Clip at Point 在不能使用音频源组件时特别有用。
例如,在物体被破坏时播放声音。
如果音频源位于被破坏的对象上,声音通常会被切断,或者它可能永远没有机会开始,因为音频源现在不再存在。
相反,使用 Play Clip at Point 可以让声音在对象被破坏后继续播放,该音频源在声音结束后会被整齐地处理掉。
然而,Play Clip at Point 还是存在一点点问题的。
在 Point 处使用 Play Clip 的缺点
由于播放剪辑的音频源是在运行时创建的,因此无法选择更改任何音频源的设置,音频源是使用默认设置创建的,空间混合除外,它将设置为完全 3D。
这也意味着不能将 Play Clip at Point 与混音器一起使用,默认情况下,输出将直接发送到音频侦听器。
如果确实需要更改任何音频源的设置,有一些方法可以解决这个问题,通过创建自己的 Play Clip at Point 功能的修改版本。但是,在这种情况下,简单地使用常规音频源可能会容易得多。
如何使用 Play Delayed 和 Play Scheduled
Play Delayed 和 Play Scheduled 允许在未来以两种不同的方式播放音频源。
播放延迟
//延迟后播放音频源
AudioSource.PlayDelayed(float delay);
第一个,Play Delayed,以秒为单位延迟,是延迟音频剪辑的最简单方法。
public class PlayAudio : MonoBehaviour
{
public AudioSource audioSource;
public float delay=4;
void Start()
{
// Plays an Audio Clip after 4 seconds
audioSource.PlayDelayed(delay);
}
}
此方法易于使用,非常适合快速更改音频源的时序。
使用此功能的示例包括延迟音乐的开始、触发它们的事件之后发生的声音效果,例如闪电和雷声,以及其他时间调整和随机化。
Play Delayed 非常适合简单的计时,但不适合更精确的计时,例如将两个剪辑拼接在一起或节拍匹配的音频剪辑。
为此,需要 PlayScheduled。
播放预定
//在精确的时间播放音频源
AudioSource.PlayScheduled(double timeToPlay);
Play Scheduled 与 Play Delayed 的工作方式略有不同,但它非常精确。
这是因为它使用实际的音频引擎时间运行并采用高精度的双精度值,而不是浮点数。
要使用它,需要指定音频源应该启动的时间,而不是延迟。这对应于AudioSettings.dspTime,即音频引擎已运行的秒数。
Play Scheduled 是精确音频定时任务的理想选择,例如将音频剪辑排队以准确地依次播放,或进行节拍匹配。
下面的示例说明如何在另一个剪辑完成后将剪辑排队以无缝播放。
public class PlayAudio : MonoBehaviour
{
public AudioSource audioSource1;
public AudioSource audioSource2;
void Start()
{
audioSource1.PlayScheduled(AudioSettings.dspTime);
double clipLength = audioSource1.clip.samples / audioSource1.clip.frequency;
audioSource2.PlayScheduled(AudioSettings.dspTime + clipLength);
}
可以使用 PlayScheduled 做很多事情,其中包括如何排队剪辑、节拍匹配音频以及如何用音乐刺痛结束循环的示例。
调度音频时使用 isPlaying 不起作用
使用任一方法调度音频时,音频源被视为在调度后立即播放,直到完成之后。这会在音频源排队时发生,而不是在声音开始时发生,因此 isPlaying 将为真,即使尚未发出声音。
这意味着,在安排音频时,无法使用 isPlaying 检查音频是否已启动或停止。
如何使用 Play on Awake
Play on awake 是触发声音的最简单方法,因为它不需要任何脚本。

默认启用,Play on Awake 将在对象启用后立即启动音频源,如果游戏对象已经启用,这通常是场景的开始,或者,如果它被禁用,则在游戏对象或音频源激活时 Play on Awake 将立即触发。
这对于在加载对象时自动启动音频很有用,例如场景开始时的音乐或对象初始化时播放的声音。
例如,要在创建新对象时添加声音,只需将 Audio Source 组件添加到该对象的 prefab 并确保选中 Play on Awake。然后,当对象被添加到场景中时,声音就会播放。
有关可以从音频源调用的不同方法的更多信息,请尝试 Unity官方音频源文档 。
其他选项
虽然 Unity 处理音频的内置选项比以前好得多,但如果想轻松访问高级音频功能 或者 只是想节省一些时间,可能需要考虑第三方 Unity源码 。
例如, Master Audio 长期以来一直是音频管理器资产不错的选择标准,功能齐全且支持良好,它提供了高级功能,例如音频遮挡,所以使用该工具可以挑战性的多人游戏音频变得更加容易。
音频触发示例
通过以上内容我们大概知道了在 Unity 中触发音频的不同方法,那么将在下面谈谈一些常见音频触发器的示例,可以将它们复制并粘贴到自己的项目中。
如何播放随机声音
在 Unity 中选择随机声音的最佳方法是什么?首先,创建一个音频源和一组音频剪辑。
public AudioSource audioSource;
public AudioClip[] audioClipArray;
回到 Unity,将不同的音频剪辑添加到数组中。

接下来,编写一个返回类型为 Audio Clip 的函数,以随机选择其中一个剪辑。
AudioClip RandomClip(){
return audioClipArray[Random.Range(0, audioClipArray.Length)];
}
然后,每当想使用随机音频剪辑时,请传入通常会传入剪辑名称的函数:
void Start() {
audioSource.PlayOneShot(RandomClip());
}
如何触发随机声音,不重复
为防止同一声音连续触发两次,请将前一个声音存储在一个变量中,并使用 while 语句对其进行检查,如下所示:
public class PlayAudio : MonoBehaviour
{
public AudioSource audioSource;
public AudioClip[] audioClipArray;
AudioClip lastClip;
void Start()
{
audioSource.PlayOneShot(RandomClip());
}
AudioClip RandomClip()
{
int attempts = 3;
AudioClip newClip = audioClipArray[Random.Range(0, audioClipArray.Length)];
while (newClip == lastClip && attempts > 0)
{
newClip = audioClipArray[Random.Range(0, audioClipArray.Length)];
attempts--;
}
lastClip = newClip;
return newClip;
}
}
如何播放重复的声音
下面是一个如何在 Unity 中重复触发声音的示例,在例子中为每 0.25 秒发射一次的声音。
还使用上一个示例中的 Audio Clip 数组在每次射击时使用随机声音。
public class PlayAudio : MonoBehaviour
{
public AudioSource audioSource;
public AudioClip[] audioClipArray;
public float timeBetweenShots = 0.25f;
float timer;
void Update()
{
timer += Time.deltaTime;
if (timer > timeBetweenShots)
{
audioSource.PlayOneShot(RandomClip());
timer = 0;
}
}
AudioClip RandomClip()
{
return audioClipArray[Random.Range(0, audioClipArray.Length-1)];
}
}
按下按钮时如何播放声音
Unity 有一个内置方法,用于在按下按钮时触发事件,其中包括播放音频剪辑的选项。
只需创建一个 On Click 事件触发器,将一个游戏对象拖到对象字段并从下拉菜单的音频源部分选择 PlayOneShot(AudioClip)。

选择播放一个后,在出现的新字段中选择要播放的音频剪辑。通过使用 Play One Shot,可以让不同的按钮仅使用一个音频源播放不同的声音。
但是,也可以从 Play 或 PlayDelayed 中进行选择,就像从脚本播放时一样。
进入区域时如何启动音乐
如何在 Unity 中制作当角色进入特定区域时触发的音乐触发器?
首先创建触发器:
- 创建一个形状,例如一个盒子,作为场景中的触发区域。
- 如果有网格渲染器,请删除它,不需要。
- 在 Collider 组件上确保 Is Trigger 设置为 true。
- 如果 Player 对象还没有,需要添加一个刚体组件才能使其工作。
- 最后,在 Player 对象上,选择 Player Tag。

接下来,将此脚本添加到触发区域:
public class PlayOnCollision : MonoBehaviour
{
public AudioSource audioSource;
void OnTriggerEnter(Collider other)
{
if (other.tag == "Player" && !audioSource.isPlaying)
{
audioSource.Play();
}
}
}
如何在 2D 中创建触发声音
要在 2D 项目中创建相同的效果,只需使用 2D Collider 和 2D Rigidbody,确保更新脚本以匹配:
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player" && !audioSource.isPlaying)
{
audioSource.Play();
}
}
与物体碰撞时如何播放声音
就像进入一个区域一样,可以在两个物体发生碰撞时触发声音,对象需要有一个刚体组件才能工作。
将此脚本放在移动对象上:
public class PlayOnCollision : MonoBehaviour
{
public AudioSource audioSource;
void OnCollisionEnter(Collision collision)
{
audioSource.Play();
}
}
为了防止轻微碰撞触发声音,可以通过检查碰撞的速度只播放较大碰撞的声音:
public class PlayOnCollision : MonoBehaviour
{
public AudioSource audioSource;
void OnCollisionEnter(Collision collision)
{
if(collision.relativeVelocity.magnitude > 1)
audioSource.Play();
}
}
或者,为了获得更自然的碰撞声音,可以根据碰撞力改变音量。
public class PlayOnCollision : MonoBehaviour
{
public AudioSource audioSource;
public float maxForce = 5;
void OnCollisionEnter(Collision collision)
{
float force = collision.relativeVelocity.magnitude;
float volume = 1;
if (force <= maxForce)
{
volume = force / maxForce;
}
audioSource.PlayOneShot(audioSource.clip, volume);
}
}
音量值决定了什么样的冲击力会产生最大的声音量,超过最大的值只会以最大音量播放。
如何在 2D 中创建碰撞声音
可以使用相同的方法在 2D 游戏中使用 2D Colliders、2D Rigidbody 和更新脚本类来创建碰撞音效,如下所示:
void OnCollisionEnter2D(Collision2D collision)
{
audioSource.Play();
}
如何在破坏物体时播放声音
要在对象被破坏后继续播放声音,一种选择是使用 Play Clip at Point,如下所示:
public class PlayOnDestroy : MonoBehaviour
{
public AudioClip audioClip;
void DestroyObject()
{
AudioSource.PlayClipAtPoint(audioClip, transform.position);
Destroy(gameObject);
}
}
这通过创建一个在对象的最后一个位置播放的临时音频源来工作,即使原始对象已经消失。
以上涵盖的音频基础知识,可以轻松地了解更多信息,以便在未来进行研究或为未来的音频开发更先进的思路,都是可以的。