---
title: "音频"
content_type: tutorial
url: "https://learn.unity.com/tutorial/yin-pin-8?language=zh-cn"
language: zh-cn
difficulty: beginner
duration_minutes: 30
unity_version:
  - "2020.3"
  - "2020.2"
  - "2020.1"
  - "2019.4"
  - "2019.3"
  - "2019.2"
  - "2019.1"
  - "2018.4"
  - "2018.3"
supported_unity_versions:
  - name: "2020.3"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2020.3"
  - name: "2020.2"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2020.2"
  - name: "2020.1"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2020.1"
  - name: "2019.4"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2019.4"
  - name: "2019.3"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2019.3"
  - name: "2019.2"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2019.2"
  - name: "2019.1"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2019.1"
  - name: "2018.4"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2018.4"
  - name: "2018.3"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn&version=2018.3"
available_languages:
  - name: "en"
    url: "https://learn.unity.com/tutorial/audio-ayf.md?language=en"
  - name: "es"
    url: "https://learn.unity.com/tutorial/sonido-su.md?language=es"
  - name: "ja"
    url: "https://learn.unity.com/tutorial/odeio-loq.md?language=ja"
  - name: "ko"
    url: "https://learn.unity.com/tutorial/odio-z338.md?language=ko"
  - name: "zh-cn"
    url: "https://learn.unity.com/tutorial/yin-pin-8.md?language=zh-cn"
last_updated: "2026-08-04T14:21:43.000Z"
---

# 音频

学习为游戏添加配乐和音效并用脚本控制音频，从而完成项目并准备创建构建版本。

现在，您可以通过引人入胜的音频为游戏添加画龙点睛的效果。

在本教程中，您将：

- 探索游戏中可以使用的各种音频
- 添加音轨和一系列音频效果
- 编写脚本来控制游戏中的音频使用

学完本教程后，您的游戏将完成，然后便可以开始创建游戏的构建版本了！

## 1. 音频

现在，您在关卡中已经填入了一系列敌人使 JohnLemon 能够逃生，但是当您测试游戏时，发现游戏有点安静。在本教程中，您将使用一系列诡异的音频来增强气氛，为游戏添加画龙点睛的效果。

本教程将使用两种不同的音频：

- **非剧情声音**，这种声音没有可识别的音源（比如音轨）
- **剧情声音**，这种声音具有可识别的音源（比如枪击声）

让我们首先给游戏添加非剧情音频！

## 2. Unity 音频的入门介绍

在开始向游戏中添加音频之前，让我们快速探究一下音频在 Unity 中的工作方式。主要包括三个部分：音频剪辑 (Audio Clips)、音频源 (Audio Sources) 和音频监听器 (Audio Listener)。


- **音频剪辑 (Audio Clips)** 是诸如 MP3 之类的资源，其中包含与特定声音相关的所有数据。


- **音频源 (Audio Sources)** 是在游戏世界中充当声音起源的组件。在游戏中发出声音的大多数事物都应具有音频源 (Audio Source) 组件，以便声音具有位置。


- **音频监听器 (Audio Listener)** 作为场景中的单个组件，其功能类似于玩家的虚拟耳朵（就像 Camera 组件的作用也类似于玩家的虚拟眼睛一样）。默认情况下，音频监听器 (Audio Listener) 组件位于主摄像机 (Main Camera) 上。

这些不同的部件通常以如下方式协同工作：音频源播放音频剪辑，如果音频监听器离音频源足够近，则可以听到声音。

特定音频源的**空间混合**决定了音频听起来是来自游戏世界中的某个特定点，还是无论音频源与音频监听器之间的距离如何都是同等大小的音量。

您将从非剧情音频开始。由于这种声音没有起源，因此其**空间混合**设置为 **2D**。当空间混合设置为纯 2D 时，音频源和音频监听器之间的距离不会影响音量。之所以称为 2D，是因为仍然可以使用 Stereo Pan 设置来左右平移。如果音频源的空间混合设置为纯 3D，则音量将随着与音频监听器的距离不同而变化。2D 和 3D 之间的值会改变此效果的强度。

## 3. 什么是非剧情音频？

