最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Unity Joint用法及案例

2023-03-21 09:44 作者:程序員-王堅(jiān)  | 我要投稿

什么是Joint

官方文檔介紹
Joint可以連接一個(gè)剛體與 另一個(gè)剛體 或世界空間某點(diǎn),Joint可以通過(guò)施加力的方式來(lái)限制運(yùn)動(dòng),joint中文翻譯可以叫 約束。
在力學(xué)觀點(diǎn)下,運(yùn)動(dòng)分為6個(gè)自由度,沿著xyz軸的位移,繞xyz軸的旋轉(zhuǎn)。
通過(guò)將某些軸的位移和旋轉(zhuǎn)給一些限制條件來(lái)達(dá)到限制剛體運(yùn)動(dòng)的目的。

Unity的Joint實(shí)際就是調(diào)用了NVIDIA PhysX的PxConstraint。

有哪些Joint

PhysX提供了 Fixed Joint,Character Joint、Hinge Joint、Spring Joint等等。
這些種種的Joint其實(shí)都是基于通用的 Configurable Joint調(diào)配參數(shù)封裝出來(lái)的,比如Fixed Joint就是將6自由度運(yùn)動(dòng)全部配置為lock,兩只剛體加上了這個(gè)約束就會(huì)綁定在一起,沒(méi)有任何相對(duì)運(yùn)動(dòng)。


通過(guò)點(diǎn)擊這個(gè)按鈕我們可以看到一些用來(lái)調(diào)節(jié)joint參數(shù)的Gizmos。

Joint計(jì)算原理

在Unity中 Joint是作為Component存在,他必須依附一個(gè)Go,這個(gè)被依附的Go需要有rigidbody,Joint會(huì)影響這個(gè)剛體,
通常我們指定另一個(gè)剛體到ConnectedBody上表示另一個(gè)被Joint影響的剛體,如果想要這個(gè)joint attached 剛體被固定在空間點(diǎn)上,那么conectedBody可以不填。

自由度配置

Joint擁有3個(gè)位移自由度和3個(gè)旋轉(zhuǎn)自由度。相應(yīng)的,在Configurable Joint中對(duì)應(yīng)如下幾個(gè)參數(shù):

  • 位移有 - XMotion、YMotion、ZMotion

  • 旋轉(zhuǎn)有 - AngularXMotion,AngularYMotion,AngularZMotion
    在這6個(gè)自由度上,分配有以下三種配置:

  • ConfigurableJointMotion.Free

  • ConfigurableJointMotion.Locked

  • ConfigurableJointMotion.Limited
    其中Free意味著約束不存在。比如XMotion Free,代表了兩個(gè)剛體在X軸向可以相對(duì)隨意移動(dòng)。
    Locked則表示剛性約束,比如XMotion Locked代表了兩個(gè)剛體在X軸向的相對(duì)位置被完全固定不可改變。(但在實(shí)際物理模擬中是存在被強(qiáng)行拆散可能性的,例如剛體穿插等等,會(huì)導(dǎo)致Solver失敗)
    Limited則意味著有限范圍的偏差。當(dāng)超出有效范圍時(shí),約束將會(huì)開始生效,企圖使兩個(gè)剛體回到正常偏差范圍內(nèi)。

Axis與Anchor

Joint默認(rèn)會(huì)以這個(gè)attach的GO的Transform坐標(biāo)系作為Joint的六自由度坐標(biāo)系,如果我們想要一個(gè)另外的坐標(biāo)系,需要填A(yù)xis和SecondAxis,他會(huì)作為這個(gè)body transform的child而存在。

然后是使用Joint是最容易出錯(cuò)的點(diǎn)——Anchor
這里我們畫一幅圖來(lái)說(shuō)明

cubeA 身上放了一個(gè)Joint組件,連接著cubeB,cubeA的anchor放在藍(lán)圈位置,joint的坐標(biāo)系的xy是紅綠線。
anchor實(shí)際上有兩個(gè),一個(gè)連著A 叫Anchor,另一個(gè)連著B,叫ConnectedAnchor,一般我們都會(huì)勾選AutoConfigureConnectedAnchor讓兩個(gè)anchor在一起。
從anchor到A的連線在joint游戲開始時(shí) anchor到重心的距離會(huì)被記錄,可以看做一個(gè)不可變形的剛桿(如果anchor在某個(gè)cubeA的中心那么屬于cubeA到anchor就沒(méi)有鋼桿了),
游戲運(yùn)行時(shí)anchor和conectedanchor會(huì)發(fā)生相對(duì)運(yùn)動(dòng), 以joint坐標(biāo)系為準(zhǔn),這里我們假定沒(méi)有自己配置Axis,那么joint坐標(biāo)系就是A的坐標(biāo)系,
如果此時(shí)我們配置了Joint的XYZ的Motion為lock,其他angular xyz motion為free,并且把A的剛體配置成Kinematic(讓他不受重力下落影響,固定在空中),
那么就會(huì)得到一根鋼桿一頭在藍(lán)圈 一頭在cube的重心的自由旋轉(zhuǎn)運(yùn)動(dòng),拽著A去甩B其實(shí)有點(diǎn)像雙節(jié)棍。

