iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0

在我們的環境中,常會有一些聲音與音效來提高我們遊戲的體驗,在實驗的過程中我們也會將聲音作為一種非視覺的回饋,告訴受試者完成某一件事情或是滿足某一個條件等,對我們來說非常重要。所以今天我將會透過一個簡單將兩物件接觸後觸發音效來演示音效產生的功能。 今天的實驗將會有趣也很簡單,那就讓我們開始吧XD

建置場景

  1. 我們建置一個場景,ActiveRegion 是當我觸發的時候會發出一個觸發的聲音。 TargetPoint 是我要主動去觸發ActiveRegion 的物件。

  2. 我們先新增Empty Object 該命名為 AudioManager,並在 Component 內新增Audio Listener。

  3. 接著在我們的 Target 中增加 Audio Source,也就是物件上新增一個Component。我這邊是登入註冊該網站,裡面有免費的音效。
    https://www.zapsplat.com/sound-effect-categories/

  4. 接著要將Mp3 檔案放置在該Audio Source中, AudioClip 上面。

  • 注意到 Play On Awake 要取消勾選。
  1. 如果你想要聽看看該Audio Source 的聲音可以點選 下方的Sound Effect 下面有撥放可以點選。

撰寫文本

  1. 接著在 AudioManager 上新增一個 Scripts ,我們這邊就叫做 Audio Feedback 。

  2. 接著在 Project 內新增一個 Sound.cs 的腳本,主要是控制該Sound Feedback 的控制。並不會使用到任何 Unity 內部的物件或是環境的元素,故不要去繼承 MonoBehaviour ,主要就只是去控制音量的大小與高低,並且讓我們環境可以儲存各種不同的音效。

Sound.cs Scripts

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Sound 
{
    public string  name;
    public AudioClip clip;                      // clip is the audio type 
    [Range(0f, 1f)]public float volume;         // volume 
    [Range(.1f, 3f)]public float pitch;         // pitch

    [HideInInspector]
    public AudioSource source;
    
}
  • 這邊就是控制聲音的大小,高低
  • 注意到這邊 Name 很重要,因為代表之後我們要去尋找不同的聲音就是依照 Sound 文本物件去取得 Name 的名稱。
  • 接下來要記得去撰寫一個 AudioSource source 的物件,並且將它 HideInInspector 不要顯示在Unity 的 Inspector 上面。

AudioFeedback.cs

  1. 第一步因為之後會有一些不同的音效,所以說要新增一個Sound Class Array Object。也就是 Sound.cs 各種不同的物件。
public Sound[] sounds;
  1. 這邊就是要去處理 Audio Clip音效的高低調整。 所以要去 foreach 讓系統可以個別調整該不同的聲音。 Start就是當系統啟動的時候就會開始控制。
void Start() 
    {
        foreach(Sound s in soundsArr)
        {
            s.source = gameObject.AddComponent<AudioSource>();
            s.source.clip = s.clip;
            s.source.volume = s.volume;
            s.source.pitch = s.pitch;
            
        }
    }
  1. 後面需要寫一個 PlayEffect method 去驅動該聲音,這邊使用 Lambda 方式去尋找該聲音的名稱在哪裡。接著將聲音實現。
// set the name and find the name of the sound effect
    void playSoundEffect(string name) 
    {
        Sound soundObj = Array.Find(soundsArr, sound => sound.name == name);
        // find the name of the Audio Clip
        soundObj.source.Play();                                                    
        // play the sound effect
    }
  1. 完整程式碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class AudioFeedback : MonoBehaviour
{
    public Sound[] soundsArr;

    void Start() 
    {
        foreach(Sound s in soundsArr)
        {
            s.source = gameObject.AddComponent<AudioSource>();
            s.source.clip = s.clip;
            s.source.volume = s.volume;
            s.source.pitch = s.pitch;

        }
    }

    // set the name and find the name of the sound effect
    void playSoundEffect(string name) 
    {
        Sound soundObj = Array.Find(soundsArr, sound => sound.name == name);       
        // find the name of the Audio Clip
        soundObj.source.Play();                                                    
        // play the sound effect
    }

}
  1. 最後回到 Unity 上中的 Inspector 中看到該結果,我們將該剛剛新增的 Sound Sorce 放置於該AudioFeedback 文本中的Array 內部,就可以去調整該Effect 的名稱以及聲音的大小與高低。

如何使用該聲音?

  1. 首先我們可以用之前學習到的 Collision關係來尋找兩個物件是否碰撞! 先將兩個物件 ActiveRegion 與 TargetPoint 各新增 Rigidbody。並把他們Rigidbody 的 Use Gravity 給取消勾選。

  2. 撰寫一個簡單的程式碼,如果當小球TargetPoint 觸發到 ActiveRegion 的話,就會有聲音的回饋,這時候我們就會需要勾選其中一個物件的 IsTrigger,因為我們不需要任何的物理碰撞! 我這邊勾選該 TargetPoint 中 Sphere Collider 的 IsTrigger

  3. 撰寫腳本,我們新增一個AwakeSound.cs 的腳本到我們TargetPoint 上面,首先我們撰寫當兩個物件接觸的瞬間的判斷。請記得如果要使用 OnTriggerEnter務必要使用在本身的物件上。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AwakeSound : MonoBehaviour
{
    private void OnTriggerEnter(Collider collision){
        if(collision.gameObject.name == "ActiveRegion")
        {
            Debug.Log("Trigger something!");
        }
    
    }
    
}
  1. 回到 Unity 執行後就會看到當我們TargetPoint 碰觸到物件Console 就會輸出 Trigger someting。

  2. 最後就是要去使用該聲音了,現在就回到你需要喚醒聲音的地方。

  3. 這邊就是需要去新增該聲音的地方。增添一行取出該物件並且去直接使用 Class 內部的方法。無須使用 Static。我們可以直接在Update 中使用。

// audio effect
FindObjectOfType<AudioFeedback>().Play("effect");
  1. 加上一個判斷式來判斷兩物件接觸時喚醒聲音。非常好用,未來也可以根據該聲音的長短決定要做什麼樣聲音的回饋。比如說兩個車碰撞再一起的聲音,或是電梯門到某一層樓開電梯門瞬間的回饋等。當然你也可以透過使用距離來當作判斷音效的開始。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class AwakeSound : MonoBehaviour
{
    private void OnTriggerEnter(Collider collision){
        if(collision.gameObject.name == "ActiveRegion")
        {
            Debug.Log("Play Sound!");
             FindObjectOfType<AudioFeedback>().playSoundEffect("sound1");
        }
    }
        
}
  1. 這邊可能沒辦法實際的執行給大家聽到聲音上的變化,所以就針對場景顯示。

結論:

  1. 今天我們討論到如何使用 Unity 產生一些有趣的聲音,來產生非視覺的回饋。
  2. 也撰寫透過 FindObject 來獲取觸發聲音的方式。
  3. 以上這個聲音的實作未來也可以實現使用更多不同的聲音在不同的場合中。

上一篇
Day16: Player Movement Control
下一篇
Day18: Understand Rotate in VR
系列文
Unity 基本功能實作與日常紀錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言