非剧情音频（没有可识别的音源的音频）可能会对您的游戏和玩家体验产生重大影响。想一想您喜欢玩的游戏，它们如何利用这些声音来营造特殊的氛围，让您有什么感觉？这些声音特别有效吗？

您将在自己的游戏中添加三个非剧情声音：

- 一个是循环播放的环境音轨，为鬼屋带来一般性的氛围
- 一个是抓住 JohnLemon 时播放的音效
- 一个是 JohnLemon 设法逃脱时播放的音效

## 4. 为您的游戏创建音频源

首先，为您的游戏创建一些音频源：

**1.**在 Hierarchy 窗口中，单击 Create 菜单并选择 **Create Empty**。将游戏对象重命名为“**Ambient**”。

**2.**在 Inspector 中，将 Ambient 的位置设置为 **(0, 0, 0)**。

该游戏对象的位置在技术上并不重要，因为无论在哪里，音频的音量都是相同的。但是，为了防以后发生问题，让游戏对象的位置保持井然有序总是有用的。

**3.**接下来，需要添加一个 Audio Source 组件。通常情况下可以使用 Add Component 按钮来执行此操作，但是当您还要分配音频剪辑时，可以使用一种快捷的方式。

在 Project 窗口中，选择 **Assets > Audio**。将 **SFXHouseAmbience** 音频剪辑从 Project 窗口拖到 **Inspector 窗口**上即可创建 Audio Source 组件并自动将其分配为音频剪辑 (AudioClip)。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/6fbe9c77-06e4-4fcf-a047-2d931b4d266a_01.PNG)

**4.Spatial Blend** 属性已经完全设置为 2D，因此您无需对其进行更改。默认情况下还已经启用 **Play On Awake**。这意味着，一旦关卡开始，音频就会开始播放。

**5.**但是，默认情况下，音频将在单次完整运行后停止。启用 **Loop** 复选框可以循环播放游戏的环境音轨。

**6.**现在，您的鬼屋有了一些令人毛骨悚然的背景声音！请进入播放模式并测试音频是否正确播放。

**7.**您应该会听到音频，但是与本教程中将要添加的其他声音相比，声音有点大。请退出播放模式以便对此进行调整。

**8.**在 Inspector 中，将 Audio Source 组件的 **Volume** 属性设置为 **0.5**。

## 5. 复制音频源

在这里我们不再针对两个游戏结束音效重复执行上述过程，而是采用以更高效的方式，即复制游戏对象，然后根据需要更改设置。

**1.**在 Hierarchy 窗口中，选择 Ambient 游戏对象。使用 Ctrl + D (Windows) 或 CMD + D (macOS) 快捷方式复制两次该游戏对象。将第一个副本重命名为“**Escape**”，将第二个重命名为“**Caught**”。


![](https://connect-mediagw.unity.com/h1/20190411/learn/images/187468ca-c412-40eb-9c8e-c27b3b8908e7_02.PNG)

**2.**这两个音效之间的唯一区别是使用的音频剪辑 (AudioClip)；它们的设置完全相同。

在 Hierarchy 窗口中，按 Ctrl (Windows) 或 CMD (macOS)，并单击 **Escape** 和 **Caught** 游戏对象。这样一来，您便可以一起编辑这两个游戏对象。

**3.**这些声音不应立即播放，也不应循环播放。此外，需要在游戏中的其他声音之外听到这些声音，因此它们应该比环境音频响亮。


同时选择 Escape 和 Caught 游戏对象，然后：

- 禁用 **Play On Awake** 复选框
- 禁用 **Loop** 复选框

将 **Volume** 的值设置为 **1**

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/87052b63-5143-4ab9-ad2d-653da2b08f93_03.PNG)

现在，您已经调整了这两个游戏对象的通用设置，接下来便可以设置每个游戏对象的音频剪辑 (AudioClip)。

**4.**选择 **Escape** 游戏对象，并将其 Audio Source 组件的 **AudioClip** 设置为 **SFXWin**；要执行此操作，可以将其从 Project 窗口进行拖动或使用圈选按钮。


