天天看點

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

前言         很多童鞋沒有系統的Unity3D遊戲開發基礎,也不知道從何開始學。 為此我們精選了一套國外優秀的Unity3D遊戲開發教程,翻譯整理後放送給大家,教您從零開始一步一步掌握Unity3D遊戲開發。  本文不是廣告,不是推廣,是免費的純幹貨! 本文全名:喵的Unity遊戲開發之路 - 移動 -  遊泳 - 在水中移動和漂浮

遊泳 在水中移動和漂浮

  • 檢測水量。
  • 施加水阻力和浮力。
  • 在水上遊泳,包括上下遊泳。
  • 使物體漂浮。

這是關于控制角色移動的系列教程的第九部分。它可以漂浮在水中并在水中移動。

本教程使用Unity 2019.4.1f建立。它還使用ProBuilder軟體包。

Unity更新

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

我已更新到Unity 2019.4 LTS和ProBuilder 4.2.3版本,是以某些視覺效果已更改。

效果之一

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳
unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

在遊泳池裡玩。

很多遊戲都含有水,而且通常都可以遊泳。但是,沒有針對互動式水的開箱即用的解決方案。PhysX不直接支援它,是以我們必須自己建立一個近似的水。

水景

為了示範水,我建立了一個包含遊泳池的場景。它具有各種岸邊配置,兩個水準面,兩個水隧道,一個水橋以及可以在水底行走的地方。我們的水也可以在任意重力下工作,但是此場景使用簡單的均勻重力。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

遊泳池。

水面由具有半透明藍色材料的單面扁平網制成。從上方可見,但從下方看不到。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

水面。

必須使用設定為觸發器的對撞機來描述水的體積。我在大多數體積中都使用了不帶網孔的箱式對撞機,縮放比例略大于所需的體積,是以水中不會有任何縫隙。一些地方需要更複雜的ProBuilder網格以适合體積。還必須将其設定為觸發器,這可以通過ProBuilder視窗中的“ 設定觸發器”選項來完成。請注意,作為觸發器的網格碰撞器必須是凸形的。凹面網格會自動生成将其包裹起來的凸面版本,但會導緻它戳出所需水量的地方。彎曲的水橋就是一個例子,為此我制作了一個簡化的凸對撞機。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

水對撞機。

忽略觸發器碰撞器

所有水體積對象都在“ 水”層上,應将其排除在運動球體和軌道攝影機的所有層蒙版中。即使到那時,通常我們目前擁有的兩個實體查詢也僅用于正常對撞機,而不是觸發器。可以通過“ 實體/查詢命中觸發器”項目設定來配置是否檢測到觸發器。但是我們永遠都不想使用代碼來檢測觸發器,因為我們現在擁有什麼,是以無論項目設定如何,我們都将其明确化。

第一個查詢在MovingSphere.SnapToGround中。将

QueryTriggerInteraction.Ignore

作為最終參數添加到ray cast。

其次,對OrbitCamera.LateUpdate中BoxCast執行相同操作。

檢測水

現在,我們可以移動水,好像它不存在一樣。但是要支援遊泳,我們必須檢測到它。我們将通過檢查是否在“ 水”層上的觸發區域内來完成此操作。首先,在MovingSphere中添加水面罩以及遊泳材料,我們将用它來證明它在水中。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

水面罩和遊泳材料設定。

然後添加一個

InWater

訓示球體是否在水中的屬性。首先,我們将其設為一個簡單的get / set屬性,并在 

ClearState中

将其重置為

false

如果我們不攀爬,請在Update中使用該屬性選擇中的遊泳材料。

最後,通過添加

OnTriggerEnter

OnTriggerStay

方法完成對水的檢測。它們的工作方式

OnCollisionEnter

OnCollisionStay

相同,不同之處在于它們适用于對撞機,并且具有

Collider

參數而不是

Collision

。兩種方法都應檢查對撞機是否在水層上,如果設定

IsSwimming

true

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

球在水中時是藍色的。

何時調用觸發方法?

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

所有觸發方法都在所有碰撞方法之前被調用。

淹沒

僅僅知道我們的球體是否與水相交,還不足以使其正常遊泳或漂浮。我們需要知道其中有多少被淹沒,然後我們可以用它來計算阻力和浮力。

浸沒程度

讓我們添加一個淹沒浮點字段來跟蹤球體的淹沒狀态。值零表示沒有水接觸,而值1表示完全在水下。然後進行更改

InWater

,使其僅傳回淹沒是否為正。在ClearState中将其設定回零。

更改觸發器方法,以便它們調用新

EvaluateSubmergence

