【Unity3D】 Unity Chan項目分享

 

https://blog.csdn.net/candycat1992/article/details/51357077git

寫在前面

以前的一個博文裏分享了日本Unity醬的項目,若是你們有去仔細搜Unity醬的話,就會發現日本Unity官方還放出了一個更完整的Unity醬的項目,感受被萌化了!(事實上,Unity日本常常會分享一些開源項目,要常關注github~)github

這裏寫圖片描述

一些效果

項目裏還有有一些特效實現能夠借鑑下的~函數

MusicPlayer

這個項目裏的特效有個最大的特色就是,特效會根據音效作出反饋。這個功能主要是經過做者的另外一個開源插件Reaktion來實現的(Keijiro Takahashi是個多產哥,這哥們感受一年時間都用在寫開源項目了,一年有幾十的repositories。。)只惋惜文檔都不是很全,大多須要本身去稍微讀一下源碼。Keijiro曾經爲Reaktion寫過一版文檔,不過看來沒有維護下去……性能

想要讓Reaktion工做就須要有三個關鍵部分,音頻注入器Injector音頻核心處理器Reaktor以及接收信號的裝置Gear,Injector把音頻信號傳遞給某個Reaktor,而後場景裏全部的Gear會監聽某個Reaktor的輸出,它們之間的連接都是經過GenericLink類實現的。也就是咱們須要兩個links,一個link(InjectorLink類型)負責讓每一個Reaktor找到一個Injector,一個link(ReaktorLink類型)負責讓每一個Gear找到一個Reaktor。它們都有四種連接模式(在GenericLink.cs中被定義):Not Bound,即不綁定輸入;Auto Bind,找到離該物體最近的那個輸入器(先在自身身上找,否則再找父親,否則再找兒子,否則再找全場景);Bind By Reference則可讓咱們直接拖一個輸入的引用;Bind By Name則會在場景裏找名字爲該字符串的特定輸入。優化

所以,整個過程大概就是:spa

  1. 在場景裏添加一個AudioSource,而後在同一個物體上添加AudioInjector.cs,以及添加Reaktor.cs,保證該Reaktor能夠找到這個Injector(能夠直接把模式設成Auto Bind就會直接找到自身綁定的這個Injector了)。咱們能夠調整Reaktor上的屬性來對音頻信號進行調整。
  2. 想要接收聲音信號的話能夠在自定義腳本中聲明Reaktion.ReaktorLink類型的變量。例如:.net

    public Reaktion.ReaktorLink spectrum1; public Reaktion.ReaktorLink spectrum2; public Reaktion.ReaktorLink spectrum3; public Reaktion.ReaktorLink spectrum4;
    • 1
    • 2
    • 3
    • 4

    聲明瞭四個音頻來源,那麼在面板上就是這樣的結果:插件

    這裏寫圖片描述

    咱們能夠經過不一樣的連接模式來爲它們綁定不一樣的Reaktor,如上所示。而後在代碼裏經過Reaktion.ReaktorLink.Output就能夠直接獲得輸出信號了。3d

  3. 做者爲咱們內置了一些常見的信號功能,例如把信號傳遞給材質來設置屬性值(MaterialGear)、設置Transform屬性(TransformGear)、設置粒子系統屬性(ParticleSystemGear)等。咱們能夠直接使用這些內置的腳本(都在Reaktion/Gear文件夾下)。

到這個具體項目裏,全部的Injectors和Reaktors都在名爲MusicPlayer的prefab中。它的結構以下:code

這裏寫圖片描述

MusicPlayer包含了五個子物體,其中四個子物體(Spectrum 1,Spectrum 2等)各包含了一對Injector和Reaktor,之因此有四個是由於做者想要使用不一樣的過濾器(BandPassFilter.cs)來過濾同一個音頻,獲得四種音頻信號。注意到每一個Spectrum上的AudioInjector上的Mute屬性被勾選了,這意味着雖然它們身上都有一個AudioSource但並不會發出任何聲音。真正的音樂是由第五個子物體Main負責發出的。

舞臺光柱、臺標、光圈和環狀大軌道

這個項目裏不少效果都會隨着音效變化,變化比較類似的是舞臺後面光柱(Pillars)、Unity Chan的臺標(Ribbon)、和環狀大軌道(Orbit Inner和Orbit Outer)。

這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述

這些都是使用MaterialGear來配合材質的。下面是光柱(Pillars)的面板:

這裏寫圖片描述

它使用了3個材質,其中第二個材質YellowSurface和第三個材質RedSurface使用了自定義的自發光Custom/Untextured Emmisive Surface,這個shader其實就是一個有最簡單自發光效果的surface shader,它的自發光大小是靠屬性_Amplitude控制的:

o.Emission = _Emission * _Amplitude;
  • 1

爲了讓自發光大小隨着音樂變化,這裏使用了兩個MaterialGear,分別對應一個材質。爲了讓兩個材質的變化不要徹底一致,這裏把它們的Reaktor來源設成了不一樣的模式。MaterialIndex用於指定是做用於當前的第幾個材質,後面的TargetType和TargetName是設置的屬性,FloatCurve是可讓咱們進一步對輸入信號進行加工。

舞臺音響