**5.** 选择 **Caught** 游戏对象，并将其 Audio Source 组件的 **AudioClip** 设置为 **SFXGameOver**；要执行此操作，可以将其从 Project 窗口进行拖动或使用圈选按钮。

现在，您已经设置了非剧情音频源，但是在继续实现 Escape 和 Caught 声音之前，让我们先将音频源整理到单个父项下。


## 6. 整理音频源

要整理音频源，请执行以下操作：

**1.**在 Hierarchy 窗口中，创建一个空游戏对象。将其重命名为“**Audio**”。

**2.**在 Hierarchy 窗口中，按住 Ctrl (Windows) 或 CMD (macOS) 并分别单击 Ambient、Escape 和 Caught 游戏对象以选择这些游戏对象。

**3.** 将选定的游戏对象拖到 Audio 游戏对象上以使 Audio 游戏对象成为它们的父项。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/37bfc45e-3598-4279-8c50-070f38b0a0a2_04.PNG)

## 7. 返回到 GameEnding 脚本

现在您已经整理好了，接下来让我们继续在 GameEnding 脚本中实现游戏结束音效。

在 Project 窗口中，打开 **Assets > Scripts** 文件夹，然后双击 GameEnding 脚本以将其打开进行编辑。

当您最后完成 GameEnding 脚本时，该脚本如下所示：

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameEnding : MonoBehaviour
{
    public float fadeDuration = 1f;
    public float displayImageDuration = 1f;
    public GameObject player;
    public CanvasGroup exitBackgroundImageCanvasGroup; 
    public CanvasGroup caughtBackgroundImageCanvasGroup;

    bool m_IsPlayerAtExit;
    bool m_IsPlayerCaught;
    float m_Timer;
    
    void OnTriggerEnter (Collider other)
    {
        if (other.gameObject == player)
        {
            m_IsPlayerAtExit = true;
        }
    }

    public void CaughtPlayer ()
    {
        m_IsPlayerCaught = true;
    }

    void Update ()
    {
        if (m_IsPlayerAtExit)
        {
            EndLevel (exitBackgroundImageCanvasGroup, false);
        }
        else if (m_IsPlayerCaught)
        {
            EndLevel (caughtBackgroundImageCanvasGroup, true);
        }
    }

    void EndLevel (CanvasGroup imageCanvasGroup, bool doRestart)
    {
        m_Timer += Time.deltaTime;
        imageCanvasGroup.alpha = m_Timer / fadeDuration;

        if (m_Timer > fadeDuration + displayImageDuration)
        {
            if (doRestart)
            {
                SceneManager.LoadScene (0);
            }
            else
            {
                Application.Quit ();
            }
        }
    }
}
```

## 8. 更新 GameEnding 脚本以播放音频

您需要添加在调用 EndLevel 方法时播放音频源的功能。可以播放两种不同的音频源，因此您需要分别引用它们。请记住：在 Update 中的每一帧都会调用 EndLevel 方法。您不希望音频源一直播放，因此您需要通过某种方式在第一次播放之后停止播放。

让我们开始添加音频源引用：

**1.**  在 **exitBackgroundImageCanvasGroup 变量声明**下面添加以下代码：

```csharp
    public AudioSource exitAudio;
```

**2.**在 **caughtBackgroundImageCanvasGroup 变量声明**下面添加以下代码：

```csharp
  public AudioSource caughtAudio;
```

**3.**接下来，您需要创建一个变量以确保音频仅播放一次。一个布尔变量默认情况下为 false，当您要播放音频时，可以确认该变量为 false 并播放音频，并在播放完成时将该变量设置为 true。

在 **m_Timer 变量声明**下面添加以下代码：

```csharp
bool m_HasAudioPlayed;
```

## 9. 调整您的方法以使用新变量

现在，让我们使用以下新变量：

**1.**  由于游戏应根据 JohnLemon 被抓还是逃脱而播放不同的音频源，因此您需要向 EndLevel 方法添加另一个参数。将 EndLevel 方法签名更改为如下所示：

```csharp
  void EndLevel (CanvasGroup imageCanvasGroup, bool doRestart, AudioSource audioSource)