方法,該方法現在僅将淹沒設定為1。

淹沒範圍

我們将使淹沒範圍可配置。這樣,我們可以精确地控制何時球體算在水中以及何時完全浸入水中。我們從球體中心上方的一個偏移點開始測量,一直到最大範圍。這樣一來,即使我們接觸水面,也可以在整個球體進入該區域之前将其完全淹沒,或者完全忽略水坑之類的低水位。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

偏移量和範圍。

使偏移量和範圍可配置。使用0.5和1作為預設值,以比對我們的半徑0.5球體的形狀。範圍應為正。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

淹沒偏移和範圍。

現在,我們必須在

EvaluateSubmergence中

使用水罩執行從偏移點一直向下直至浸入範圍的射線投射。在這種情況下,我們确實想擊中水,請使用

QueryTriggerInteraction.Collide

。然後,浸入等于1減去擊中距離除以範圍。

要測試浸水值,請使用它為球臨時着色。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

淹沒,不正确。

這一直到球體完全浸沒的那一刻起作用,因為從那時起,我們從已經在水對撞器内部的點開始投射,是以射線投射無法擊中它。但這意味着我們已經完全浸入水中,是以我們隻要不打任何東西就可以将浸入設為1。

但是,由于身體位置與PhysX檢測到觸發時的位置不同,是以從水中移出時可能會導緻無效的1淹沒,這是由于碰撞和觸發方法的調用延遲所緻。我們可以通過将射線的長度增加一個機關來防止這種情況。這不是完美的,但幾乎可以解決所有情況,除非移動速度非常快。退出水時,這将導緻浸水變為負值,這很好,因為這不算在水中。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

淹沒,正确。

現在我們可以擺脫淹沒可視化了。

請注意,此方法假定球的中心正下方有水。當球體碰到水體積的側面或底部時(例如,碰到不真實的水牆時),情況可能并非如此。在這種情況下,我們立即進入完全淹沒狀态。

水拖

與水相比,水的運動更為緩慢,因為水比空氣造成更大的阻力。是以,加速明顯較慢,而減速較快。讓我們添加對此的支援,并通過添加水拖動選項(預設設定為1)使其可配置。零到10的範圍是可以的,因為10會引起巨大的阻力。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

水拖。

我們将使用簡單的線性阻尼,類似于PhysX。我們将速度縮放1減去阻力乘以時間增量。在FixedUpdate中調用AdjustVelocity之前進行此操作。我們首先應用阻力,是以總是可以加速。

請注意,這意味着如果水阻力等于1除以固定時間步長,則速度會在單個實體步長中下降為零。如果速度變大,速度将反轉。由于我們将最大值設定為10,是以這不會成為問題。為了安全起見,可以確定速度至少縮放為零。

如果我們沒有完全淹沒,那麼我們就不會遇到最大的阻力。是以,因素會浸入阻尼中。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

水拖10。

浮力

水的另一個重要屬性是事物傾向于将其漂浮在水中。是以,應向我們的球體添加一個可配置的浮力值,該浮力值的最小值為零,預設值為1。該想法是,浮力值為零的物體像石頭一樣下沉,隻是被水拖慢了速度。浮力為1的對象處于平衡狀态,完全消除了重力。浮力大于1的物體會浮到水面。2的浮力意味着它的上升和正常下降一樣快。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

浮力。

我們通過在FixedUpdate中檢查是否不是在攀登但在水中來實作這一點。如果是這樣,請應用按1減去浮力标定的重力,然後再次考慮浸入。這将覆寫重力的所有其他應用。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

浮力1.5。

請注意,實際上向上的力會随着深度的增加而增加,而在我們的情況下,一旦達到最大浸入力,向上的力就保持恒定。這足以産生令人信服的浮力,除非在極深的水中玩耍。

浮力似乎失敗的唯一情況是球體最終距離底部太近。在這種情況下,地面彈跳被激活,抵消了浮力。如果我們在水中,我們可以通過中止SnapToGround來避免這種情況。

遊泳

現在我們可以在水中漂浮了,下一步就是支援遊泳,其中應該包括潛水和浮潛。

遊泳門檻

我們隻有在水深的情況下才能遊泳,但是我們不需要完全浸入水中。是以,讓我們添加一個可配置的遊泳門檻值,該門檻值定義遊泳所需的最小浸入度。它必須大于零,是以使用0.01–1作為其範圍,預設值為0.5。如果球體的至少下半部在水下,則可以使球體遊泳。還添加一個

Swimming

訓示是否達到遊泳門檻值的屬性。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

遊泳門檻值。

在Update進行調整,以便僅在遊泳時使用遊泳材料。