如果我們配置了angular xyz為lock,xyz的motion中某個(gè)軸 比如Y軸為free,那么便可以得到沿著y軸的滑動(dòng)一樣的效果。

通過(guò)對(duì)于不同維度的控制我們可以得到很多不一樣的效果。

Limit與Spring

整個(gè)計(jì)算流程包括三步
1、計(jì)算兩物體軸向距離
2、將軸向距離投影到j(luò)oint空間下
3、調(diào)節(jié)軸向距離滿足joint參數(shù)

如果我們想讓兩個(gè)anchor的某些軸向的位移在一個(gè)范圍里運(yùn)動(dòng),那便可以將這幾個(gè)軸的motion調(diào)整為limit,這種兩個(gè)anchor的距離(注意是距離,算的是兩點(diǎn)作差的值)會(huì)被限制在limit內(nèi),
如果把A固定,B自由下落那么B到了某個(gè)點(diǎn)位就會(huì)啪的一下卡住,好像撞到了地面一樣,實(shí)際上是被Joint拉住了。
如果我們想他在這個(gè)邊緣位置不要這么生硬的停下而是有彈性、柔和一點(diǎn)的運(yùn)動(dòng),那么可以配置spring值。

需要注意的是xyz都是共享一個(gè)limit的,只存在anchor之間 按線運(yùn)動(dòng)、按圓圈運(yùn)動(dòng)、在球體范圍內(nèi)運(yùn)動(dòng)三種情況。
默認(rèn)spring是0,表示沒(méi)有任何彈簧就是一個(gè)很剛性的約束(看起來(lái)非常硬)。
damper標(biāo)志了彈簧震動(dòng)的阻尼系數(shù),阻尼會(huì)根據(jù)剛體運(yùn)動(dòng)速度產(chǎn)生一個(gè)反向的作用力,以降低震動(dòng)的頻率。

angular limit和其spring的配置原理也是一樣的,只不過(guò)是計(jì)算軸向距離變成計(jì)算兩個(gè)rotation的差異,另外angularlimit關(guān)于主軸的計(jì)算可定制性更強(qiáng),可以存在最小負(fù)角和最大正角,其他兩個(gè)軸則定義相對(duì)限制多。
按兩個(gè)方向分別進(jìn)行定義是由現(xiàn)實(shí)意義的,因?yàn)槿说暮芏嚓P(guān)節(jié)都是這樣的。比如你的膝關(guān)節(jié)、肘關(guān)節(jié)都只能往一個(gè)角度彎曲,而不能反向彎曲。這也決定了當(dāng)我們使用Joint來(lái)模擬物理骨骼時(shí),必須正確的分配Joint主軸朝向。
至于為什么不每個(gè)軸都分配最大和最小角度,可能是有數(shù)學(xué)限制吧,這里博主也不知道。

Drive與Target

上述所講的anchor與anchor之間的限制主要還是一種受到外力導(dǎo)致運(yùn)動(dòng)后 應(yīng)該怎么限制運(yùn)動(dòng),
其實(shí)Joint還提供了一種內(nèi)力驅(qū)動(dòng)來(lái)讓Joint對(duì)兩個(gè)剛體產(chǎn)生力,很多的結(jié)構(gòu)比如挖掘機(jī)旋轉(zhuǎn)關(guān)節(jié),車輪的懸掛系統(tǒng)都會(huì)輸出一些內(nèi)部的力對(duì)外做功。
要配置這些力我們就要用到Drive和Target。
首先一般用drive的軸的自由度配置都會(huì)配成free,然后通過(guò)配置target position、target rotation來(lái)對(duì)兩anchor連接的剛體施加力。
主要分為幾個(gè)步驟
1、計(jì)算兩個(gè)剛體的坐標(biāo)差異
2、將差異投影到j(luò)oint坐標(biāo)系
3、計(jì)算差異和配置的target的距離
4、為了讓距離滿足0,會(huì)對(duì)兩剛體求解施加力