舞臺音響也是個頗有特點的效果。它的音波(其實就是不少圓圈)會隨着音樂忽大忽小。

這裏寫圖片描述 這裏寫圖片描述

這個就是經過AnimatorGear來觸發Animator裏面的狀態來實現的。

這裏寫圖片描述

酷炫的地板

Unity Chan腳下的地板(Visualizer)特效非常酷炫,一會畫圈圈一會畫蜂巢的,還能隨着音樂變化,頗有意思。

Visualizer大概是這裏面最複雜的一個。做者不只爲它自定義了音頻信號處理腳本,它使用的shader也比較複雜,還用到了額外的渲染紋理來實現反射效果(能夠從下圖的材質上看到有些許舞臺反射效果)。

這裏寫圖片描述

Visualizer.cs腳本仍是比較簡單的,它聲明瞭四個用於鏈接Reaktor的ReaktorLink,分別對應了MusicPlayer中的四個Reaktor。每次Update時,它從ReaktorLink.Output獲得四個音頻信號,再在OnWillRenderObject中、在渲染該物體以前,把信號傳遞給本身的材質,並找到渲染物體的攝像機,把該攝像機的視角-投影矩陣的逆矩陣傳給材質,這主要是爲了根據反射的深度圖重建每一個點的世界座標,再根據座標的高度值(y)來計算一個反射程度的衰減值。

另外一個腳本MirrorReflection比較複雜,負責渲染反射的彩色紋理和深度紋理。有興趣的能夠仔細看下,大概就是在地板附近放一個攝像機,而後設置它的各個矩陣和狀態,獲得兩張渲染紋理,再傳遞給材質。

Visualizer.shader也比較複雜,感受性能堪憂,居然仍是用surface shader寫的。Anyway,它的那些光圈和格格的效果全是代碼實現的,而後添加到自發光變量上。除了上面的自發光顏色,還添加了舞臺反射的顏色,反射點距離地板越遠,反射強度越弱。此外,還使用了模糊技術,取了9個採樣點平均後做爲最終的反射顏色。計算量仍是很大的,優化作的也不是很好,採樣座標的計算等都放到了surf裏計算,並且還有一次矩陣乘法。感興趣的須要本身優化下了。

舞臺前燈

這裏寫圖片描述 這裏寫圖片描述

Unity Chan的舞臺前燈(場景裏的Front Lights和Front Lights Beam物體)雖然不會隨音樂變化,但它用的shader也挺有意思的。Front Lights的顏色(其實就是一個使用了自發光的surface shader)會隨着時間變化,這是靠Animator實現的。而它發出的光(Front Lights Beam)是靠一個椎體實現的,並且看起來好像有飄渺的效果(也有Bloom特效的功勞),這主要是靠Custom/Light Beam來實現的。這個shader是一個雙面半透明的vf shader,包含一個主顏色(控制光的總體顏色)、漸變紋理(控制光由強到弱)、兩張噪聲紋理(控制光的移動效果)、噪聲程度和噪聲速度(控制噪聲的大小和平移速度)。有一些有趣的法線:

  • 計算噪聲紋理的採樣座標時,做者使用了世界空間位置的xy來讓各個前燈的光都不同:

    o.uv1 = wp.xy * _NoiseScale.xy + _NoiseSpeed.xy * _Time.y;
    • 1
  • 計算光的透明度時,做者還使用了一個衰減因子就是觀察方向和法線的角度,當角度在某個區間範圍內該衰減因子爲0。這樣作的目的是爲了讓光錐的邊界更加平滑,這一點很重要。

    float falloff = max(abs(dot(camDir, normal))-0.4, 0.0); falloff = falloff * falloff * 5.0;
    • 1
    • 2

舞臺大屏幕

另外一個挺好的就是後面的大屏幕(Back Screen)。

這裏寫圖片描述

這個確定是經過另外一個攝像機渲染一張渲染紋理獲得的,但上面的屏幕黑條效果使用了Custom/Back Screen的shader。

這裏寫圖片描述

shader仍是很簡單的,就是在主紋理上添加了一個條狀紋理,並使用sin配合lerp函數添加一個不斷閃爍的效果:

float4 frag(v2f i) : COLOR
{
    float4 color = tex2D(_MainTex, i.uv0);

    float amp = tex2D(_StripeTex, i.uv1).r; amp = _BaseLevel + _StripeLevel * amp; float time = _Time.y * 3.14f * _FlickerFreq; float flicker = lerp(1.0f, sin(time) * 0.5f, _FlickerLevel); return color * (amp * flicker); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

其餘

還有一些就不一一寫了。好比攝像機的運動很飄逸啊,這是靠CameraSwitcher.cs在不少個位置之間不斷lerp獲得的;激槍(Laser)發射的效果,是靠Animator實現的;各類撒花(Confetti),是粒子系統。

寫在最後

這個項目還有一個特色就是基本全部的物體都是後來加載到場景的,運行前整個場景基本是空的,做者說這樣有助於多人協做。

關於做者之一的Keijiro Takahashi再多說幾句,Keijiro以前在索尼工做了十年,而後跳到了Unity日本,期間作了大量關於Unity的開源項目,有一些仍是很不錯的~

相關文章
相關標籤/搜索