上一節(jié)給大家介紹了BEPUphysicsint的一些基本的情況,這節(jié)課我們來(lái)介紹它的基本使用,本節(jié)主要從以下5個(gè)方面來(lái)介紹:
(1) 創(chuàng)建一個(gè)物理世界Space蟹漓,并開啟模擬迭代;
(2) 添加一個(gè)物理物體Entity到世界;
(3) 物理引擎的基本處理與操作使用;
(4) 添加靜態(tài)的Mesh形狀的物理物體;
(5) 處理物理事件;
對(duì)惹晋柱,這里有一個(gè)游戲開發(fā)交流小組曙蒸,希望大家可以點(diǎn)擊進(jìn)來(lái)一起交流一下開發(fā)經(jīng)驗(yàn)呀
創(chuàng)建一個(gè)物理世界
在游戲中使用BEPUphysicsint物理引擎,首先要?jiǎng)?chuàng)建一個(gè)物理世界Space(物理空間)鲤屡。所有的物理的物體都加入到這個(gè)物理世界中統(tǒng)一的模擬與迭代老充。在游戲框架初始化的位置进倍,我們來(lái)創(chuàng)建物理世界,代碼很簡(jiǎn)單:
space = new Space();
世界創(chuàng)建出來(lái)后土至,物理的物體就有地方可以放了。世界創(chuàng)建后猾昆,需要模擬迭代物理計(jì)算陶因,所以在游戲框架中的某個(gè)Update/FixedUpdate的地方來(lái)迭代物理世界,代碼很簡(jiǎn)單,調(diào)用space的Update接口就可以了垂蜗。如下:
space.Update();
這個(gè)代碼被調(diào)用后楷扬,物理引擎就開始迭代計(jì)算里面的物理物體了。
物理世界里面的重力默認(rèn)是(0, 0, 0), 我們可以通過(guò)接口來(lái)設(shè)置物理世界的重力,代碼如下:
space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0);
創(chuàng)建物理Entity到物理世界
物理世界創(chuàng)建出來(lái)后贴见,目前世界是空的烘苹,沒(méi)有任何物理Enity,接下來(lái)就是往物理世界里面放一些物理的Entity片部。你可以創(chuàng)建各種不同的物理Entity類型包括有: 長(zhǎng)方體(Box)镣衡、圓柱體(Cylinder)、球體(Sphere)吞琐、膠囊(Capsules)和其它可以在BepupPhysics中找到的實(shí)體類型捆探。你可以右鍵”轉(zhuǎn)到定義”去查看可以支持的類型來(lái)解決問(wèn)題。
所有的物理Entity分為兩種: Dynamic Entity與Kinematic Entity站粟。Dynamic Entity按照物理的方式來(lái)進(jìn)行運(yùn)動(dòng)模擬與迭代包括: 下落, 碰撞,反彈,滑動(dòng)等黍图。Kinematic Entity類似于動(dòng)力學(xué)實(shí)體,但可以認(rèn)為具有無(wú)限質(zhì)量,除非明確的設(shè)置,否則不會(huì)因?yàn)槿魏蔚呐鲎埠拖嗷プ饔昧Χ淖兾锢淼乃俣?大小+方向)奴烙。Kinematic Entity可以理解為是一個(gè)可以推動(dòng)的物體助被,如果兩個(gè)這樣的物體相遇,那么他們會(huì)相互的穿越而過(guò)切诀。
在構(gòu)建Dynamic Entity與Kinematic Entity的時(shí)候揩环,它們構(gòu)建的區(qū)別就在最后一個(gè)參數(shù), Dynamic Entity有物體質(zhì)量mass,而Kinematic Entity沒(méi)有質(zhì)量。當(dāng)Entity構(gòu)建出來(lái)以后幅虑,也可以調(diào)用接口BecomeKinematic/BecomeDynamic 來(lái)改變Entity的類型丰滑。
Kinematic Entity可以在游戲中用于靜態(tài)物體與結(jié)構(gòu)形狀物體(如:地形),我們可以創(chuàng)建一個(gè)Box的Kinematic Entity,來(lái)作為我們的地面Ground,代碼如下:
Box ground = new Box(Vector3.Zero, 30, 1, 30);
第一個(gè)參數(shù)是物理地面在物理世界space中的位置倒庵。后面三個(gè)參數(shù)分別為Box物體的長(zhǎng)褒墨,高炫刷,寬。創(chuàng)建出來(lái)后郁妈,我們把地面加入到物理世界進(jìn)行迭代模擬浑玛,代碼如下:
space.Add(ground);
接下來(lái)我們?cè)偻孛嫔戏乓恍〥ynamic Entity,用來(lái)模擬動(dòng)態(tài)的物體,代碼如下:
space.Add(new Box(new Vector3(0, 4, 0), 1, 1, 1, 1)); space.Add(new Box(new Vector3(0, 8, 0), 1, 1, 1, 1)); space.Add(new Box(new Vector3(0, 12, 0), 1, 1, 1, 1));
由于Dynamic Entity必須要有質(zhì)量mass,所以最后一個(gè)參數(shù)就是質(zhì)量mass噩咪。當(dāng)調(diào)用構(gòu)造函數(shù)時(shí)顾彰,如果有質(zhì)量就會(huì)把物理的Entity認(rèn)為是Dynamic,否則就是Kinematic。
我們構(gòu)建出來(lái)物理世界+物理Entity以后胃碾,我們的物理世界就會(huì)在重力等作用下迭代出當(dāng)前物理世界最新的狀態(tài)與變化涨享。
物理引擎的基本處理與操作使用
我們創(chuàng)建出物理世界,往里面加入物體Entity后仆百,物理世界迭代起來(lái)了灰伟,但是對(duì)于畫面來(lái)說(shuō)什么都看不見,接下來(lái)我們就是要同步儒旬。如何把物理引擎能和”圖像視覺(jué)”同步呢?其實(shí)就是在Update里面帖族,實(shí)時(shí)的把物理Entity里面的postion, rotation, scale同步到游戲物體中的Transform組件里面栈源。獲取物理Entity的位置代碼如下:
Matrix worldMatrix = Transform * entity.WorldTransform;
這里要注意,物理的中心最好要與圖像節(jié)點(diǎn)節(jié)點(diǎn)的中心保持一致竖般,這樣我們就可以獲得Entity的Transform數(shù)據(jù)同步到wolrdMatrix甚垦。
當(dāng)我們的圖像同步做好以后,我們只要控制物理Entity,就能帶動(dòng)圖像節(jié)點(diǎn)移動(dòng)了涣雕,我們來(lái)看下如何給物理Entity一個(gè)線性速度代碼如下:
toAdd.LinearVelocity = Entity.Forward * 10;
上面的代碼為給物理Entity一個(gè)方向?yàn)閒orward,大小為10的線性速度,這樣物理世界就會(huì)模擬迭代entiy變化艰亮,同時(shí)update同步給圖像節(jié)點(diǎn),這樣圖像節(jié)點(diǎn)就飛出去了挣郭。
Mesh形狀的物理Entity
在很多物理Entity中,有一個(gè)比較特殊迄埃,叫做StaticMesh, 一般我們用來(lái)模擬復(fù)雜物理環(huán)境,它的本質(zhì)就是根據(jù)3D物體的Mesh來(lái)創(chuàng)建一個(gè)物理Entity出來(lái)兑障,形狀和3D Mesh一樣侄非。代碼如下:
Vector3[] vertices;int[] indices;ModelDataExtractor.GetVerticesAndIndicesFromModel(model, out vertices, out indices);var mesh = new StaticMesh(vertices, indices, new AffineTransform(new Vector3(0, -40, 0)));space.Add(mesh);
基于游戲引擎,編寫一個(gè)ModelDataExtractor, 能從模型里面讀出定點(diǎn)數(shù)據(jù)與面的索引,根據(jù)定點(diǎn)與面的索引流译,來(lái)創(chuàng)建出和Mesh形狀一樣的物理Entity逞怨。所以整合到Unity引擎的時(shí)候,我們只要編寫對(duì)應(yīng)的ModelDataExtractor功能既可以很方便的創(chuàng)建出來(lái)StaticMesh 物理Entity了福澡。一般我們把StaticMesh用于部署復(fù)雜物理環(huán)境叠赦。
物理Entity的事件處理
游戲整合好物理引擎以后,接下來(lái)要面對(duì)的就是處理物理事件革砸。物理事件包括了觸發(fā)與碰撞除秀。BEPUphsicsint的物理事件都可以在名字空間: BEPUphysics.Events中找到糯累。為了監(jiān)聽到對(duì)應(yīng)的事件,我們只需要在物理Entity上添加事件回調(diào)就可以了鳞仙,比如寇蚊,我們要添加InitialCollisionDetected事件,代碼如下:
deleterBox.EventManager.InitialCollisionDetected += HandleCollision;
以上面的平面+Box為例,當(dāng)一個(gè)Dynamic Box掉下來(lái)棍好,碰到地面Kinematic后仗岸,我們就可以這樣來(lái)寫回調(diào)函數(shù),代碼如下:
void HandleCollision(EntityCollidable sender, Collidable other, CollidablePairHandler pair){
var otherEntityInformation = other as EntityCollidable;
if (otherEntityInformation != null) {
space.Remove(otherEntityInformation.Entity);
Components.Remove((EntityModel)otherEntityInformation.Entity.Tag);
}}
第一個(gè)參數(shù)sender就是碰撞實(shí)體,本例中就是deleterBox, 第二個(gè)參數(shù)other借笙,于碰撞實(shí)體發(fā)生碰撞的其它物體信息扒怖。第三個(gè)參數(shù)pair, 記錄了兩個(gè)碰撞實(shí)體的碰撞信息,我們可以獲取。
今天的BEPUphysicsint的基本使用和概念就分享到這里业稼,關(guān)注我們盗痒,學(xué)習(xí)如果在Unity中構(gòu)建基于確定性的3D物理引擎BEPUphysicsint。
下節(jié)預(yù)告: 基于BEPUphysicsint整合到Unity項(xiàng)目實(shí)戰(zhàn)