想要一個真實的心跳
最近和朋友組成了一個不大的遊戲工作室正在開發一款暫定名《大荒鬼差》的遊戲。可以說的部分是這是一個注重探索感知看不見的鬼以及使用各種機關陷阱捉妖抓鬼的遊戲。這個遊戲中有很多關於對鬼感知的設計,其中的一個細節設定是玩家在鬼附近時會有心跳聲強化氛圍以及提供反饋,越是接近鬼,心跳越強烈。心跳要能提供緊張感的同時還能給玩家提供足夠的信息,聽起來不違和不死板。作為整個遊戲第一與聲音相關的部分,我安排自己來做實現(非常有私心的想自己玩玩新的東西)。
先試試最直觀的方案
首先尋找一個心跳的音效,瀏覽我收藏的各種免費商用的音效網站,找到了一個非常乾淨的心臟兩連跳的音頻
波形也很像心跳
導入UE,直接修改播放速度,搞定了,輕鬆愉快。。。嗎?
並沒有,實際上直接播放音頻是沒有播放速度這個選項的,對於音頻直接的修改選項只有音量與音高。想要心跳加快還是需要引入其他的系統。
較為簡單的替代方案
虛幻在多個版本的迭代中提供了多個聲音的處理系統,先用相對較老但是也更簡單用的Sound Cue試一下。官方的文檔在這裡, 與虛幻中絕大部分的編輯器一樣,Sound Cue有一個節點化的編輯界面。整個系統支持的節點並不多,如下圖:
可以看到沒有可以直接調節音頻播放速度的節點,為了讓心跳加速,我們要再自己想點辦法。
拆分重組心跳
先拆解一下心跳的聲音的構成方式,心臟一次循環會產生兩個聲音分別是收縮和舒張,通常來講收縮的聲音更厚重,舒張的聲音相對弱一些。時間上也有一些差異,同一次心臟跳動的收縮與舒張的聲音間隔比兩次心跳之間的時間更短。這個時間比例基本一比二左右。
根據我們的結論,先用Logic Pro將之前的音頻進行拆解。
我們得到了兩個收縮與兩個舒張的音效。
這樣拆開之後還額外帶來一個好處,如果以一次收縮一次舒張作為一次完整的心跳,拆開之後的音頻排列組合一共就可以產生四種不同的心跳音效組合。每次心跳的時候隨機的播放一種組合,這樣可以儘可能減少玩家對聲音的重複感,讓整個音效聽起來不是死板。
確定了方案,我們來看在Sound Cue中的具體實現方式
使用sound cue實現可以調整心跳速度的不那麼死板的心跳音效的節點圖
- 分別導出剛剛的四個音頻,導入UE後,拖入到Sound Cue的編輯界面
- 收縮一組,舒張一組,分別連接到Random(隨機)節點,這樣每次播放的時候會隨機選取一個收縮和一個舒張。
- 我第一次的想法是收縮播放完成播放舒張,所以使用了Concatenator(串聯器)節點,但是根據前面的設計收縮與舒張之間的時間和舒張與下一次收縮之間的時間都是需要調節的,按照這個設計收縮與舒張的間隔只能增加不能減少,所以Concatenator不能滿足需求
- 能夠滿足需求的方式是使用一個Mixer(混音器),加一個Delay(延遲)節點,讓舒張通過Delay節點延後一小段時間播放,再將兩個有所錯位的音頻連入同一個Mixer
- 現在已經構成了一次完整的心跳,Sound Cue支持在節點上直接試聽當前節點的結果,此時在Mixer節點上試聽,多次播放就可以聽到多次不同的心跳效果
- 因為我們的心跳是一個連續的音效而不是一個單次的效果,所以在獲得了單個心跳之後我們還需要再增加一個Delay來表示兩次心跳之間的間隔,再連接一個Loop(循環)節點最終連上輸出節點。此時播放整個sound cue效果就可以聽到無限延續的心跳聲
- 要加快心跳只需要修改兩個Delay節點的時長即可,因為時間計算時從收縮的開始時間開始計算的,所以要注意需要保持一個一比三的比例。
回到最開始的需求,現在的心跳已經比較生動了,也有可以控制速度的方式,接下來就需要將這個音效交給遊戲程序根據情況計算並設置心跳速度就可以了。
然而,事情沒有這麼簡單,sound cue中的數值調節只能手動設定,虛幻官方並沒有提供通過運行時的程序控制這些變量的方法。
ps. delay中倒是可以設定隨機的延遲時間,但是那也只會得到一個心律不齊的心跳
pps. 一個心律不齊的心跳也許在這個遊戲裡也有用武之地
為了程序化的控制心跳速度,我們將會掏出今天的最終武器MetaSounds系統。
來吧,元(Meta)起來
Unreal Engine 5 introduces MetaSounds, a high-performance audio system that provides audio designers with complete control over a Digital Signal Processing (DSP) graph for the generation of sound sources.
根據官方的介紹,MetaSounds是一個次時代的圖形化的高性能音頻數字信號處理系統。理論上音頻設計師可以設計出在遊戲運行時動態處理音頻甚至生成音頻的節點圖。
官方文檔在這裡
這套系統完全可以從簡單的波開始通過各種調製製造音效,但是今天我們只用他的動態傳入控制參數的功能,補全在Sound Cue那個方案中缺失的部分。
整體的邏輯與在Sound Cue中一樣,兩組聲音,各自隨機選擇一個,給舒張加上Delay,再用Mixer一起輸出,循環起來就是心跳。接下來重點說一下不同的部分:
- 首先是音頻的導入方式,MetaSounds採用的是參數化的輸入,所以音頻素材是類型為` Wave Asset` 的輸入參數,因為我們要在多個音頻中隨機,所以最終的參數類型為Wave Asset數組。(我們需要收縮與舒張各一個數組)
- 其次需要定義一下調節心跳速率的變量,根據之前的設計,心跳的速度使用兩個Delay的時間來定義,類型是時間,又因為我們的兩個時間間隔是有數學關係的,所以只需要定義一個參數,計算另外一個就可以了(這裡又用到了MetaSounds的一個重要功能,那就是數學計算)
- 再次是循環的方式,Sound Cue是在最後添加一個循環節點,而MetaSounds是在整個播放邏輯之前加入Repeat Trigger(重複觸發器)
ok,到這裡這個音效就基本完工了,但是我們還是要再補充兩個細節。
- MetaSounds構造的音頻資產默認是有一個OneShot(一次性)的接口的,我們這個心跳音效是持續不斷地,所以要將這個接口刪掉
- 通常來講,隨著心跳加速,心跳的音量也會增強,所以我們再加入一個浮點型的變量作為音量的參數,連接到最終Mixer的增益上,整個音效就可以更加的生動了。
小結與展望
得到了MetaSounds的資產,我們就可以在遊戲角色的運行時邏輯中調用播放,並根據距離設定心跳間隔和音量了。這部分比較簡單,由於我們的遊戲中的心跳的計算並不只與距離有關,有點複雜所以用了C++來實現,這裡就不貼出來了,直接控制心跳的話可以參考這個圖
到這裡今天的全部內容就都結束了,今天的日記記錄的內容都是基於虛幻官方的教程之上的針對我自己的需求的應用,可能不是最佳的實踐,也還有很多改進的空間,但是在思路上我覺得很有趣,使用的工具也是之前完全沒有接觸過的,所以值得記錄和分享一下。如果真的有人能看到這裡,為你點贊,希望你能有所收穫,同時希望我們的遊戲可以順利的完工。
隨緣更新,各位有緣再見。