介紹
是的,這個名字聽起來很奇怪。“運動角色”。那是什麼?該名稱的原因是,當實體引擎問世時,它們被稱為“動态”引擎(因為它們主要處理碰撞響應)。為了使用動态引擎建立角色控制器,已經進行了許多嘗試,但是這并不像看起來那樣容易。Godot是您可以找到的最佳動态角色控制器實作之一(如在2d / platformer示範中所見),但是使用它需要相當水準的技能和對實體引擎的了解(或者非常耐心嘗試錯誤)。
諸如Havok之類的某些實體引擎似乎認為動态角色控制器是最佳選擇,而其他實體引擎(PhysX)則更願意推廣運動學引擎。
那麼差別是什麼呢?:
甲動态字元控制器采用剛性體具有無限慣性張量。這是一個不能旋轉的剛體。實體引擎總是讓物體移動和碰撞,然後一起解決它們的碰撞。如平台遊戲示範所示,這使動态角色控制器能夠與其他實體對象無縫互動。但是,這些互動并非總是可預測的。碰撞可能需要一幀以上的時間才能解決,是以一些碰撞似乎隻位移了一小部分。這些問題可以解決,但需要一定的技能。
一個運動人物控制器被假定為總是在非碰撞狀态開始,并且會一直移動到非沖突狀态。如果它開始處于碰撞狀态,它将嘗試像剛體一樣釋放自身,但這是例外,而不是規則。這使得它們的控制和運動更加可預測且易于程式設計。但是,不利的是,除非手動編寫代碼,否則它們無法直接與其他實體對象進行互動。
這個簡短的教程将集中于運動字元控制器。基本上,這是老式的處理沖突的方式(不一定在幕後變得更簡單,而是被很好地隐藏起來并作為一個很好的簡單API呈現)。
實體過程
為了管理運動體或角色的邏輯,始終建議使用實體過程,因為它在實體步驟之前被調用,并且其執行與實體伺服器同步,也總是被稱為每秒相同的次數。與使用正常過程相比,這使實體和運動計算的工作方式更具可預測性,如果幀率太高或太低,則正常過程可能會出現尖峰或失去精度。
using Godot;
using System;
public class PhysicsScript : KinematicBody2D
{
public override void _PhysicsProcess(float delta)
{
}
}
場景設定
有一些測試,這裡的場景(從tilemap的教程) kbscene.zip。我們将為角色建立一個新場景。使用機器人精靈建立一個這樣的場景:

您會注意到,我們的CollisionShape2D節點旁邊有一個警告圖示。這是因為我們尚未為其定義形狀。在CollisionShape2D的shape屬性中建立一個新的CircleShape2D。單擊轉到其選項,并将半徑設定為30:
注意:如之前在實體教程中所述,實體引擎無法處理大多數形狀的比例(僅碰撞多邊形,平面和線段有效),是以請始終更改形狀的參數(例如半徑),而不是縮放它。運動/剛體/靜态物體本身也是如此,因為它們的比例會影響形狀比例。
現在,為角色建立一個腳本,上面用作示例的腳本應作為基礎。
最後,在tilemap中執行個體化該角色場景,并将其作為主要場景,以便在按下play時運作。
運動學特征
回到角色場景,打開腳本,魔術開始了!運動體預設情況下不執行任何操作,但它具有一個有用的功能,稱為 KinematicBody2D.move_and_collide()。此函數将Vector2用作參數,然後嘗試将該運動應用于運動體。如果發生碰撞,它會在碰撞發生時立即停止。
是以,讓我們向下移動精靈,直到它掉到地上:
using Godot;
using System;
public class PhysicsScript : KinematicBody2D
{
public override void _PhysicsProcess(float delta)
{
// Move down 1 pixel per physics frame
MoveAndCollide(new Vector2(0, 1));
}
}
結果是角色将移動,但在撞擊地闆時會立即停止。太酷了吧?
下一步是将重力添加到混合中,這樣,它的行為就有點像正常遊戲角色:
using Godot;
using System;
public class PhysicsScript : KinematicBody2D
{
const float gravity = 200.0f;
Vector2 velocity;
public override void _PhysicsProcess(float delta)
{
velocity.y += delta * gravity;
var motion = velocity * delta;
MoveAndCollide(motion);
}
}
現在,角色平穩滑落。讓我們在觸摸方向鍵時向左右兩側行走。請記住,所使用的值(至少對于速度而言)是像素/秒。
這可以通過向左和向右按下來增加簡單的步行支撐:
using Godot;
using System;
public class PhysicsScript : KinematicBody2D
{
const float gravity = 200.0f;
const int walkSpeed = 200;
Vector2 velocity;
public override void _PhysicsProcess(float delta)
{
velocity.y += delta * gravity;
if (Input.IsActionPressed("ui_left"))
{
velocity.x = -walkSpeed;
}
else if (Input.IsActionPressed("ui_right"))
{
velocity.x = walkSpeed;
}
else
{
velocity.x = 0;
}
// We don't need to multiply velocity by delta because "MoveAndSlide" already takes delta time into account.
// The second parameter of "MoveAndSlide" is the normal pointing up.
// In the case of a 2D platformer, in Godot, upward is negative y, which translates to -1 as a normal.
MoveAndSlide(velocity, new Vector2(0, -1));
}
}
https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character