游戲開發中的物理介紹

      網友投稿 885 2022-05-30

      在游戲開發中,您通常需要知道游戲中的兩個對象何時相交或接觸。這就是所謂的碰撞檢測。當檢測到碰撞時,您通常希望發生某些事情。這就是所謂的碰撞響應。

      Godot在2D和3D中提供了許多碰撞對象,以提供碰撞檢測和響應。試圖確定要為您的項目使用哪個選項可能會造成混淆。如果您了解每個工作原理以及各自的優缺點,則可以避免問題并簡化開發。

      在本指南中,您將學習:

      戈多的四種碰撞對象類型

      每個碰撞對象如何工作

      什么時候以及為什么要選擇一種而不是另一種

      ==注意==

      本文檔的示例將使用2D對象。每個2D物理對象和碰撞形狀在3D中具有直接等效的功能,并且在大多數情況下,它們的工作方式幾乎相同。

      碰撞對象

      Godot提供了四種物理體,擴展了CollisionObject2D:

      Area2D

      Area2D節點提供檢測和影響。它們可以檢測物體何時重疊,并可以在物體進入或離開時發出信號。Area2D 還可以使用an來覆蓋定義區域中的物理特性,例如重力或阻尼。

      其他三個主體擴展了PhysicsBody2D:

      StaticBody2D

      靜態物體是物理引擎不會移動的物體。它參與碰撞檢測,但不會響應碰撞而移動。它們最常用于環境中的對象或不需要任何動態行為的對象。

      RigidBody2D

      這是實現模擬2D物理的節點。您無需RigidBody2D直接控制a ,而是要對其施加力(重力,脈沖等),然后物理引擎將計算最終的運動。閱讀更多有關使用剛體的信息。

      KinematicBody2D

      提供碰撞檢測但沒有物理學的物體。所有運動和碰撞響應都必須用代碼實現。

      碰撞形狀

      物理物體可以將任意數量的Shape2D對象作為子對象。這些形狀用于定義對象的碰撞范圍并檢測與其他對象的接觸。

      ==注意==

      為了檢測碰撞,Shape2D必須至少分配一個對象。

      分配形狀的最常見方法是添加CollisionShape2D 或CollisionPolygon2D作為對象的子級。這些節點允許您直接在編輯器工作區中繪制形狀。

      重要

      注意不要在編輯器中縮放碰撞形狀。 檢查器中的“比例”屬性應保留為(1,1)。

      更改碰撞形狀的大小時,應始終使用大小控制柄,而不是Node2D比例控制柄。 縮放形狀會導致意外的碰撞行為。

      物理過程回調

      物理引擎可以產生多個線程以提高性能,因此它最多可以使用一個完整的幀來處理物理。 因此,對于當前幀,身體的狀態變量(例如位置或線速度)的值可能不準確。

      為了避免這種不準確性,任何需要訪問人體屬性的代碼都應在Node._physics_process() 回調中運行,該回調在每個物理步驟之前以恒定幀速率(默認為每秒60次)被調用。該方法將被傳遞一個delta 參數,該參數是一個浮點數,它等于自上一步以來經過的時間(以 秒為單位)。當使用默認的60 Hz物理更新速率時,通常等于0.01666…(但不總是如此,請參見下文)。

      ==注意==

      建議始終delta在物理計算中使用相關參數,以便在您更改物理更新率或玩家的設備無法跟上時,游戲能夠正確運行。

      碰撞層和蒙版

      碰撞層系統是最強大但經常被誤解的碰撞特征之一。該系統使您可以在各種對象之間建立復雜的交互。關鍵概念是圖層 和蒙版。每個CollisionObject2D都有可與之交互的20個不同的物理層。

      讓我們依次查看每個屬性:

      碰撞層

      這描述了對象出現在的層。默認情況下,所有實體都在layer上1。

      碰撞面罩

      這描述了身體將掃描碰撞的層。如果對象不在遮罩層之一中,則主體將忽略它。默認情況下,所有實體都掃描layer 1。

      這些屬性可以通過代碼或在檢查器中編輯來配置。

      跟蹤每個圖層的用途可能很困難,因此您可能會發現為使用的圖層分配名稱很有用。可以在項目設置->圖層名稱中分配名稱。

      GUI示例

      游戲中有四種節點類型:墻,玩家,敵人和硬幣。玩家和敵人都應與墻碰撞。播放器節點應同時檢測到與敵人和硬幣的碰撞,但敵人和硬幣應互相忽略。

      首先命名第1-4層“墻”,“玩家”,“敵人”和“硬幣”,然后使用“層”屬性將每個節點類型放置在其相應的層中。然后通過選擇每個節點應與之交互的層來設置每個節點的“蒙版”屬性。例如,播放器的設置如下所示:

      代碼示例

      在函數調用中,將圖層指定為位掩碼。如果功能默認啟用所有圖層,則圖層蒙版將指定為0x7fffffff。您的代碼可以對圖層蒙版使用二進制,十六進制或十進制表示法,具體取決于您的偏好。

      上面啟用了第1、3和4層的示例的等效代碼如下:

      # Example: Setting mask value for enabling layers 1, 3 and 4 # Binary - set the bit corresponding to the layers you want to enable (1, 3, and 4) to 1, set all other bits to 0. # Note: Layer 20 is the first bit, layer 1 is the last. The mask for layers 4,3 and 1 is therefore 0b00000000000000001101 # (This can be shortened to 0b1101) # Hexadecimal equivalent (1101 binary converted to hexadecimal) 0x000d # (This value can be shortened to 0xd) # Decimal - Add the results of 2 to the power of (layer be enabled-1). # (2^(1-1)) + (2^(3-1)) + (2^(4-1)) = 1 + 4 + 8 = 13 pow(2, 1) + pow(2, 3) + pow(2, 4)

      Area2D

      區域節點提供檢測和影響。它們可以檢測物體何時重疊并在物體進入或離開時發出信號。區域還可以用于覆蓋定義區域中的物理屬性,例如重力或阻尼。

      Area2D有三個主要用途:

      給定區域中的替代物理參數(例如重力)。

      檢測其他物體何時進入或離開區域或當前區域中有哪些物體。

      檢查其他區域是否重疊。

      默認情況下,區域還接收鼠標和觸摸屏輸入。

      StaticBody2D

      靜態物體是物理引擎不會移動的物體。它參與碰撞檢測,但不會響應碰撞而移動。但是,它可以利用其和屬性為碰撞的物體提供運動或旋轉,就好像它在運動一樣。constant_linear_velocityconstant_angular_velocity

      StaticBody2D 節點最常用于環境中的對象或不需要任何動態行為的對象。

      示例用于StaticBody2D:

      平臺(包括移動平臺)

      輸送帶

      墻壁和其他障礙

      RigidBody2D

      這是實現模擬2D物理的節點。您不能直接控制 RigidBody2D。取而代之的是,您對其施加力,然后物理引擎會計算出最終的運動,包括與其他物體的碰撞以及碰撞響應(如彈跳,旋轉等)。

      您可以通過“質量”,“摩擦”或“彈跳”之類的屬性來修改剛體的行為,這些屬性可以在檢查器中設置。

      人體的行為也會受到世界屬性(如在“ 項目設置”->“物理”中設置的)的影響,或者受輸入 覆蓋全球物理屬性的Area2D的影響。

      當剛體處于靜止狀態并且一段時間未移動時,它將進入睡眠狀態。睡眠物體的作用類似于靜態物體,其力不是由物理引擎計算的。當通過碰撞或通過代碼施加力時,身體將醒來。

      剛體模式

      剛體可以設置為以下四種模式之一:

      剛性-身體表現為物理對象。它會與其他物體碰撞,并對其施加的力作出反應。這是默認模式。

      靜態-主體的行為類似于StaticBody2D,并且不會移動。

      角色-與“剛性”模式相似,但身體無法旋轉。

      運動-身體的行為類似于KinematicBody2D,必須通過代碼移動。

      使用RigidBody2D

      使用剛體的好處之一是無需編寫任何代碼即可“免費”獲得許多行為。例如,如果您要制作帶有下降塊的“憤怒的小鳥”式游戲,則只需創建RigidBody2Ds并調整其屬性。堆積,下落和彈跳將由物理引擎自動計算。

      但是,如果你想有過身體有一定的控制,你應該照顧-改變position,linear_velocity,剛體的或其他物理性質可能會導致意外的行為。如果您需要更改任何與物理學相關的屬性,則應使用_integrate_forces() 回調而不是_physics_process()。在此回調中,您可以訪問人體的Physics2DDirectBodyState,它可以安全地更改屬性并將其與物理引擎同步。

      例如,以下是“小行星”式太空飛船的代碼:

      class Spaceship : RigidBody2D { private Vector2 _thrust = new Vector2(0, 250); private float _torque = 20000; public override void _IntegrateForces(Physics2DDirectBodyState state) { if (Input.IsActionPressed("ui_up")) SetAppliedForce(_thrust.Rotated(Rotation)); else SetAppliedForce(new Vector2()); var rotationDir = 0; if (Input.IsActionPressed("ui_right")) rotationDir += 1; if (Input.IsActionPressed("ui_left")) rotationDir -= 1; SetAppliedTorque(rotationDir * _torque); } }

      請注意,我們不是 直接設置linear_velocity或angular_velocity屬性,而是將力(thrust和torque)施加到物體上,然后讓物理引擎計算出所產生的運動。

      注意

      當剛體進入睡眠狀態時,_integrate_forces()

      將不會調用該功能。要覆蓋此行為,您將需要通過創建碰撞,向其施加力或禁用can_sleep

      屬性來使身體保持清醒狀態。請注意,這可能會對性能產生負面影響。

      聯系人報告

      默認情況下,剛體不跟蹤接觸,因為如果場景中有很多剛體,這可能需要大量的內存。若要啟用聯系人報告,請將contacts_reported 屬性設置為非零值。然后可以通過Physics2DDirectBodyState.get_contact_count()和相關函數來獲取聯系人 。

      可以通過contact_monitor 屬性啟用通過信號的接觸監視。有關可用信號的列表,請參見RigidBody2D。

      KinematicBody2D

      KinematicBody2D實體可以檢測與其他實體的碰撞,但不受重力或摩擦等物理屬性的影響。相反,它們必須由用戶通過代碼控制。物理引擎不會移動運動體。

      移動運動機構時,請勿position直接設置它。而是使用move_and_collide()ormove_and_slide()方法。這些方法沿著給定的矢量移動物體,如果檢測到與另一個物體的碰撞,它將立即停止。身體碰撞后,任何碰撞響應都必須手動編碼。

      運動碰撞響應

      發生碰撞后,您可能希望身體反彈,沿墻滑動或改變其撞擊的對象的屬性。處理碰撞響應的方式取決于您用來移動KinematicBody2D的方法。

      move_and_collide

      使用時move_and_collide(),該函數返回 KinematicCollision2D對象,該對象包含有關碰撞和碰撞體的信息。您可以使用此信息來確定響應。

      例如,如果要查找空間中發生碰撞的點:

      class Body : KinematicBody2D { private Vector2 _velocity = new Vector2(250, 250); public override void _PhysicsProcess(float delta) { var collisionInfo = MoveAndCollide(_velocity * delta); if (collisionInfo != null) { var collisionPoint = collisionInfo.GetPosition(); } } }

      或從碰撞對象反彈:

      class Body : KinematicBody2D { private Vector2 _velocity = new Vector2(250, 250); public override void _PhysicsProcess(float delta) { var collisionInfo = MoveAndCollide(_velocity * delta); if (collisionInfo != null) _velocity = _velocity.Bounce(collisionInfo.Normal); } } move_and_slide

      滑動是一種常見的碰撞反應。想象一個玩家在自上而下的游戲中沿著墻壁移動,或者在平臺游戲中在斜坡上上下移動。雖然可以使用后,自己編寫這種反應move_and_collide(), move_and_slide()提供了實現滑動,而無需編寫大量代碼的便捷方式。

      警告

      move_and_slide()自動包括在計算中時間步長,所以應該沒有乘法的速度矢量通過delta。

      例如,使用以下代碼制作一個可以在地面上行走(包括斜坡)并在站立在地面上時可以跳躍的角色:

      游戲開發中的物理介紹

      class Body : KinematicBody2D { private float _runSpeed = 350; private float _jumpSpeed = -1000; private float _gravity = 2500; private Vector2 _velocity = new Vector2(); private void GetInput() { _velocity.x = 0; var right = Input.IsActionPressed("ui_right"); var left = Input.IsActionPressed("ui_left"); var jump = Input.IsActionPressed("ui_select"); if (IsOnFloor() && jump) _velocity.y = _jumpSpeed; if (right) _velocity.x += _runSpeed; if (left) _velocity.x -= _runSpeed; } public override void _PhysicsProcess(float delta) { _velocity.y += _gravity * delta; GetInput(); _velocity = MoveAndSlide(velocity, new Vector2(0,-1)); } }

      有關使用的更多詳細信息,請參見運動字符(2D)move_and_slide(),包括帶有詳細代碼的演示項目。

      5G游戲

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Java學習路線-1:編程入門
      下一篇:【圖像分類】實戰——使用VGG16實現對植物幼苗的分類(pytroch)
      相關文章
      亚洲人成777在线播放| 亚洲AV永久精品爱情岛论坛| 亚洲AV无码第一区二区三区| 亚洲一区二区三区影院| 久久久久亚洲AV成人网| 亚洲AV无码乱码在线观看性色扶 | 亚洲精品精华液一区二区| 亚洲人成影院在线高清| 亚洲福利秒拍一区二区| 久久精品国产亚洲AV麻豆网站 | 久久久久无码专区亚洲av| 国产亚洲视频在线观看| 亚洲人成人无码.www石榴 | 亚洲午夜久久久久久久久久| 亚洲综合精品网站| 国产日韩成人亚洲丁香婷婷| 色噜噜AV亚洲色一区二区| 亚洲理论电影在线观看| 亚洲国产精品一区二区久久hs| 久久精品国产亚洲av四虎| 亚洲福利在线观看| 亚洲精品国产福利在线观看| 亚洲免费一级视频| 亚洲一本到无码av中文字幕| 亚洲av永久中文无码精品| 国产午夜亚洲精品不卡电影| 亚洲欧洲精品成人久久奇米网 | 67194在线午夜亚洲| 亚洲中文无码mv| 丰满亚洲大尺度无码无码专线| 婷婷亚洲综合一区二区| 亚洲精品成a人在线观看| 亚洲色偷偷综合亚洲AVYP| 亚洲第一精品在线视频| 亚洲短视频在线观看| 亚洲欧洲日韩极速播放| 亚洲av日韩av永久在线观看 | 亚洲国产夜色在线观看| 亚洲人成网站18禁止| vvvv99日韩精品亚洲| 在线A亚洲老鸭窝天堂|