PositionRelative = PositionOfConnected - PositionOfBinded ErrorOfPosition = TargetPosition - PositionRelative F = Spring * ErrorOfPosition - Damp * Velocity

  • PositionOfBinded為Joint所綁定的剛體Anchor位置

  • PositionOfConnected為另一個(gè)連接的剛體的Anchor位置

  • PositionRelative為當(dāng)前兩者位置之差,而TargetPosition則為預(yù)期之差

  • ErrorOfPosition為預(yù)期和當(dāng)前的差項(xiàng),Joint將根據(jù)這個(gè)差項(xiàng)產(chǎn)生一個(gè)彈性力作用于兩個(gè)剛體,使得PositionRelative在迭代中逼近TargetPosition

關(guān)于Rotation
差異和target 計(jì)算的部分包括:

ErrorOfRotation = TargetRotation - (RotationRelative - RotationRelativeInited)

  • RotationOfBinded為Joint所綁定剛體的旋轉(zhuǎn)量

  • RotationOfConnected為連接剛體的旋轉(zhuǎn)量

  • RotationRelative = RotationOfConnected - RotationOfBinded 為兩者之差,也可以理解為Connected相對(duì)于Binded的旋轉(zhuǎn)量。

  • RotationRelativeInited為初始情況下的RotationRelative

所有的Drive,都由以下結(jié)構(gòu)構(gòu)成:

  • PositionSpring - 表示驅(qū)動(dòng)力的彈性系數(shù)

  • PositionDamper - 表示驅(qū)動(dòng)力的阻尼系數(shù)

  • MaximumForce - 表示最大驅(qū)動(dòng)力值。即意味著F不隨著Error無(wú)限增大
    利用以上的定義,將會(huì)使用以下公式產(chǎn)生彈性力:
    Fdrive=Spring?E?Damp?dE/dtFdrive=Spring?E?Damp?dE/dt
    E代表了當(dāng)前狀態(tài)與目標(biāo)狀態(tài)之差。

可以用代碼運(yùn)行時(shí)去修改target position、target rotation來(lái)獲得一些有趣的物理效果。

Joint應(yīng)用案例

講解一個(gè)基于Joint的吊車的實(shí)現(xiàn)

車輪

旋轉(zhuǎn)

車輪我們使用了capsule collider,連接在box拼接的車身的剛體上
然后讓capsule collider關(guān)于軸心方向的軸的旋轉(zhuǎn)是free的,其他旋轉(zhuǎn)都lock,接著我們希望車輪有一點(diǎn)輕微的懸掛系統(tǒng),如果此時(shí)我們把joint組件加在了車輪上,使用車輪坐標(biāo)系,我們會(huì)發(fā)現(xiàn)joint沒(méi)法找到一個(gè)穩(wěn)定的上方向,這導(dǎo)致我們決定將joint加在車身,讓joint坐標(biāo)系跟車身保持一致,維持一個(gè)相對(duì)穩(wěn)定的Joint坐標(biāo)系。

紅色的圓圈表示這個(gè)joint綁定的東西在joint坐標(biāo)系的x軸可以自由的旋轉(zhuǎn)。

這里的anchor配置相當(dāng)重要,anchor位置為車輪的中心在車身坐標(biāo)系下的相對(duì)位置,這里我通過(guò)編輯器寫了一點(diǎn)計(jì)算代碼配置anchor位置。

然后我們通過(guò)控制車輪的x軸角速度便可以實(shí)現(xiàn)一個(gè)摩擦力驅(qū)動(dòng)的車輪了。

懸掛系統(tǒng)

我們xyz的linear motion都是lock住的,這樣遇到一些凸起的路面我們輪子就和車身的相對(duì)距離永遠(yuǎn)不變,這樣不符合真實(shí)的感覺(jué),真實(shí)的感覺(jué)應(yīng)該是輪子會(huì)往上有一點(diǎn)抬升,而車身不會(huì)有y軸方向的運(yùn)動(dòng)。

這里我們的y軸和車身綁定已經(jīng)相當(dāng)穩(wěn)定,我們可以把y軸配置成free,然后把yDrive調(diào)大,target position是000,其實(shí)也就是讓這個(gè)車輪回歸初始位置的意思,這樣當(dāng)車輪支撐車身時(shí)候車身會(huì)有重力影響產(chǎn)生一定的下沉同時(shí)有被舉起的感覺(jué),懸空時(shí)車輪也會(huì)往下掉一點(diǎn),遇到障礙物是壓過(guò)了障礙物的輪子會(huì)比其他輪子往上抬升一點(diǎn)。

