Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
키네마틱 캐릭터 (2D)
소개
네, 이름이 이상하네요. "운동학적 캐릭터". 저게 뭐에요? 이름이 붙은 이유는 물리 엔진이 나왔을 때 주로 충돌 반응을 다루었기 때문에 "Dynamics" 엔진이라고 불렀기 때문입니다. 다이나믹스 엔진을 이용하여 캐릭터 컨트롤러를 제작하려는 시도가 많이 있었지만 생각만큼 쉽지는 않았습니다. Godot는 여러분이 찾을 수 있는 최고의 동적 캐릭터 컨트롤러 구현 중 하나를 가지고 있지만(2D/플랫폼 데모에서 볼 수 있듯이), 이를 사용하려면 상당한 수준의 기술과 물리 엔진에 대한 이해가 필요합니다(또는 시행착오에 대한 많은 인내).
Havok과 같은 일부 물리 엔진은 동적 캐릭터 컨트롤러를 최선의 선택으로 맹세하는 반면, 다른 엔진(PhysX)은 운동학 엔진을 선호합니다.
그렇다면 차이점은 무엇입니까?:
**동적 캐릭터 컨트롤러**는 무한 관성 텐서가 있는 강체를 사용합니다. 회전할 수 없는 강체입니다. 물리 엔진은 항상 객체가 움직이고 충돌하도록 한 다음 충돌을 모두 함께 해결합니다. 이를 통해 플랫폼 데모에서 볼 수 있듯이 동적 캐릭터 컨트롤러가 다른 물리 개체와 원활하게 상호 작용할 수 있습니다. 그러나 이러한 상호 작용이 항상 예측 가능한 것은 아닙니다. 충돌을 해결하려면 두 개 이상의 프레임이 필요할 수 있으므로 몇 번의 충돌로 인해 약간의 위치가 바뀌는 것처럼 보일 수 있습니다. 이러한 문제는 고칠 수 있지만 어느 정도의 기술이 필요합니다.
**운동학적 캐릭터 컨트롤러**는 항상 비충돌 상태에서 시작하고 항상 비충돌 상태로 이동한다고 가정합니다. 충돌 상태에서 시작하면 강체처럼 스스로 자유로워지려고 시도하지만 이는 규칙이 아니라 예외입니다. 이를 통해 제어 및 모션을 훨씬 더 예측 가능하고 프로그래밍하기 쉽게 만듭니다. 그러나 단점은 코드에서 직접 수행하지 않는 한 다른 물리 개체와 직접 상호 작용할 수 없다는 것입니다.
이 짧은 튜토리얼에서는 운동학적 캐릭터 컨트롤러에 중점을 둡니다. 이는 충돌을 처리하는 구식 방식을 사용합니다. 이는 내부적으로 반드시 간단하지는 않지만 API로 잘 숨겨져 표시됩니다.
물리학 과정
To manage the logic of a kinematic body or character, it is always advised to use physics process, because it's called before physics step and its execution is in sync with physics server, also it is called the same amount of times per second, always. This makes physics and motion calculation work in a more predictable way than using regular process, which might have spikes or lose precision if the frame rate is too high or too low.
extends CharacterBody2D
func _physics_process(delta):
pass
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
public override void _PhysicsProcess(double delta)
{
}
}
씬 설정
테스트할 내용이 있는 씬(타일맵 튜토리얼에서 제공): kinematic_character_2d_starter.zip. 캐릭터에 대한 새로운 씬을 생성할 것입니다. 로봇 스프라이트를 사용하여 다음과 같이 씬을 만듭니다.
CollisionShape2D 노드 옆에 경고 아이콘이 있음을 알 수 있습니다. 그 이유는 우리가 모양을 정의하지 않았기 때문입니다. 만들기 CollisionShape2D의 모양 속성에 새로운 CircleShape2D가 추가되었습니다. <CircleShape2D>를 클릭하여 해당 옵션으로 이동하고 반경을 30으로 설정합니다.
참고: 앞서 물리 튜토리얼에서 언급했듯이 물리 엔진은 대부분의 모양 유형(충돌 다각형, 평면 및 세그먼트만 작동)의 크기 조정을 처리할 수 없으므로 항상 크기를 조정하는 대신 모양의 매개변수(예: 반지름)를 변경하세요. 크기가 모양 크기에 영향을 미치기 때문에 운동학/강체/정적 몸체 자체의 경우에도 마찬가지입니다.
이제 캐릭터에 대한 스크립트를 생성합니다. 위에서 예시로 사용한 캐릭터가 베이스로 작동해야 합니다.
마지막으로 타일맵에서 캐릭터 씬을 인스턴스화하고 맵 씬을 메인 맵으로 만들어 재생을 누르면 실행됩니다.
키네마틱 캐릭터 이동하기
씬 캐릭터로 돌아가서 스크립트를 열면 마법이 지금 시작됩니다! Kinematic body는 기본적으로 아무 작업도 수행하지 않지만 ``CharacterBody2D.move_and_collide()``라는 유용한 기능이 있습니다. 이 함수는 :ref:`Vector2 <class_Vector2>`을 인수로 사용하고 해당 모션을 운동체에 적용하려고 시도합니다. 충돌이 발생하면 충돌 순간 바로 멈춥니다.
이제 스프라이트가 바닥에 닿을 때까지 아래쪽으로 이동해 보겠습니다.
extends CharacterBody2D
func _physics_process(delta):
move_and_collide(Vector2(0, 1)) # Move down 1 pixel per physics frame
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
public override void _PhysicsProcess(double delta)
{
// Move down 1 pixel per physics frame
MoveAndCollide(new Vector2(0, 1));
}
}
결과적으로 캐릭터는 움직이지만 바닥에 부딪히면 바로 멈춥니다. 정말 멋지죠?
다음 단계는 믹스에 중력을 추가하는 것입니다. 이렇게 하면 일반 게임 캐릭터처럼 동작합니다.
extends CharacterBody2D
const GRAVITY = 200.0
func _physics_process(delta):
velocity.y += delta * GRAVITY
var motion = velocity * delta
move_and_collide(motion)
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
private const float Gravity = 200.0f;
public override void _PhysicsProcess(double delta)
{
var velocity = Velocity;
velocity.Y += (float)delta * Gravity;
Velocity = velocity;
var motion = velocity * (float)delta;
MoveAndCollide(motion);
}
}
이제 캐릭터가 부드럽게 넘어집니다. 방향키를 터치하면 옆, 왼쪽, 오른쪽으로 걷게 만들어 보겠습니다. 사용되는 값(적어도 속도)은 픽셀/초라는 점을 기억하십시오.
이렇게 하면 왼쪽과 오른쪽을 누를 때 걷기에 대한 기본 지원이 추가됩니다.
extends CharacterBody2D
const GRAVITY = 200.0
const WALK_SPEED = 200
func _physics_process(delta):
velocity.y += delta * GRAVITY
if Input.is_action_pressed("ui_left"):
velocity.x = -WALK_SPEED
elif Input.is_action_pressed("ui_right"):
velocity.x = WALK_SPEED
else:
velocity.x = 0
# "move_and_slide" already takes delta time into account.
move_and_slide()
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
private const float Gravity = 200.0f;
private const int WalkSpeed = 200;
public override void _PhysicsProcess(double delta)
{
var velocity = Velocity;
velocity.Y += (float)delta * Gravity;
if (Input.IsActionPressed("ui_left"))
{
velocity.X = -WalkSpeed;
}
else if (Input.IsActionPressed("ui_right"))
{
velocity.X = WalkSpeed;
}
else
{
velocity.X = 0;
}
Velocity = velocity;
// "MoveAndSlide" already takes delta time into account.
MoveAndSlide();
}
}
그리고 한번 시도해 보세요.
이는 플랫포머의 좋은 출발점입니다. 더 완전한 데모는 엔진과 함께 배포된 데모 zip이나 https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character.에서 찾을 수 있습니다.