```

**2.**您对 EndLevel 的调用不再具有正确的参数，现在还需要 AudioSource。将第一个 EndLevel 方法调用更改为如下所示：

```csharp
 EndLevel (exitBackgroundImageCanvasGroup, false, exitAudio);
```

**3.**将第二个 EndLevel 方法调用更改为如下所示：

```csharp
EndLevel (caughtBackgroundImageCanvasGroup, true, caughtAudio);
```

这些方法调用现在又正确了，但是当前您的 EndLevel 方法对其新参数不执行任何操作。

## 10. 确保音频仅播放一次


无论计时器经过多久，音频都应该播放，因此在 EndLevel 方法的开头包含音频代码是合理的。您还只希望音频在尚未播放的情况下才播放，因此需要放入 if 语句中进行检查。


**1.**在 EndLevel 方法的开头添加以下代码：

```csharp
   if(!m_HasAudioPlayed)
        {

        }
```

感叹号表示否定其右边的任何内容。这意味着 if 语句中的代码仅在音频未播放时才会执行。

**2.**在这条 if 语句中需要做的第一件事就是播放音频。要播放分配给音频源的音频剪辑，请按以下方式调用音频源的 Play 方法：

```csharp
audioSource.Play();
```

**4.**因为只希望音频播放一次，所以现在需要将 m_HasAudioPlayed 的值设置为 true。这意味着 if 语句中的代码不会再被调用。在 if 语句中的 Play 方法调用下面，添加以下代码：

```csharp
        m_HasAudioPlayed = true;
```

**5.**您现在已经完成了 GameEnding 脚本的编辑。结果应如下所示：

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameEnding : MonoBehaviour
{
    public float fadeDuration = 1f;
    public float displayImageDuration = 1f;
    public GameObject player;
    public CanvasGroup exitBackgroundImageCanvasGroup;
    public AudioSource exitAudio;
    public CanvasGroup caughtBackgroundImageCanvasGroup;
    public AudioSource caughtAudio;

    bool m_IsPlayerAtExit;
    bool m_IsPlayerCaught;
    float m_Timer;
    bool m_HasAudioPlayed;
    
    void OnTriggerEnter (Collider other)
    {
        if (other.gameObject == player)
        {
            m_IsPlayerAtExit = true;
        }
    }

    public void CaughtPlayer ()
    {
        m_IsPlayerCaught = true;
    }

    void Update ()
    {
        if (m_IsPlayerAtExit)
        {
            EndLevel (exitBackgroundImageCanvasGroup, false, exitAudio);
        }
        else if (m_IsPlayerCaught)
        {
            EndLevel (caughtBackgroundImageCanvasGroup, true, caughtAudio);
        }
    }

    void EndLevel (CanvasGroup imageCanvasGroup, bool doRestart, AudioSource audioSource)
    {
        if (!m_HasAudioPlayed)
        {
            audioSource.Play();
            m_HasAudioPlayed = true;
        }
            
        m_Timer += Time.deltaTime;
        imageCanvasGroup.alpha = m_Timer / fadeDuration;

        if (m_Timer > fadeDuration + displayImageDuration)
        {
            if (doRestart)
            {
                SceneManager.LoadScene (0);
            }
            else
            {
                Application.Quit ();
            }
        }
    }
}
```

**6.**保存脚本，然后返回到 Unity。

**7.最后一步是**设置向 GameEnding 脚本添加的引用。在 Hierarchy 窗口中，选择 **GameEnding** 游戏对象。

**8.**在 Inspector 中，使用圈选按钮将 **Exit Audio** 字段设置为 **Escape**，并将 **Caught Audio** 字段设置为 **Caught**。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/d30549b7-4868-4b89-9857-a90b149de6da_05.PNG)

就是这样，您已经完成了非剧情音频的设置！

## 11. 添加脚步声音频

现在，您需要实现可以识别来源的音频。让我们先从脚步声开始吧：

**1.**在 Hierarchy 窗口中，选择 JohnLemon 游戏对象。

**2.**在 Inspector 中，添加一个 **AudioSource** 组件。