總體運(yùn)動(dòng)起來(lái) 車身的震動(dòng)幅度相比沒(méi)有懸掛系統(tǒng)更小一點(diǎn)。

吊臂

旋轉(zhuǎn)

吊車的大臂可以以轉(zhuǎn)臺(tái)為中心來(lái)做旋轉(zhuǎn),我們以y為上方向 配置angular y motion為free,然后在運(yùn)行時(shí)根據(jù)輸入來(lái)配置target rotation,可以實(shí)現(xiàn)大臂繞著一個(gè)點(diǎn)旋轉(zhuǎn),通過(guò)把drive和damp同時(shí)拉大可以獲得一個(gè)有些重量感的吊臂。

抬升

抬升的做法有一點(diǎn)trick,對(duì)于一般的吊車這里通常是液壓的,由下面的淺紅色小臂通過(guò)液壓給力然后把紅色的大臂推出去。大臂配置一個(gè)繞軸旋轉(zhuǎn)。
但是筆者經(jīng)過(guò)嘗試,發(fā)現(xiàn)這種通過(guò)給力的方式在車子運(yùn)動(dòng)起來(lái)的同時(shí)大臂會(huì)搖搖晃晃,因?yàn)槭峭ㄟ^(guò)力來(lái)作用的,就很容易出現(xiàn)彈簧一樣的感覺(jué),并且也不利于控制具體的抬升角度。

于是這里的做法是大臂尾部?jī)蓚€(gè)joint得到一個(gè)繞軸旋轉(zhuǎn),繞軸旋轉(zhuǎn)的joint通過(guò)配置drive 和 target rotation來(lái)讓吊臂產(chǎn)生某個(gè)角度的抬升。

接著我們制作了一個(gè)小臂的一頭連著大臂一頭連著轉(zhuǎn)臺(tái),連著大臂的那端可以沿著小臂軸向有位移,形成了一個(gè)動(dòng)軌滑塊結(jié)構(gòu)。

然后讓這個(gè)小臂對(duì)大臂施加一個(gè)拉力,這個(gè)力往下,而上一個(gè)joint給的力往上,以此可以減少大臂的搖晃感。

吊鉤

伸長(zhǎng)

最后是吊鉤,吊鉤其實(shí)就是讓這個(gè)鉤子可以沿著一條軸伸長(zhǎng),始終日常垂直往下,這里我顯示給鉤子擺了一個(gè)垂直往下的姿勢(shì),y軸向上,然后joint組件添加在鉤子上,anchor一頭綁在吊臂上,一頭綁在吊鉤center,
允許y軸可以free運(yùn)動(dòng),用ydrive來(lái)分離兩個(gè)anchor,驅(qū)動(dòng)吊鉤往下運(yùn)動(dòng),這樣就得到了一個(gè)繞著初始點(diǎn)旋轉(zhuǎn)的一根彈性桿,用來(lái)做伸長(zhǎng)后的吊鉤看起來(lái)還行。

除了這些外,給一些angular的drive并且target rotation配置成000,可以讓吊鉤在空中甩來(lái)甩去時(shí)更快的回到垂直向下的初始旋轉(zhuǎn)位置。

吸附

最后吊鉤要把東西吊起來(lái),可以做一個(gè)范圍檢測(cè),運(yùn)行時(shí)創(chuàng)建一個(gè)lock的joint 把鉤子和被鉤的東西綁在一起,然后再收起吊繩,我們就能吊起東西了!

總結(jié)

對(duì)繩子不太滿意,因?yàn)橛悬c(diǎn)彈性桿的感覺(jué),實(shí)際上這種拉的緊繃的鋼性繩子相當(dāng)難模擬,拉起時(shí)候的感覺(jué)也會(huì)有彈來(lái)彈去的味道,暫時(shí)沒(méi)有想到很好的解決辦法


Unity Joint用法及案例的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
潜山县| 满洲里市| 邓州市| 卢氏县| 渭南市| 黎城县| 唐河县| 乡城县| 德清县| 庄浪县| 彭阳县| 抚顺市| 广德县| 遵义市| 临安市| 海南省| 屯昌县| 隆回县| 荥阳市| 浦县| 确山县| 双江| 芦山县| 临清市| 平阳县| 杂多县| 洛川县| 宁德市| 新田县| 盘山县| 金昌市| 成武县| 大渡口区| 扶余县| 利川市| 祥云县| 厦门市| 郓城县| 鱼台县| 东港市| 名山县|