接下來,建立一個

CheckSwimming

方法,該方法傳回我們是否正在遊泳,如果是,則将地面接觸計數設定為零,并使接觸法線等于上軸。

UpdateState中

檢查我們是否接地時,在CheckClimbing之後直接調用該方法。這樣一來,除了攀登外,遊泳淩駕一切。

然後從SnapToGround中取出檢查放在水中。這樣一來,當我們在水中而不是在遊泳時,捕捉動作就會再次起作用。

遊泳速度

添加可配置的遊泳最大速度和加速度,預設情況下均設定為5。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

最大遊泳速度和加速度。

在AdjustVelocity中,檢查爬升後是否在水中。如果是這樣,請使用與通常情況相同的軸使用遊泳加速度和速度。

我們在水中越深,我們應該更多地依賴遊泳的加速度和速度而不是正常的速度和速度。是以,我們将基于遊泳因子在正常值和遊泳值之間進行插值,該因子是淹沒除以遊泳門檻值,且最大值限制為1。

其他加速度是正常加速度還是空氣加速度取決于我們是否在地面上。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

遊泳的; 浮力1.1。

潛水和堆焊

現在,我們可以像在地面或空中一樣在遊泳時移動,是以受控的移動被限制在地面上。垂直運動目前僅是由于重力和浮力。為了控制垂直運動,我們需要第三個輸入軸。通過将UpDown軸添加到我們的輸入設定中(通過複制Horizontal或Vertical)來支援這一點。我将空格(用于跳躍的鍵)用于正鍵,将X用作負鍵。然後将

playerInput

字段更改為一個Vector3,并在遊泳時将其Z分量設定為UpDown軸,否則在Update将其設定為零。從現在開始,我們必須使用的

ClampMagnitude

版本的

Vector3

找到目前和新的Y速度分量,并在AdjustVelocity結尾用它們調整速度。這與X和Z相同,但僅在遊泳時才執行。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

上下遊泳;浮力1。

爬和跳

淹沒時應該很難爬上或跳下。我們可以通過在

Update中

遊泳時忽略玩家的輸入來禁止兩者。必須明确取消攀爬的願望。跳躍會重置自身。如果在下一次更新之前進行了多個實體步驟,則仍然有可能在遊泳時進行攀爬,但這很好,因為在過渡到遊泳的過程中會進行攀爬,是以準确的時間無關緊要。要爬出水面,玩家隻需在按下爬升按鈕的同時向上遊泳,爬升就會在某個時候激活。

雖然站在淺水裡有跳的可能,但這使它變得困難得多。我們通過将跳躍速度減小1減去浸沒除以遊泳門檻值,以最小為零來模拟這一點。

在流水中遊泳

在本教程中,我們将不考慮水流,但是我們應該處理整個運動的水量,因為它們具有動畫效果,就像我們站立或攀爬的正常運動幾何一樣。為了使這種可能成為可能,如果我們結束遊泳,将對撞機傳遞給EvaluateSubmergence并使用其連接配接的剛體。如果我們在淺水中,我們将忽略它。

如果我們連接配接到水體,則不應用EvaluateCollision中的另一個水體代替它。實際上,我們根本不需要任何連接配接資訊,是以我們可以在遊泳時跳過EvaluateCollision所有工作。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

内置動畫水立方;遊泳加速10。

漂浮物

現在我們的球體可以遊泳了,如果有一些漂浮的物體可以互動,那就太好了。再次,我們必須自己對此進行程式設計,方法是将其支援添加到已經支援自定義重力的現有元件中。

淹沒

像一樣

MovingSphere

,向CustomGravityRigidbody中添加submergenceOffset ,submergenceRange ,buoyancy ,waterDrag 和 waterMask ,除了我們不需要遊泳加速度,速度或門檻值之外。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

縮放比例為0.25的多元資料集的淹沒設定。

接下來,我們需要一個淹沒字段。如果需要,在FixedUpdate中施加重力之前将其重置為零。确定淹沒時,我們還需要知道重力,是以也要在野外對其進行跟蹤。

float submergence;  Vector3 gravity;    …    void FixedUpdate () {    …        gravity = CustomGravity.GetGravity(body.position);    if (submergence > 0f) {      submergence = 0f;    }    body.AddForce(gravity, ForceMode.Acceleration);  } 
           

然後添加所需的觸發方法以及

EvaluateSubmergence

方法,該方法的工作原理與以前相同,隻是我們僅在需要時才計算向上軸,并且不支援連接配接的物體。

