游戲越來越接近現實的感覺,如果有一個真是的 虛擬現實設備,可能我們真的會感覺是在真實世界。場景的逼真是在渲染效果、角色AI、游戲邏輯、物理效果等等一起導致的結果。現在游戲越來越大,除了渲染,物理估計是最好性能的一部分。在動作游戲中,物體的毀滅和破碎效果,讓戰斗更加的逼真和酣暢淋漓的感覺,這篇文章主要從自己應用的角度來簡單介紹破碎效果的實現。
1 簡單實現
使用maya等3D工具制作碎塊組成的物體,游戲中在物體被打碎的時候,首先銷毀原先的物體,然后再用碎片組成的pretab替換,形成的效果則是每個碎塊的加力方式不同,需要通過調整來實現。可以參考: http://www.cnblogs.com/zsb517/p/3986278.html
注意一下幾個函數的使用:
Rigidbody.AddExplosionForce : 添加爆炸力,力的大小按距離減小
Physics.OverlapSphere : 檢測范圍內的碰撞體列表
下面的代碼測試效果:
void FixedUpdate() { if(Input.GetKeyDown(KeyCode.Space)) { RaycastHit hit; if (Physics.Raycast(Camera.mainCamera.ScreenPointToRay(Input.mousePosition), out hit)) { Debug.Log("AddExplosionForce"); Collider[] hits; hits = Physics.OverlapSphere(hit.point,raduis); foreach(Collider t in hits) { if(t != null && t.attachedRigidbody!=null) t.attachedRigidbody.AddExplosionForce(force,t.attachedRigidbody.position,raduis,ups); //t.attachedRigidbody.AddForce(new Vector3(0f,0f,1f) * 500.0f); } } }分割 }
2 mesh實時分割
使用插件Shatter Toolkit 1.41,實現類似切水果中的效果,可以以點為中心對物體分割成幾個部分或者直接使用平面對物體進行分割,這種方法需要耗費CPU的運算功能,切割時首先根據給的平面方程將物體分割成上兩部分,對處於邊界線上的三角面片需要對頂點,法線,紋理,顏色,切線等進行插值計算,產生新的信息。插件實現了基本的要求,但是如果實現個人具體的效果還是需要對切割前后的事件進行處理和擴展。
使用說明:
當你需要破碎或者分裂物體的時候。你需要在物體上附加一個shattertool腳本實例對象和一個uvmap實例對象,切割之后,物體的碎片將會被實例化為原物體的克隆。
破碎工具腳本需要物體本省含有MeshFilter組件,MeshCollider和Rigidbody組件也是需要的
注意點1:如果你是用meshCollision和剛體組件,需要打開MeshCollider Convex選項,進而避免分裂后組件的質量更新問題
注意點2:如果ShatterTool.FillCut選項被打開,則網格的每個邊屬於兩個三角面片,也就是說網格是封閉的
關於使用:
1 附件 ShatterOnCollision腳本到物體上,通過觸發碰撞來觸發
2 附件鼠標事件到物體上,包括點擊、滑動以及拖拉
3 發送帶有“Shatter”、被分割位置的世界坐標點,觸發shattle tool中的Shatter事件
4 發送"Split"消息,帶有一個世界坐標系中的面序列。觸發shattle tool中的Split事件
5 使用ShatterScheduler事件管理機制,通過添加task的方法發送消息,進而可以控制更多的事件根本
關於鼠標:
1 鼠標點擊后的破碎效果
2 鼠標划線方式切割
3 鼠標拖動效果
關於層級:
HierarchyHandler 腳本可以幫助實現切割中的層析管理
關於效果:
沒做太多處理,可以通過切割前后的消息事件進行處理,類似HierarchyHandler的管理方法,處理切割前和切割后的效果
技術實現:
(1)計算切面
Plane splitPlane = new Plane(Vector3.Normalize(Vector3.Cross(line, ray.direction)), hit.point);
line為世界坐標系中的直線向量--Vector3 line = mainCamera.ScreenToWorldPoint(new Vector3(end.x, end.y, near)) - mainCamera.ScreenToWorldPoint(new Vector3(start.x, start.y, near));
ray.direction為屏幕到切割點的向量--》Ray ray = mainCamera.ScreenPointToRay(Vector3.Lerp(start, end, (float)i / raycastCount));
上面二者叉乘后的結果就是需要平面的法向量,再加上切割墊就可以確定切割平面
(2)單點切割方案:
利用vector生成幾個隨機的面向量,結合切割點形成幾個平面
類似的unity插件:Shatter Toolkit 1.41 ,下載地址:
3 爆破效果(Fracture 最大50塊的分割)
使用插件:Fracturing__Destruction_1.11,這個插件稍微復雜點, 其實基本原理和第一種類似,牛逼的地方在於不需要美術參與碎塊的破裂,插件會首先根據你的設置將物體打碎,生成另外一堆碎塊,並且對碎塊之間的連接關系進行記錄,方便后面實現破碎時的處理。插件的完成性非常好,基本上已經可以像使用粒子一同一樣,通過設置就可以實現一些很好的破碎效果。因為不需要實時的計算碎片,使用中的效果還是可以的,如果需要prefab, 則需要占用點資源罷了。使用前請仔細閱讀的設置面板~~實在太多參數了。具體的使用可以 參考這里
4 粒子效果
總結,主機性能不好的情況下,尤其是GPU性能不強,上述兩種方法產生的碎塊都是剛體性質,爆破過程中都會去利用物理引擎,所以對性能的耗費比較厲害,尤其是碎片比較多的情況下。適當的控制碎片的數目會比較好點
好的效果應該是多種效果的結合,比如破碎后馬上生成粒子效果,不過要人感覺到自然,當然也需要好的機器性能來支撐這些大量的物理計算和渲染。公司的主機性能還是比較差,過多的物理計算和精細的渲染就會造成卡頓。不過說實話,好的游戲並不一定必須非常優秀的視覺效果