game/godot

Godot3 API - Kinematic Character (2D)

C/H 2018. 11. 8. 08:30

Kinematic Character (2D)

Introduction

Yes, the name sounds strange. “Kinematic Character”. What is that? The reason is that when physics engines came out, they were called “Dynamics” engines (because they dealt mainly with collision responses). Many attempts were made to create a character controller using the dynamics engines but it wasn’t as easy as it seems. Godot has one of the best implementations of dynamic character controller you can find (as it can be seen in the 2d/platformer demo), but using it requires a considerable level of skill and understanding of physics engines (or a lot of patience with trial and error).
네, 이름이 이상하게 들립니다. "키네마 틱 문자". 그게 뭐야? 그 이유는 물리 엔진이 나왔을 때 (주로 충돌 응답을 처리했기 때문에) "동력(Dynamics)"엔진이라고 불렀기 때문입니다. 다이나믹 엔진을 사용하여 캐릭터 컨트롤러를 만들려는 시도가 많이 있었지만 그렇게 쉬운 것은 아니 었습니다. Godot은 (2D/Platformer 데모에서 볼 수 있듯이) 찾을 수있는 동적 캐릭터 컨트롤러의 가장 좋은 구현 중 하나입니다. 하지만 이를 사용하려면 상당한 수준의 물리 엔진에 대한 기술과 이해가 필요합니다 (또는 시행 착오에 대한 많은 인내심이 필요힙니다).

Some physics engines such as Havok seem to swear by dynamic character controllers as the best alternative, while others (PhysX) would rather promote the Kinematic one.
Havok과 같은 일부 엔진은 역동적인 캐릭터 컨트롤러로 최고의 대안이지만, 다른 것들 중 하나인(PhysX) Kinematic을 홍보하려고합니다.

So, what is the difference?:
그래서, 그 차이점은 뭘까? :

  • A dynamic character controller uses a rigid body with infinite inertial tensor. Basically, it’s a rigid body that can’t rotate. Physics engines always let objects collide, then solve their collisions all together. This makes dynamic character controllers able to interact with other physics objects seamlessly (as seen in the platformer demo), however these interactions are not always predictable. Collisions also can take more than one frame to be solved, so a few collisions may seem to displace a tiny bit. Those problems can be fixed, but require a certain amount of skill.
    동적 캐릭터 컨트롤러는 무한 관성 텐서(tensor: 공간 좌표의 함수 인 구성 요소의 배열로 표현되는 벡터와 유사한 수학적 객체)가 있는 강체(rigid body)를 사용합니다. 기본적으로 회전 할 수없는 강체입니다. 물리(Physics) 엔진은 항상 객체가 충돌하게하고 충돌을 모두 해결합니다. 따라서 동적 캐릭터 컨트롤러는 다른 물리 객체와 원활하게 상호 작용할 수 있지만 (플랫폼 데모에서 볼 수 있듯이) 이러한 상호 작용은 항상 예측 가능하지는 않습니다. 충돌은 해결해야 할 프레임을 두개 이상 가질 수 있으므로 약간의 충돌이 조금씩 옮겨가는 것처럼 보일 수 있습니다. 이러한 문제는 해결 될 수 있지만 일정 수준의 기술이 필요합니다.
  • A kinematic character controller is assumed to always begin in a non-colliding state, and will always move to a non colliding state. If it starts in a colliding state, it will try to free itself (like rigid bodies do) but this is the exception, not the rule. This makes their control and motion a lot more predictable and easier to program. However, as a downside, they can’t directly interact with other physics objects (unless done by hand in code).
    키네메택(기구학적) 문자 컨트롤러는 항상 비 충돌 상태에서 시작하여 항상 충돌하지 않는 상태로 이동합니다. 충돌 상태에서 시작하면, 강체와 같이 스스로 해방하려고 시도하지만 이것은 예외가 아니라 규칙입니다. 이를 통해 제어 및 모션을 예측하고 프로그래밍하기가 훨씬 쉬워집니다. 그러나 단점은 다른 물리 객체와 직접 상호 작용할 수 없다는 것입니다 (직접 코딩하지 않는 한).

This short tutorial will focus on the kinematic character controller. Basically, the oldschool way of handling collisions (which is not necessarily simpler under the hood, but well hidden and presented as a nice and simple API).
이 짧은 튜토리얼은 키네메텍 캐릭터 컨트롤러에 초점을 맞출 것입니다. 기본적으로 충돌을 처리하는 oldschool방식 입니다 (반드시 후드에서는 더 간단하지는 않지만 숨김없이 멋지고 간단한 API로 제공됨). (중요하지 않지만, 더 잘 표현된 쉽고 편한(좋은)) API가 기저에 숨겨져 있다. 로 표현되는 것 같음.)

Physics process

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 KinematicBody2D

func _physics_process(delta):
    pass

Scene setup

To have something to test, here’s the scene (from the tilemap tutorial): kbscene.zip. We’ll be creating a new scene for the character. Use the robot sprite and create a scene like this:
테스트 할 무언가를 얻으려면 여기 타일 맵 튜토리얼의 장면이 있습니다 : kbscene.zip. 우리는 캐릭터의 새로운 장면을 만들어 낼 것입니다. 로봇 스프라이트를 사용하고 다음과 같은 장면을 만듭니다.

