简单力场护盾效果ASE实现笔记
https://vdn6.vzuu.com/SD/42d88158-3209-11ec-9482-5205fb48cbf7.mp4?pkey=AAXAIWf3cO_MEnH9vjnMdBS2Cj0Gsx_gZ7dVOmdPAwN9kgAmkvxOjauU-0HouER0jkcXjmiA8-kMRg0vz-Ac-OI9&c=avc.0.0&f=mp4&pu=078babd7&bu=078babd7&expiration=1679475988&v=ks6
v1.0 效果圖
著色器部分
著色器部分包括了護盾主要的表現效果和護盾受擊效果。這里主要使用ASE實現,重在講解思路,降低學習成本。
編寫準備
開始正式編寫之前,我們需要首先完成基本開發環境的部署。無需從頭開始的小伙伴可以直接越過這部分內容,從工程文件創建開始瀏覽。
Unity安裝
從Unity官方網站上下載Unity Hub并按照自己需求安裝一個版本。推薦安裝不低于2018的任一LTS版本,就本工程來說,社區版本也是完全足夠的。
具體步驟較為簡單,網絡上教程也比較豐富,這里就不做進一步展開。
ASE插件安裝
如前所說,我們需要安裝ASE插件來創建ASE著色器,以獲得圖形界面支持。Unity的Asset Store里面上架了ASE插件,可以直接從里面獲取。與通常Package的下載相同,點擊Download并下載完成后,點擊Import自動導入即可。
如果是從非Asset Store途徑獲取的ASE,雙擊ASE.unitypackage即可在安裝了Unity的前提下自動導入插件。
ASE插件安裝完成后會彈出ASE初始化界面,關閉即可。
工程文件創建
與創建普通著色器類似,我們依然是在Asset界面使用右鍵菜單創建ASE Shader,ASE插件通過編輯器腳本為我們在右鍵菜單中添加了額外的選項:
選擇Surface來以表面著色器為模板,來創建一個ASE Shader。
創建完畢后將文件名改為ASE_ForceShield(或者是你喜歡的其他名字),我們就完成了工程的準備工作,可以開始正式編寫著色器了。
Albedo&Normal(反射和法線部分)
對于Albedo和Normal,我們不做過多處理,簡單地留出接口并輸入shader即可。如果有需要,可以自行改寫。
Emission(自發光部分)
在這部分,我們將逐個完成護盾的各方面表現效果,并最終將它們組合到一起。
模塊劃分
閉上眼睛,想象一下,一個護盾應該是什么樣的?你能在最近玩過的游戲,看過的影視作品中找到參考嗎?當你確定之后,思考一下,可以把這個效果進行劃分嗎?它由哪些細分效果組成?
在本案例中,我們主要將護盾簡單劃分為護盾波紋,護盾紋理,護盾光暈和護盾受擊四個模塊。通過組合這四個模塊,我們就能夠實現一個最基本的護盾效果。
準備時間參數
如果我們想讓我們的特效動起來,我們就需要一個時間參數,用于標識時間的流逝,并且我們應當能通過一個外接的參數對時間流逝速度進行控制,從而間接地控制動畫播放的速率。
Unity為我們提供了這個基本參數,它是一個由四個浮點數組成的浮點數組。在ASE中我們可以以節點的形式直接引用它,就像在代碼中使用宏。
Time Parameters即時間參數,以秒為單位輸出Unity內部流逝的時間,這個參數組包括4不同的預設縮放值。
序號 | 成員 | 描述 | 類型 |
0 | t/20 | 返回t值的二十分之一放縮值 | Float |
1 | t | 返回t值原始值 | Float |
2 | t*2 | 返回t值的二倍放縮值 | Float |
3 | t*3 | 返回t值的三倍放縮值 |
*部分ASE版本中可能包含一個Output的額外輸出端口,輸出包括所有成員的原始時間向量。
我們首先將節點給出的四個成員重新組合與原始時間向量一致的Float4數組,然后將它與我們定義的參數相乘,最后將輸出結果注冊為本地變量待用。
護盾波紋——外色值光波效果
我們引入紋理坐標節點,通過向這個節點輸入參數來決定我們的護盾網格紋理以什么方式映射到我們的物體上。
在坐標偏移參數中,我們使用了之前準備的時間參數,并對其進行了適當的縮放,作為UV坐標的Y偏移值,使我們的紋理能夠動起來,形成動畫。
Texture Coordinates“紋理坐標”節點(快捷鍵:U鍵)使用網格UV并根據紋理平鋪和偏移參數對其進行操作,以定義如何將紋理映射到3d資產上。如果Tex端口連接到紋理對象,或者如果在節點屬性面板中引用了Tex端口,則它們將通過材質檢查器中的該紋理字段進行轉換。否則,將使用節點的參數或輸入來轉換坐標。
端口 | 描述 | 類型 |
Tex | 該端口接受一個紋理對象,該對象允許使用其紋理UV參數。覆蓋節點填充和偏移量,而改用物料檢查器 | Sampler2D |
Tilling | 參數Tilling的動態版本。僅當Reference設置為None時可用,否則將被鎖定以指示其使用了材質檢查器中的Texture屬性的填充 | Float2 |
Offset | 參數Offset的動態版本。僅當Reference設置為None時可用,否則將被鎖定以指示其使用了材質檢查器中的Texture屬性的偏移 | Float2 |
UV(WT) | 在vector2的情況下,返回分別包含U和V坐標的vector2,vector3或vector4,vector3的UVW坐標,vector4的UVWT | Float2(34) |
可以通過修改Tilling常量的值來決定紋理是否重復拼接;如果將Tilling常量的值設為0,0,紋理事實上將用于修改物體的整體顏色。
護盾網格——外圖案紋理效果
類似地,我們為網格紋理設置動畫效果,并同時引入護盾基色和護盾強度參數。
護盾受擊——護盾沖擊效果
這里我們為了盡可能地簡化系統,僅對護盾受擊效果做了顏色上的簡單模擬,更加深入的內容我們將放在后續筆記中。
總的思路是,使用受擊點位置與頂點位置得出沖擊距離,然后對距離進行判斷,分三段表現受擊效果,各邊界值由參數控制。
首先,我們使用Distance節點獲取受擊點與頂點之間的距離。
DistanceDistance節點輸出兩個值或向量 A和 B之間的歐式距離,可以將其視為以下運算 Sqrt ( Dot (B-A,B-A))。 如果將不同的數據類型連接到每個端口,則將始終對大多數通道的端口類型執行強制轉換。
然后將得出的距離值引入Compare節點,與邊界值進行比較,以決定是否啟用沖擊效果,應用哪種效果。
Compare NodeThe Compare 節點比較其A和B上設置的值,根據運算符類型獲得對應布爾值,并根據該值輸出對應參數
注意:無論 True and False輸入端口可以有不同的數據類型,但投將與渠道的量最多的類型進行。所選類型還將定義輸出類型,并定義在比較操作中將使用的A和B通道數量。
端口 | 描述 | 類型 |
A | 第一個比較值 | Float [1] |
B | 第二個比較值 | Float [1] |
True | 如果邏輯表達式為真,輸出該值 | Float [1] |
False | 如果邏輯表達式為假,輸出該值 | Float [1] |
此外,這里的受擊效果使用的是受擊顏色與頂點顏色的插值,由受擊點逐漸過渡至基色;但如果我們將Lerp節點的輸入對調,只需要一些簡單的調整我們就能實現一個看起來完全不同的效果。
https://vdn6.vzuu.com/SD/d424671e-321b-11ec-9eab-22e7ec068dc6.mp4?pkey=AAWoCrBiCIvpcIYnibTaEMcGC42DFF0T2D-_YTo5cym8iFwyFS3iZnX9J7IzqOgD9TpaWGouWcQJ8Z3Mn7agPGOu&c=avc.0.0&f=mp4&pu=078babd7&bu=078babd7&expiration=1679476107&v=ks6
護盾光暈——菲涅爾邊緣光效果
如果想要讓我們的護盾看起來晶瑩剔透,加一點點邊緣光是個不錯的主意。這里我們使用了Fresnel節點來實現邊緣光效果,并使用參數控制其反射強度。
Fresnel節點的原理是大名鼎鼎的菲涅爾光照模型,描述了光線在不同折射率材料交界處的行為。如果讀者對此節點背后的機理感興趣,可以自行查閱相關資料,這里不過多展開敘述。
Fresnel Node菲涅耳節點輸出菲涅耳效果的結果。它定義了光到達具有不同折射率的兩種材料之間的界面時的行為,反射和折射的量。 該節點在與該反射部分特定的交易,并計算其由下面的表達式定義的菲涅耳反射系數:
Reflection Coefficient = Bias + Scale x ( 1 + N·I )^Power
方程的每個成員都可以修改,但 I 變量除外,該變量定義了從攝像機到對象的入射向量,并在節點內部將其計算為反向的世界方向向量。
端口 | 描述 | 類型 |
Normal | 要使用的法線向量。如果未連接,則將使用Surface World法線 | Float 3 |
Bias | 定義菲涅耳方程式的Bias變量 | Float |
Scale | 定義菲涅耳方程式的Scale變量 | Float |
Power | 定義菲涅耳方程式的冪變量 | Float |
自發光總裝——護盾效果混合
接下來就是激動人心的總裝時刻。在這一部分,我們將把之前制作的模塊效果一一引入并進行混合,以得到最終的護盾效果。
首先,我們將邊緣光與護盾紋理進行疊加。
然后,引入護盾波紋。
需要注意的是,引入時使用的運算符不同,會極大地影響引入結果。讀者可以自行嘗試不同的運算符節點,查看效果。現在我們的護盾效果已經初具雛形,接下來我們要為護盾效果上色,引入護盾基色和受擊效果。
由于受擊效果同樣涉及頂點顏色的變更,所以我們在引入之前,首先對護盾基色和受擊效果進行合并處理。
然后,我們再將其引入到護盾效果上。
接下來,我們需要制造一點層次感。這里使用Depth Fade節點處理過的參數對護盾效果和護盾深度色進行插值,使護盾效果在與其他幾何體交錯時實現顏色的平滑漸變。
值得注意的一點是,Depth Fade本身輸出的值并不是映射在[0,1]內的,因此我們需要一個Clamp對其進行進一步處理,以用于插值。然后將其引入,用于深度色和護盾效果的插值。
Depth FadeDepth Fade 節點輸出一個線性漸變值,表示對象表面與其后面的幾何體之間的距離。漸變范圍或漸變距離可以通過調整Distance參數來設置。
更具體地說,Distance參數的作用是在對象表面與其后面的幾何體之間的距離小于等于Distance值時將其距離一一映射為 [0,1] 范圍內的值。
端口 | 描述 | 類型 |
Vertex Position | 可自定義的頂點位置,默認時使用當前頂點位置 | Float 3 |
Distance | 允許映射的距離上界 | Float |
Out | 輸出的線性漸變值 | Float |
最后一步,引入一個總參數用于控制整體表現,然后我們就可以將整個效果輸出到Emission了!
大功告成!如果讀者正確完成了之前的步驟,應該能獲得以下結果:
細心的讀者可能注意到,在我們的沖擊效果前方還有一個未使用的本地變量。這個變量輸出的是改進后的沖擊效果,在后續筆記中才會涉及。護盾的主體工程已經結束,我們接下來將對透明度進行簡單的處理,并添加一個頂點動畫。
Opacity(透明度部分)
在處理透明度之前,讀者應當檢查自己的Shader配置,確保Blend Mode是Transparent狀態,否則很多節點可能無法正常工作。
然后,我們簡單地加入一個參數用于控制護盾曲面整體的透明度。
上圖中,我們對反照、法線和透明度都只做了預留接口的簡單處理,主要功能模塊集中在Emission部分。下方輸出到頂點偏移接口的正是我們接下來要做的頂點動畫。
Vertex Offset(頂點偏移部分)
在這一部分,我們將實現一個簡單的抖動頂點動畫,讓我們的護盾像布丁一樣看起來富有彈性。
首先,再次引入之前制備的時間參數,并對其進行縮放。
然后,將結果與頂點位置相加。
這個隨時間變化的頂點位置將作為UV坐標供Noise Generator生成我們想要的隨機噪聲值。
Noise Generator“噪聲生成器”節點使用 Type指定的方法根據 UV處指定的值在 [-1 1]范圍內創建 浮動噪聲值。
注意:輸入數據必須在整個幾何圖形上變化,因為相等的值會產生相同的噪聲。一種簡單的方法是將“ 紋理坐標”節點連接到其輸入。
端口 | 描述 | 類型 |
UV | 用于產生噪聲的值。相同的輸入值始終會產生相同的噪聲值。僅在未連接相應的輸入端口時可見。 | Float2/3 |
Scale | 用于縮放通過UV端口給定的輸入的值。僅在未連接相應的輸入端口時可見。 | Float |
參數 | 描述 | 默認值 |
Type | 噪聲生成選項 Simplex 2D:使用Simplex方法從Vector2創建噪聲值 Simplex 3D: 使用Simplex 方法從Vector3創建噪聲值 Gradient: :使用Gradient方法從Vector 2創建噪聲值 | Simplex 2D |
0-1 Range | 如果打開,則輸出值為[0 1]范圍;如果關閉,則為[-1 1]范圍。 | True |
最后,引入一個參數,控制其抖動幅度。
具體控制方式是通過將噪聲重映射至正負參數范圍來控制其所能出現的偏移值范圍。如果一切順利,我們在最終的輸出上能夠看到如下的噪聲:
腳本部分
在這部分中,我們將在腳本實現碰撞檢測、著色器賦值,并基于碰撞檢測實現簡單的射彈,用于受擊效果的測試。
首先,在場景中創建一個球,一個使用我們的護盾著色器的材質,然后將材質賦給這個球,并將球重命名為Force Shield(或者你喜歡的其他名字)。
然后在球上新建一個CS腳本,并重命名為Force Shield Manager。
接下來,我們將著手實現碰撞檢測。
碰撞檢測
碰撞檢測依賴于碰撞盒和剛體。因此,我們首先需要在球上增加一個Rigid Body組件。
在設置中取消了默認勾選的 Use Gravity,并勾選了Freeze Position的所有方向。這是為了更好的觀察效果而進行的處理UNITY提供了預設事件OnCollisionEnter(),這個事件將在掛載物體被其他剛體碰撞時觸發。我們在腳本中公共類下創建該事件:
voidOnCollisionEnter(Collisioncollision){Debug.Log("triggered");}我們可以將另一個擁有Rigid Body的物體扔向掛載了腳本的球,如果console彈出了debug信息,則說明碰撞檢測已經正常運作。
賦值著色器
我們向著色器傳遞參數的方法是通過物體掛載的Material組件的.SetFloat方法,因此我們需要聲明一個材質私有變量,并在Start()中獲取物體掛載的材質:
privateMaterialmat;voidStart(){mat=GetComponent<Renderer>().material;// 儲存掛載的材質引用 }另外我們需要一個參數控制轟擊的強度:
[Range(0,1)]publicfloatbasicImpactFactor=1;privatefloathitTime;//計算當前效果強度這個強度將隨時間衰減,實現受擊效果的淡出:
voidUpdate(){// 受擊效果淡出 if(hitTime>0){hitTime-=Time.deltaTime;if(hitTime<0){hitTime=0;}mat.SetFloat("_HitTime",hitTime);}}為了使之前編寫的護盾受擊效果派上用場,我們需要遍歷collision中的所有接觸點.contacts,為著色器獲取碰撞位置和碰撞強度:
voidOnCollisionEnter(Collisioncollision){foreach(ContactPointcontactincollision.contacts){Debug.Log("triggered");mat.SetVector("_HitPosition",transform.InverseTransformPoint(contact.point));//將受擊點坐標從世界空間坐標系轉換為本地坐標系 hitTime=basicImpactFactor;mat.SetFloat("_HitTime",hitTime);//通過材質傳參 }} 這里需要注意的地方是,這里設置參數所使用的名稱務必與著色器中用于接收撞擊位置的參數名稱保持一致。完成如上腳本后,我們再使護盾球與其他具有剛體的物體碰撞時,就應當能看到護盾受擊效果。
到這里,事實上整個護盾效果的功能我們就已經完成了實現。后面的內容只是為了更好的展示效果而添加的額外內容,并不是必需的組成部分,讀者可以根據自己的需要選擇性閱讀。射彈生命周期
“展示受擊效果不好搞啊,每次都要操作物體撞上去,位置也很難選,不容易看到清晰的展示...”“為什么還要我手動扔啊,煩死了!”
“累了,寫個腳本自己動吧!”
這一部分中,我們將繼續補充之前的腳本,實現射彈的自動發射和生命周期管理,以期獲得更好的展示效果。
在開始之前,我們需要準備一個擁有Rigid Body組件的剛體預制件作為我們的發射物,你可以憑自己的喜好在場景中創建一個3D物件,為它添加Rigid Body組件,并拖入Asset 視窗中,制成Prefab備用。
需要注意的是,射彈通常忽略重力,因此在添加RigidBody組件時需要取消勾選Use Gravity。
此外,我們還需要自定義一個名為Bullet的編輯器自定義標簽,并將Prefab的標簽修改為Bullet,以對射彈進行統一管理。
射彈生成
剛體的創建與Game Object類似,獲取預制體后實例化即可。
打開掛載于護盾球上的腳本,我們編寫一個創建函數用于實例化預制的子彈剛體,并將預制子彈剛體的變量聲明添加到腳本中:
publicRigidbodybulletPrefab;publicfloatbulletCreateSpeed=10;//對外參數,用于控制子彈生成數量 privatefloatcurrentBulletsNum=0;//對內變量,計算當前子彈數量 voidcreateBullets(){Rigidbodybullet=Instantiate<Rigidbody>(bulletPrefab);//定義子彈剛體,然后克隆一個子彈 //此處不用bullet.position,而是bullet.transform.position,兩者有區別 Vector3targetPosition=newVector3(0,0,0);targetPosition=this.transform.position+newVector3(Random.Range(-BulletRandomRange,BulletRandomRange),Random.Range(-BulletRandomRange,BulletRandomRange),Random.Range(-BulletRandomRange,BulletRandomRange));//在物體附近隨機選擇位置 bullet.transform.position=targetPosition;}我們將在Update()函數中調用這個實例化函數。
子彈密度的控制與受擊效果的衰減類似:
voidUpdate(){// 受擊效果淡出 if(hitTime>0){hitTime-=Time.deltaTime*fadeSpeed*hitTime*hitTime/1000;if(hitTime<0){hitTime=0;}mat.SetFloat("_HitTime",hitTime);}// 子彈密度控制 currentBulletsNum-=Time.deltaTime*bulletCreateSpeed;if(currentBulletsNum<=0){createBullets();currentBulletsNum=1;}} 細心的讀者可能會發現控制變量的表意并不是冷卻和密度。這兩個變量事實上是一個采用實體數量控制密度的早期方案的殘余部分。密度設置越高,射彈創建冷卻衰減速度也就越快,創建函數調用也更頻繁,從而生成更密集的射彈。
射彈發射
怎么用石頭擊中遠處的樹干?當然是用力扔。在Unity中,我們可以使用.AddForce()方法對一個具有RigidBody組件的剛體施加一個力,如果這個剛體沒有勾選Freeze選項,那么它將根據自身的Mass和力的施加大小、類型產生相應的速度變化,發生運動。
首先,我們在腳本中聲明一個參數來對力的大小進行控制:
[Range(1,10)]publicfloatmaxBulletsPower=3;然后,我們繼續向createBullets()方法中添加語句:
bullet.AddForce((this.transform.position-bullet.transform.position).normalized*maxBulletsPower,ForceMode.Impulse);//以脈沖形式施加一個力施加的力讓我們創建的射彈能夠向著目標物體運動。換句話說,我們成功向目標物體發射了射彈。
射彈銷毀
任何臨時創建的物體都應當被完善地管理,確保它從創建、使用到銷毀的整個生命周期都是可控的。至少,你得確保它被正確且及時地銷毀了,否則等待著你的就是可怕的泄漏事故。一個臨時創建的物體的銷毀通常由自己搭載的腳本負責,少數情況下,會將銷毀的責任交給其他腳本。這是因為轉交的次數越多,潛在的泄漏風險和性能浪費也就越大。但在我們的場景中,由于射彈沒有使用重力,且場景中唯一的力就是使其向護盾球發射的力,所有的射彈最終都會擊中護盾球,觸發受擊函數。因此,我們選擇直接在護盾球搭載腳本中的受擊函數內進行處理。
我們向OnCollisionEnter函數中添加一個判斷語句:
if(collision.gameObject.tag=="Bullet"){Destroy(collision.gameObject);}這里通過判斷碰撞物體是否具有Bullet標簽來分辨射彈和其他物體,并對擊中自身的射彈執行銷毀。結合上面我們編寫的生成函數,事實上起到了控制同一時間存在在場景內射彈數量的作用。
拓展部分:更好的表現效果
在這個部分,我們將考慮如何改善我們的受擊效果表現。
非線性衰減
在前面的腳本中,我們的受擊效果是線性衰減的,受擊顏色以一個均勻的速度衰減為護盾基色。但真實的波的衰減速度往往和其強度成正相關,強度越高,衰減也隨之越快,這事實上是一個非線性過程。
很容易想到對衰減函數進行改造,使之同樣變為非線性,以盡可能符合預期:
hitTime-=Time.deltaTime*hitTime*100;而非線性的公式需要更大的初始值支持,因此我們將basicImpactFactor的范圍和默認值增大:
[Range(1,100)]publicfloatbasicImpactFactor=10;同時,我們也希望受擊表現能夠更加可控,所以引入了一個額外的參數:
[Range(1,1000)]publicfloatfadeSpeed=1000;這樣,衰減函數則變為:
hitTime-=Time.deltaTime*fadeSpeed*hitTime/10;為了使波形更加陡峭,我們將衰減函數的分母變為平方:
hitTime-=Time.deltaTime*fadeSpeed*hitTime*hitTime/1000;完成后,我們發現受擊效果的變化曲率更加陡峭,徹底淡出的時間也得到了延長。
轟擊強度隨機化
雨天的所有雨滴都是完全一樣的嗎?當然不是。世界上有完全相同的兩片樹葉嗎?當然沒有。
真實的世界里,任何東西都是獨一無二的。
在前面的腳本中,我們的轟擊強度被basicImpactFactor所控制,所有的射彈轟擊的強度和速度都是固定且完全相同的,這讓我們的受擊效果在連續多次播放時顯得毫無生趣。
我們只需要向OnCollisionEnter方法中的hitTime賦值語句內添加一個簡單的參數,就能為轟擊帶來變化:
hitTime=basicImpactFactor*collision.relativeVelocity.magnitude;collision.relativeVelocity.magnitude的作用是獲取撞擊物的撞擊速度向量并轉換為浮點類型的向量長度,所以事實上我們是獲取了每一個射彈的終點速度作為隨機值,而這就要求我們的射彈的初始速度和加速度至少有一個是隨機的。
由于我們的射彈使用了統一的預制件,最簡單的隨機速度方法就是使我們發射射彈時施加的力隨機化:
bullet.AddForce((this.transform.position-bullet.transform.position)*Random.Range(0.1f,maxBulletsPower/3),ForceMode.Impulse);這樣,各個射彈到達護盾時的速度就是基本上隨機的了。將射彈密度調低,讀者應該能很容易觀察到各個射彈轟擊時效果強度的隨機化。
射彈生成位置優化
在前面的腳本中,我們的射彈生成位置是護盾球物體周圍的一個球形空間內的隨機位置,射彈將從四面八方射向護盾球。
但事實上,在攝像機拍攝的畫面中,我們只能看到其中一部分射彈轟擊在護盾球正面的效果,其他地方的射彈轟擊幾乎是完全不可見的,這使得大量的射彈事實上并沒有起到真正有效的表現效果,產生了浪費。
為了改善這一問題,我們對createBullets方法中的語句進行修改:
targetPosition=Camera.main.transform.position+newVector3(Random.Range(-BulletRandomRange,BulletRandomRange),Random.Range(-BulletRandomRange,BulletRandomRange),Random.Range(-BulletRandomRange,BulletRandomRange));//生成中心由物體改為主攝像機這樣可以盡可能地保證射彈轟擊的位置是護盾球的正面。
然而,我們希望主攝像機到物體的距離的調整不會對表現產生太大的影響。在當前情況下,如果生成范圍大于攝像機到護盾球物體的距離,那么一定會出現射彈與主攝像機視線夾角超過90°的情況;并且,有可能發生射彈憑空出現導致的“穿幫"。
因此,我們再在當前的基礎上對生成空間進行位移,確保它位于攝像機正后方:
targetPosition+=(Camera.main.transform.position-this.transform.position).normalized*BulletRandomRange;//基于相對位置方向向量的位移這樣一來,無論我們如何調整范圍,射彈都只會在鏡頭之外生成,并從攝像機后方射向護盾球。同時,轟擊的范圍也更加集中,受范圍縮放的影響程度也降低到了一個可以接受的水平。
https://vdn6.vzuu.com/SD/29dd8dee-321b-11ec-9649-b2a520a92b8f.mp4?pkey=AAUrVng-A6Ffi_DRJNi1JV2_K5Yjn-BKaSMatK8TlP12SU8SjKccIZ-0R0HqlYMnbpPVjxXQjeVVVBEvn_pIOZnP&c=avc.0.0&f=mp4&pu=078babd7&bu=078babd7&expiration=1679476149&v=ks6
改進后的轟擊位置分布
這部分筆記到這里就完全結束了。在后面的筆記中,我們會進一步討論如何實現更好的受擊效果。https://vdn6.vzuu.com/SD/1e525ff8-321c-11ec-bf66-86721c1d7c0e.mp4?pkey=AAVnyfiSSL3i3PpB0qqOCOl5G1htI5EK2gxMX-peS5Zs9b4ag7cxPQJp3VlHqwW45HZgCEBjyei-car14nq6gqQe&c=avc.0.0&f=mp4&pu=078babd7&bu=078babd7&expiration=1679476157&v=ks6
總結
以上是生活随笔為你收集整理的简单力场护盾效果ASE实现笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 九个小众实用设计预览网站
- 下一篇: UI设计师、平面设计师常用的网站大全,初