即使漂浮在水中,物體仍然可以進入睡眠狀态。如果是這種情況,那麼我們可以跳過評估淹沒程度。是以,如果身體正在睡覺,請不要調用OnTriggerStay中的 EvaluateSubmergence 。我們仍然在OnTriggerEnter中這樣做,因為這保證了更改。

漂浮

在FixedUpdate中,必要時應用水的阻力和浮力。在這種情況下,我們通過單獨的

AddForce

調用而不是将其與法向重力結合來應用浮力。

我們還将拖動應用于角速度,以使對象在漂浮時不會保持旋轉。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

浮動的多元資料集。

浮動對象現在可以在浮動時以任意旋轉結束。通常,物體會以最輕的一面朝上的方式漂浮。我們可以通過添加可配置的浮力偏移矢量(預設設定為零)來模拟這一點。

然後,我們通過調用

 AddForceAtPosition

而不是AddForce,在此時應用浮力而不是對象的原點,并将偏移量轉換為單詞空間作為新的第二個參數。

由于重力和浮力現在作用于不同的點,是以它們會産生角動量,進而将偏移點推到頂部。較大的偏移會産生更強的效果,這會導緻快速振蕩,是以應将偏移保持較小。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳
unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

輕微的浮力偏移。

與浮動對象互動

當在其中漂浮着物體的水中遊泳時,軌道錄影機會來回晃動,因為它試圖停留在物體的前面。可以通過添加一個與正常圖層類似的透視圖層來避免這種情況,隻是将軌道錄影機設定為忽略它。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

透明層。

該層僅應用于足夠小以忽略或與之互動的對象。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

推動浮動的東西。

當透視對象遮擋視圖時,我們可以使它們不可見嗎?

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

是的,在這種情況下可以檢測到它,可以用來更改對象的可視化。但是,這不是本教程的一部分。

穩定浮動

我們目前的方法适用于小型物體,但不适用于較大且不均勻的物體。例如,大的浮動塊在球體與其互動時應保持更穩定。為了增加穩定性,我們必須将浮力作用擴充到更大的區域。這需要更複雜的方法,是以

CustomGravityRigidbody

将其複制并重命名為

StableFloatingRigidbody

。用偏移矢量數組替換其浮力偏移。将浸入也轉換為數組,并以

Awake

與偏移數組相同的長度建立它。

進行EvaluateSubmergence調整,以便分别評估所有浮力偏移量的淹沒度。

然後

FixedUpdate中

還要對每個偏移量應用阻力和浮力。阻力和浮力都必須除以偏移量,以使最大效果保持不變。對象所經曆的實際效果取決于淹沒的總數。

通常,對于任何盒子形狀,四個點就足夠了,除非它們很大或經常部分掉出水面。請注意,偏移量随對象縮放。同樣,增加對象的品質使其更穩定。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳
unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

穩定了四個浮力抵消。

意外的懸浮

如果一個點最終在表面上方足夠高,則其光線投射将失敗,這将使其錯誤地算作完全淹沒。對于具有多個浮點的大型物體來說,這是一個潛在的問題,因為有些物體可能最終落在水面之上,而物體的另一部分仍被淹沒。結果将是高峰最終浮空。您可以通過将一個較大的輕物體部分地從水中推出來實作此目的。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

升空後被推。

該問題仍然存在,因為部分物體仍然接觸水。為了解決這個問題,當射線投射無法檢查該點本身是否在水量之内時,我們必須執行一個額外的查詢。可以通過調用

Physics.CheckSphere

位置和小半徑(例如0.01)作為參數,然後調用遮罩和互動模式來完成此操作。僅當該查詢傳回時

true

,我們才應将淹沒設定為1。但是,這可能會導緻大量額外的查詢,是以,通過添加可配置的安全浮動切換項,使其變為可選。僅對于可以充分推入水中的大型物體才需要。

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳
unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

安全浮動。

下一個教程是互動環境。

資源庫(Repository)

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳

https://bitbucket.org/catlikecodingunitytutorials/movement-09-swimming/

往期精選

Unity3D遊戲開發中100+效果的實作和源碼大全 - 收藏起來肯定用得着

Shader學習應該如何切入?

UE4 開發從入門到入土

聲明:釋出此文是出于傳遞更多知識以供交流學習之目的。若有來源标注錯誤或侵犯了您的合法權益,請作者持權屬證明與我們聯系,我們将及時更正、删除,謝謝。

原作者:Jasper Flick

原文:

https://catlikecoding.com/unity/tutorials/movement/swimming/

翻譯、編輯、整理:MarsZhou

More:【微信公衆号】 u3dnotes

unity建立路勁無效_喵的Unity遊戲開發之路 遊泳