You’ll notice that there’s a warning icon next to our CollisionShape2D node, that’s because we haven’t defined a shape for it. Create a new CircleShape2D in the shape property of CollisionShape2D. Click on <CircleShape2D> to go to the options for it, and set the radius to 30:
CollisionShape2D 노드 옆에 경고 아이콘이 있다는 것을 알게 될 것입니다, 왜냐하면 우리가 그것의 모양을 정의하지 않았기 때문입니다. CollisionShape2D의 shape 속성에 새 CircleShape2D를 만듭니다. <CircleShape2D>를 클릭합니다, 옵션으로 이동하여 반지름을 30으로 설정합니다.

Note: As mentioned before in the physics tutorial, the physics engine can’t handle scale on most types of shapes (only collision polygons, planes and segments work), so always change the parameters (such as radius) of the shape instead of scaling it. The same is also true for the kinematic/rigid/static bodies themselves, as their scale affect the shape scale.
참고 : 물리 튜토리얼에서 앞서 언급했듯이 물리 엔진은 대부분의 유형의 모양 (충돌 폴리곤, 평면 및 세그먼트 만 작동)에서 스케일을 처리 할 수 없으므로 스케일링하는 대신에 항상 모양의 매개 변수(예 : 반지름)를 변경하십시오. 키네메틱/릿지/스태틱 개체(bodies) 자체의 스케일이 모양(shape) 스케일에 영향을 미칩니다.

Now create a script for the character, the one used as an example above should work as a base.
이제 캐릭터의 스크립트를 작성하십시오. 위의 예제로 사용 된 스크립트는 기본으로 작동해야합니다.

Finally, instance that character scene in the tilemap, and make the map scene the main one, so it runs when pressing play.
마지막으로, 타일 맵의 캐릭터 장면을 인스턴스화하고 맵 장면을 주 장면으로 만들어 재생을 누를 때 실행됩니다.

Moving the Kinematic character

Go back to the character scene, and open the script, the magic begins now! Kinematic body will do nothing by default, but it has a useful function called KinematicBody2D.move_and_collide(). This function takes a Vector2 as an argument, and tries to apply that motion to the kinematic body. If a collision happens, it stops right at the moment of the collision.
캐릭터 장면(Scene)으로 돌아가서 스크립트(코드)를 열면(Open) 마법이 시작됩니다! 키네마틱 몸체는 기본적으로 아무 것도하지 않지만 KinematicBody2D.move_and_collide()라는 유용한 함수가 있습니다. 이 함수는 Vector2를 인수로 사용하여 해당 동작을 키네메틱 개체에 적용하려고합니다. 충돌이 발생하면 충돌 순간에 바로 멈춥니다.

So, let’s move our sprite downwards until it hits the floor:
바닥에 닿을 때까지 스프라이트를 아래쪽으로 움직여 봅시다:

extends KinematicBody2D

func _physics_process(delta):
	move_and_collide(Vector2(0, 1)) # Move down 1 pixel per physics frame

The result is that the character will move, but stop right when hitting the floor. Pretty cool, huh?
결과는 캐릭터가 움직이지만 바닥에 닿으면 바로 멈추게됩니다.

The next step will be adding gravity to the mix, this way it behaves a little more like an actual game character:
다음 단계는 중력을 추가하고 섞는(mix) 것입니다, 이 방법은 실제 게임 캐릭터와 조금 비슷하게 동작합니다:

extends KinematicBody2D

const GRAVITY = 200.0
var velocity = Vector2()

func _physics_process(delta):
    velocity.y += delta * GRAVITY

    var motion = velocity * delta
	move_and_collide(motion)

Now the character falls smoothly. Let’s make it walk to the sides, left and right when touching the directional keys. Remember that the values being used (for speed at least) is pixels/second.
이제 캐릭터가 부드럽게 떨어집니다. 방향키를 만져(조정)서 좌우로 걸어 보자. 사용되는 값(최소 속도 이상)은 초당 픽셀 수입니다.

This adds simple walking support by pressing left and right:
이것은 왼쪽과 오른쪽을 눌러 간단한 걷기 지원(기능)을 추가합니다.

extends KinematicBody2D

const GRAVITY = 200.0
const WALK_SPEED = 200

var velocity = Vector2()

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

	# We don't need to multiply velocity by delta because MoveAndSlide already takes delta time into account.
	# MoveAndSlide가 이미 델타 시간을 고려하기 때문에 델타로 속도를 곱할 필요가 없습니다.

    # The second parameter of move_and_slide is the normal pointing up.
	# move_and_slide의 두 번째 매개 변수는 위로 향하는 법선입니다.
	# In the case of a 2d platformer, in Godot upward is negative y, which translates to -1 as a normal.
	# 2d 플랫폼의 경우, Godot의 상향은 음수이고, 이는 -1로 평행합니다.
    move_and_slide(velocity, Vector2(0, -1))

And give it a try.
도전

This is a good starting point for a platformer. A more complete demo can be found in the demo zip distributed with the engine, or in the https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character.
이것은 플랫폼 작성자에게 좋은 출발점입니다. 보다 완벽한 데모는 엔진과 함께 배포된 zip 데모 https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character에서 찾을 수 있습니다.

반응형

'game > godot' 카테고리의 다른 글

Godot3 API - Internationalizing games  (0) 2018.11.09
Godot3 API - Physics  (0) 2018.11.08
Godot3 API - Physics introduction  (0) 2018.11.07
Godot3 API - Using KinematicBody2D  (0) 2018.11.06
Godot3 API - Ray-casting  (0) 2018.11.05