**3.**使用圈选按钮将 **AudioClip** 属性设置为 **SFXFootstepsLooping**。

**4.**尽管这是剧情声音，但仍应使用完全 2D 的空间混合 (Spatial Blend)，以便音量不会随着 JohnLemon 的移动而变化，默认设置就很好。

**5.**由于 JohnLemon 在开始时处于静止状态，因此您不希望在场景开始后立即播放音频。**禁用** **Play On Awake** 复选框。

**6.**您希望声音在您命令其停止之前一直播放，因此它需要循环播放。**启用** **Loop** 复选框。

和以前一样，您现在需要编辑脚本，以便可以随时播放音频。

## 12. 返回到 PlayerMovement 脚本

为了启用脚步声音频，需要编辑 PlayerMovement 脚本。双击 PlayerMovement 组件的 **Script** 属性以打开 PlayerMovement 脚本进行编辑。

当您最后完成 PlayerMovement 脚本时，该脚本如下所示：

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public float turnSpeed = 20f;

    Animator m_Animator;
    Rigidbody m_Rigidbody;
    Vector3 m_Movement;
    Quaternion m_Rotation = Quaternion.identity;

    void Start ()
    {
        m_Animator = GetComponent<Animator> ();
        m_Rigidbody = GetComponent<Rigidbody> ();
    }

    void FixedUpdate ()
    {
        float horizontal = Input.GetAxis ("Horizontal");
        float vertical = Input.GetAxis ("Vertical");
        
        m_Movement.Set(horizontal, 0f, vertical);
        m_Movement.Normalize ();

        bool hasHorizontalInput = !Mathf.Approximately (horizontal, 0f);
        bool hasVerticalInput = !Mathf.Approximately (vertical, 0f);
        bool isWalking = hasHorizontalInput || hasVerticalInput;
        m_Animator.SetBool ("IsWalking", isWalking);

        Vector3 desiredForward = Vector3.RotateTowards (transform.forward, m_Movement, turnSpeed * Time.deltaTime, 0f);
        m_Rotation = Quaternion.LookRotation (desiredForward);
    }

    void OnAnimatorMove ()
    {
        m_Rigidbody.MovePosition (m_Rigidbody.position + m_Movement * m_Animator.deltaPosition.magnitude);
        m_Rigidbody.MoveRotation (m_Rotation);
    }
}
```

## 13. 更新 PlayerMovement 脚本以播放音频

现在，您需要编辑脚本，以便 JohnLemon 走路时播放脚步声，而当他静止时停止播放脚步声。

您需要做的第一件事是引用刚刚添加到 JohnLemon 的 Audio Source 组件

**1.**  在 **m_Rigidbody 变量声明**下面，添加以下代码：

```csharp
  AudioSource m_AudioSource;
```

由于这不是公共变量，因此您无法在 Inspector 窗口中分配该变量。相反，您需要像对 Animator 和 Rigidbody 组件一样在代码中分配该变量。


**2.**在 Start 方法中的 **m_Animator 和 m_Rigidbody 变量**后面分配它们的引用，并添加以下代码：

```csharp
 m_AudioSource = GetComponent<AudioSource>();
```

就是这样！接下来，您需要使用 Audio Source 组件的这个引用。

## 14. 调整您的方法以使用新变量

幸运的是，您已经在 FixedUpdate 方法中创建了一个名为 **isWalking** 的变量。这个变量非常适合用于播放和停止脚步声：

**1.**  在 **Animator 组件上的 SetBool 方法调用**下方，添加以下 if-else 语句：

```csharp
     if(isWalking)
        {

        }
        else
        {

        }
```

现在，如果 isWalking 为 true，则可以在音频源上调用 Play，否则如果为 false，则可以在音频源上调用 Stop。


**2.**除非音频源尚未处于播放状态，否则您不希望持续在每一帧都调用 Play。为确保不会在每一帧都进行调用，请在刚添加的 if 语句中添加以下 if 语句：

```csharp
   if(!m_AudioSource.isPlaying)
            {

            }
```

**3.**现在，向 if 语句中添加对 Play 方法的调用：

```csharp
                m_AudioSource.Play ();
```

**4.**要停止播放音频源，请将以下代码添加到 else 语句中：

```csharp
            m_AudioSource.Stop ();
```

**5.**确认您完成的 PlayerMovement 脚本如下所示：

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public float turnSpeed = 20f;

    Animator m_Animator;
    Rigidbody m_Rigidbody;
    AudioSource m_AudioSource;
    Vector3 m_Movement;
    Quaternion m_Rotation = Quaternion.identity;

    void Start ()
    {
        m_Animator = GetComponent<Animator> ();
        m_Rigidbody = GetComponent<Rigidbody> ();
        m_AudioSource = GetComponent<AudioSource> ();
    }

    void FixedUpdate ()
    {
        float horizontal = Input.GetAxis ("Horizontal");
        float vertical = Input.GetAxis ("Vertical");
        
        m_Movement.Set(horizontal, 0f, vertical);
        m_Movement.Normalize ();

        bool hasHorizontalInput = !Mathf.Approximately (horizontal, 0f);
        bool hasVerticalInput = !Mathf.Approximately (vertical, 0f);
        bool isWalking = hasHorizontalInput || hasVerticalInput;
        m_Animator.SetBool ("IsWalking", isWalking);
        
        if (isWalking)
        {
            if (!m_AudioSource.isPlaying)
            {
                m_AudioSource.Play();
            }
        }
        else
        {
            m_AudioSource.Stop ();
        }

        Vector3 desiredForward = Vector3.RotateTowards (transform.forward, m_Movement, turnSpeed * Time.deltaTime, 0f);
        m_Rotation = Quaternion.LookRotation (desiredForward);
    }

    void OnAnimatorMove ()
    {
        m_Rigidbody.MovePosition (m_Rigidbody.position + m_Movement * m_Animator.deltaPosition.magnitude);
        m_Rigidbody.MoveRotation (m_Rotation);
    }
}
```

**6.**保存脚本，然后返回到 Unity。

## 15. 将音频监听器 (Audio Listener) 移动到 JohnLemon

游戏的最后一段音频是幽灵在通过时发出的一些诡异声音。此音频不仅要营造气氛，还将帮助玩家识别危险离自己有多远。

有一个难题是，幽灵的声音在幽灵靠近 JohnLemon 时不会变大，但在靠近摄像机时会变大。这是因为默认情况下，音频监听器 (Audio Listener) 位于主摄像机 (Main Camera) 上。第一步就是要更改此设置。

要将 Audio Listener 组件移到 JohnLemon 游戏对象，请执行以下操作：

**1.**在 Hierarchy 中，选择 **Main Camera** 游戏对象。

**2.**在 Inspector 中，单击 Audio Listener 组件的上下文菜单，然后选择 **Remove Component**。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/918fbbf6-556a-40fc-b928-3bd29af6be4b_06.png)

**3.**在 Hierarchy 中，选择 **JohnLemon** 游戏对象。

**4.**在 Inspector 中，将 **Audio Listener** 组件添加到 JohnLemon。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/64132668-a872-4b85-a983-f7227b453c44_07.PNG)

## 16. 更新 JohnLemon 预制件

您在本教程中对 JohnLemon 所做的所有更改都已对 JohnLemon 预制件的实例做过了。

您添加的新组件在图标上带有 + 号，以表明这些组件已添加到预制件实例中。若是要实例化另一个 JohnLemon，这些音频组件将不存在。

您可以通过将以下更改应用于 JohnLemon 预制件来解决此问题：

**1.**在 Hierarchy 中，选择 JohnLemon 游戏对象。

**2.**在 Inspector 中，找到窗口顶部的 **Overrides** 下拉菜单。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/b927b545-4b04-4469-be12-e632224556d8_08.PNG)

Overrides 下拉菜单会显示 JohnLemon 实例与 JohnLemon 预制件不同的所有方式。

**3.**单击该下拉菜单以查看更改。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/04e4d193-c1e7-4c75-a25b-92166a6fad1b_09.png)

您添加了两个组件：Audio Source 和 Audio Listener。让我们使这些更改成为 JohnLemon 预制件的一部分。

**4.**单击 Overrides 下拉菜单底部的 Apply All 按钮。

## 17. 将音频源添加到幽灵

现在，JohnLemon 预制件具有音频监听器 (Audio Listener)，所有幽灵音频都将具有相对于 JohnLemon 位置的音量。这将使玩家更容易识别与幽灵之间的距离。现在，让我们将音频添加到幽灵：

**1.**在 Hierarchy 窗口中，展开 **Enemies** 游戏对象。

**2.**选择 **Ghost** 游戏对象之一。使用名称旁边的箭头快捷方式可打开预制件以进行编辑。

**3.**在 Project 窗口中，展开 **Assets > Audio** 文件夹，然后找到 **SFXGhostMove 音频剪辑**。

**4.**将 **SFXGhostMove 音频剪辑**从 Project 窗口拖到 Hierarchy 窗口中的 **Ghost 游戏对象**上。

**5.**在 Inspector 窗口中，找到 Audio Source 组件。


**6.**为防止音量过大并确保音量取决于与 JohnLemon 之间的距离，请执行以下操作：


- **启用** **Loop** 属性复选框
- 将 **Volume** 属性设置为 **0.4**
- 将 **Spatial Blend** 设置为 **1**，使其完全为 3D

以上便是基础知识！

## 18. 调整 3D Sound Settings 功能

让我们调整几项高级功能，使幽灵具有出色的音效：

**1.**在 Audio Source 组件中**，**展开 **3D Sound Settings** 部分。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/859c2654-99a6-4b47-81a8-9e915d32d332_10.PNG)


3D Sound Settings 用于控制音频如何随着与音频监听器 (Audio Listener) 之间的距离不同而变化。

**2.**将 **Max Distance** 属性更改为 **10**。将 Max Distance 设置为 10 意味着，当幽灵在 10 米外时，玩家将可以非常轻微地听到它们的声音。

**3.**音量随距离而变化的方式由 **Volume Rolloff** 控制。目前，此设置为 Logarithmic Rolloff，非常适合用于较远的距离。由于您的 Max Distance 现在仅为 10，请将 Volume Rolloff 更改为 **Custom Rolloff**。

**4.**默认的自定义曲线正好适合该游戏，因此无需调整此项。

但是，在完成之前，还有最后一个修复操作。



## 19. 纠正幽灵音效的方向

您已经将 Audio Listener 组件放在 JohnLemon 上，但有一个小问题：当 JohnLemon 转动时，音频监听器 (Audio Listener) 会也随之转动。这意味着，当 JohnLemon 面向屏幕时，玩家的虚拟眼睛（摄像机）和玩家的虚拟耳朵（音频监听器）将面向不同的方向。因此，听起来，鬼魂就像在对面。

让我们结合使用两个属性，使幽灵的声音似乎毫无方向性，但随着幽灵的靠近，声音仍会变大：

**1.**  **SFXGhostMove** 音频剪辑已设置为播放单声道声音 (Mono) 而不是立体声 (Stereo)。这意味着通过左右声道的声音是相同的。（如果要查看 Import Settings，请在 **Assets > Audio** 中查找此部分，然后选择剪辑以查看其设置。）


**2.**在幽灵 (Ghost) 预制件的 Audio Source 组件中，找到 **3D Sound Settings** 部分。Spread 属性用于控制声音听起来的发生范围（以度为单位）。


**3.**将 **Spread** 属性设置为 **180**。这意味着一半的声音将来自每个声道，而由于这些声道相同，因此音频听起来将无方向性。

![](https://connect-mediagw.unity.com/h1/20190411/learn/images/aebf66ba-b856-48ef-acab-2e8c5af45bbd_12.PNG)

**4.**保存幽灵 (Ghost) 预制件，然后返回到场景中。

**5.**保存场景。

您的游戏现在已完成！恭喜！确保对游戏进行测试，以了解玩家的体验情况。

## 20. 总结

在本教程中，您通过向游戏中添加环境音轨和音效来探索了 Unity 中的音频基础知识。您的游戏现在已完成！还有另一件事要做：在最后一个教程中，您将创建游戏的构建版本，以便可以分发游戏。
