game/godot

Godot3 API - Physics introduction

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

Physics introduction

In game development you often need to know when two objects in the game intersect or come into contact. This is known as collision detection. When a collision is detected, you typically want something to happen. This is known as collision response.
게임 개발에서는 게임의 두 객체가 교차하거나 접촉 할 때를 종종 알아야합니다. 이를 충돌 감지라고합니다. 충돌이 감지되면 일반적으로 어떤 일이 발생하기를 원합니다. 이를 충돌 응답이라고합니다.

Godot offers a number of collision objects in 2D and 3D to provide both collision detection and response. Trying to decide which one to use for your project can be confusing. You can avoid problems and simplify development if you understand how each works and what their pros and cons are.
Godot은 충돌 감지 및 응답을 제공하기 위해 2D 및 3D에서 여러 가지 충돌 객체를 제공합니다. 프로젝트에 사용할 프로젝트를 결정하는 것은 혼동을 줄 수 있습니다. 각각의 작동 방식과 장점 및 단점을 이해하면 문제를 피하고 개발을 단순화 할 수 있습니다.

In this guide you will learn:
이 가이드에서는 다음 내용을 배우게됩니다.

  • Godot’s four collision object types
    Godot의 네 가지 충돌 객체 유형
  • How each collision object works
    각 충돌 객체의 작동 방식
  • When and why to choose one type over another
    언제 그리고, 왜 다른 유형을 선택해야 하는가?
Note

This document’s examples will use 2D objects. Every 2D physics object and collision shape has a direct equivalent in 3D and in most cases they work in much the same way.
이 문서의 예제는 2D 객체를 사용합니다. 모든 2D 물리 개체 및 충돌 셰이프는 3D에서 직접적으로 동일하며 대부분의 경우 동일한 방식으로 작동합니다.

Collision Objects

Godot offers four kinds of physics bodies, extending CollisionObject2D:
Godot은 CollisionObject2D를 확장하여 4 가지 종류의 물리 구조를 제공합니다.

  • Area2D

    Area2D nodes provide detection and influence. They can detect when objects overlap and can emit signals when bodies enter or exit. An Area2D can also be used to override physics properties such as gravity or damping in a defined area.
    Area2D 노드는 탐지와 영향을 제공합니다. 물체가 겹칠 때이를 감지하고 물체가 들어가거나 나가면 신호를 낼 수 있습니다. Area2D는 정의 된 영역에서 중력이나 댐핑과 같은 물리 속성을 무시하는데도 사용할 수 있습니다.

    The other three bodies extend from PhysicsBody2D:
    다른 세가지 body는 PhysicsBody2D에서 확장됩니다.

  • StaticBody2D

    A static body is one that is not moved by the physics engine. It participates in collision detection, but does not move in response to the collision. They are most often used for objects that are part of the environment or that do not need to have any dynamic behavior.
    정적 body는 물리 엔진에 의해 움직이지 않는 body입니다. 충돌 감지에 참여하지만 충돌에 응답하지 않습니다. 이들은 환경의 일부이거나 동적 인 동작을 필요로하지 않는 객체에 가장 자주 사용됩니다.

  • RigidBody2D

    This is the node that implements simulated 2D physics. You do not control a RigidBody2D directly, but instead you apply forces to it (gravity, impulses, etc.) and the physics engine calculates the resulting movement. Read more about using rigid bodies.
    이것은 시뮬레이트 된 2D 물리를 구현하는 노드입니다. RigidBody2D를 직접 제어하지는 않지만 대신 (힘, 중력 등) 힘을 적용하면 물리 엔진이 결과 운동을 계산합니다. rigid bodies 사용에 대해 자세히 알아보십시오.

  • KinematicBody2D

    A body that provides collision detection, but no physics. All movement and collision response must be implemented in code.
    충돌 감지 기능을 제공하지만 물리 기능은 제공하지 않는 body입니다. 모든 이동 및 충돌 응답은 코드로 구현되어야합니다.

Collision Shapes

A physics body can hold any number of Shape2D objects as children. These shapes are used to define the object’s collision bounds and to detect contact with other objects.
물리 body은 임의의 수의 Shape2D 객체를 자식으로 유지할 수 있습니다. 이 모양은 객체의 충돌 경계를 정의하고 다른 객체와의 접촉을 감지하는 데 사용됩니다.

Note

In order to detect collisions, at least one Shape2D must be assigned to the object.
충돌을 검출하려면, 적어도 1 개의 Shape2D를 객체에 할당되어야 합니다.

The most common way to assign a shape is by adding a CollisionShape2D or CollisionPolygon2D as a child of the object. These nodes allow you to draw the shape directly in the editor workspace.
셰이프(Shape)를 할당하는 가장 일반적인 방법은 개체의 자식으로 CollisionShape2D 또는 CollisionPolygon2D를 추가하는 것입니다. 이 노드를 사용하여 편집기 작업 공간에서 직접 모양을 그릴 수 있습니다.

Important

Be careful to never scale your collision shapes in the editor. The “Scale” property in the Inspector should remain (1, 1). When changing sizing the collision shape, you should always use the size handles, not the Node2D scale handles. Scaling a shape can result in unexpected collision behavior.
편집기에서 충돌 셰이프의 크기를 절대 조정하지 않도록 조심하세요. Inspector의 "Scale"속성은 그대로 남아 있어야합니다 (1, 1). 충돌 셰이프의 크기를 변경할 때 Node2D 배율 핸들이 아닌 항상 크기 핸들을 사용해야합니다. 모양을 확장하면 예상치 못한 충돌 동작이 발생할 수 있습니다.

Physics process callback

The physics engine may spawn multiple threads to improve performance, so it can use up to a full frame to process physics. Because of this, the value of a body’s state variables such as position or linear velocity may not be accurate for the current frame.
물리 엔진은 성능 향상을 위해 여러 스레드를 생성 할 수 있으므로 물리를 처리하기 위해 전체 프레임까지 사용할 수 있습니다. 이 때문에 위치 또는 선형 속도와 같은 body의 상태 변수 값은 현재 프레임에서 정확하지 않을 수 있습니다.

In order to avoid this inaccuracy, any code that needs to access a body’s properties should be run in the Node._physics_process() callback, which is called before each physics step at a constant frame rate (60 times per second by default).
이러한 부정확성을 피하기 위해 body의 속성에 액세스해야하는 모든 코드는 Node._physics_process() 콜백에서 실행해야합니다. 이 콜백은 각 물리 단계 이전에 일정한 프레임 속도(기본적으로 초당 60 회)로 호출됩니다.

Collision Layers and Masks

One of the most powerful but frequently misunderstood collision features is the collision layer system. This system allows you to build up complex interactions between a variety of objects. The key concepts are layers and masks. Each CollisionObject2D has 20 different physics layers it can interact with.
가장 강력하지만 자주 오해되는 충돌 기능 중 하나는 충돌 레이어(Layer) 시스템입니다. 이 시스템을 사용하면 다양한 객체간에 복잡한 상호 작용을 구축 할 수 있습니다. 핵심 개념은 레이어와 마스크입니다. 각 CollisionObject2D에는 상호 작용할 수있는 20 개의 서로 다른 물리 계층이 있습니다.

Let’s look at each of the properties in turn:
각 속성을 차례로 살펴 보겠습니다:

  • collision_layer

    This describes the layers that the object appears in. By default, all bodies are on layer 1.
    이것은 개체가 나타나는 레이어를 설명합니다. 기본적으로 모든 본문은 레이어 1에 있습니다.

  • collision_mask

    This describes what layers the body will scan for collisions. If an object isn’t in one of the mask layers, the body will ignore it. By default, all bodies scan layer 1.
    이것은 신체가 충돌을 검사 할 레이어를 설명합니다. body가 마스크 레이어 중 하나에 없으면 몸체가 마스크 레이어를 무시합니다. 기본적으로 모든 본문은 레이어 1을 검사합니다.

These properties can be configured via code, or by editing them in the Inspector.
이러한 속성은 코드를 통해 구성하거나 Inspector에서 편집 할 수 있습니다.

Keeping track of what you’re using each layer for can be difficult, so you may find it useful to assign names to the layers you’re using. Names can be assigned in Project Settings -> Layer Names.
각 레이어를 사용하고있는 것을 추적하는 것은 어려울 수 있으므로 사용중인 레이어에 이름을 지정하는 것이 유용 할 수 있습니다. 프로젝트 설정 -> 레이어 이름에서 이름을 지정할 수 있습니다.

Example:

You have four node types in your game: Walls, Player, Enemy, and Coin. Both Player and Enemy should collide with Walls. The Player node should detect collisions with both Enemy and Coin, but Enemy and Coin should ignore each other.
게임에는 4 가지 노드 유형 (벽, 플레이어, 적, 동전)이 있습니다. 플레이어와 적 모두 벽과 충돌해야합니다. Player 노드는 Enemy와 Coin의 충돌을 감지해야하지만 Enemy와 Coin은 서로 무시해야합니다.

Start by naming layers 1-4 “walls”, “player”, “enemies”, and “coins” and place each node type in its respective layer using the “Layer” property. Then set each node’s “Mask” property by selecting the layers it should interact with. For example, the Player’s settings would look like this:
먼저 "walls", "player", "enemies"및 "coins"이라는 이름으로 레이어 1-4를 명명하고 "레이어"속성을 사용하여 해당 레이어에 각 노드 유형을 배치합니다. 그런 다음 상호 작용해야하는 계층을 선택하여 각 노드의 "마스크"속성을 설정하십시오. 예를 들어 플레이어의 설정은 다음과 같습니다.

Area2D

Area nodes provide detection and influence. They can detect when objects overlap and emit signals when bodies enter or exit. Areas can also be used to override physics properties such as gravity or damping in a defined area.
영역(Area) 노드는 탐지와 영향을 제공합니다. 물체가 겹칠 때 이를 감지하고 물체가 들어가거나 빠져 나갈 때 신호를 낼 수 있습니다. 또한 Area를 사용하여 정의 된 영역에서 중력이나 댐핑과 같은 물리 속성을 무시할 수 있습니다.

There are three main uses for Area2D:
Area2D에는 크게 세 가지 용도가 있습니다.

  • Overriding physics parameters such as gravity in a given region.
    주어진 영역의 중력과 같은 물리 파라미터를 오버라이드합니다.
  • Detecting when other bodies enter or exit a region or what bodies are currently in a region.
    다른 body가 지역에 출입 할 때 또는 현재 어떤 지역에있는 body가 있는지 감지.
  • Checking other areas for overlap.
    다른 부분에 겹침이 있는지 검사하기.

By default, areas also receive mouse and touchscreen input.
기본적으로 영역에는 마우스 및 터치 스크린 입력도 수신됩니다.

StaticBody2D

A static body is one that is not moved by the physics engine. It participates in collision detection, but does not move in response to the collision. However, it can impart motion or rotation to a colliding body as if it were moving, using its constant_linear_velocity and constant_angular_velocity properties.
정적(스태틱 Static) body는 물리 엔진에 의해 움직이지 않는 body입니다. 충돌 감지에 참여하지만 충돌에 응답하지 않습니다. 그러나 constant_linear_velocity 및 constant_angular_velocity 속성을 사용하여 충돌하는 몸체에 움직임 또는 회전을 전달하는 것처럼 전달할 수 있습니다.

StaticBody2D nodes are most often used for objects that are part of the environment or that do not need to have any dynamic behavior.
StaticBody2D 노드는 환경의 일부이거나 동적 동작을 필요로하지 않는 객체에 가장 자주 사용됩니다.

Example uses for StaticBody2D:
StaticBody2D의 예제 사용:

  • Platforms (including moving platforms)
    플랫폼 (이동 플랫폼 포함)
  • Conveyor belts
    컨베이어 벨트
  • Walls and other obstacles
    벽 및 기타 장애물

RigidBody2D

This is the node that implements simulated 2D physics. You do not control a RigidBody2D directly. Instead you apply forces to it and the physics engine calculates the resulting movement, including collisions with other bodies, and collision responses such as bouncing, rotating, etc.
이것은 시뮬레이트된 2D 물리를 구현하는 노드입니다. RigidBody2D를 직접 제어하지 마십시오. 대신에 힘을 적용하면 물리 엔진이 다른 몸체와의 충돌, 튀는 회전, 회전 등과 같은 충돌 응답을 포함하여 결과 운동을 계산합니다.

You can modify a rigid body’s behavior via properties such as “Mass”, “Friction”, or “Bounce”, which can be set in the Inspector.
Inspector에서 설정할 수있는 "Mass", "Friction"또는 "Bounce"와 같은 속성을 통해 rigid body의 동작을 수정할 수 있습니다.

The body’s behavior is also affected by the world’s properties, as set in Project Settings -> Physics, or by entering an Area2D that is overriding the global physics properties.
본문의 동작은 프로젝트 설정 -> 물리에서 설정 한대로 또는 전역 물리 속성을 재정의하는 Area2D를 입력하여 전 역 속성의 영향을받습니다.

When a rigid body is at rest and hasn’t moved for a time, it goes to sleep. A sleeping body acts like a static body, and its forces are not calculated by the physics engine. The body will wake up when forces are applied, either by a collision or via code.
body가 쉴 때 잠시 움직이지 않으면 잠 들어 버립니다. 수면(sleep) body는 스태틱 body처럼 동작하며 물리 엔진에 의해 힘이 계산되지 않습니다. body는 충돌이나 코드를 통해 힘이 가해질 때 일어납니다.

Rigid body modes

A rigid body can be set to one of four modes:
rigid body는 네 가지 모드 중 하나로 설정 될 수 있습니다 :

  • Rigid - The body behaves as a physical object. It collides with other bodies and responds to forces applied to it. This is the default mode.
    body는 실제 객체(object)로 작동합니다. 그것은 다른 body와 충돌하고 그것에 적용된 힘에 반응합니다. 이것은 기본 모드입니다.
  • Static - The body behaves like a StaticBody2D and does not move.
    본문은 StaticBody2D처럼 작동하고 이동하지 않습니다.
  • Character - Similar to “Rigid” mode, but the body can not rotate.
    "Rigid"모드와 비슷하지만 몸체는 회전 할 수 없습니다.
  • Kinematic - The body behaves like a KinematicBody2D and must be moved by code.
    본문은 KinematicBody2D처럼 동작하며 코드로 이동해야합니다.

Using RigidBody2D

One of the benefits of using a rigid body is that a lot of behavior can be had “for free” without writing any code. For example, if you were making an “Angry Birds”-style game with falling blocks, you would only need to create RigidBody2Ds and adjust their properties. Stacking, falling, and bouncing would automatically be calculated by the physics engine.
rigid body를 사용하면 얻을 수있는 이점 중 하나는 코드를 작성하지 않고도 많은 행동이 "free(기본으로)"로 제공 될 수 있다는 것입니다. 예를 들어 낙하 객체(block)가 있는 "Angry Birds"스타일의 게임을 제작했다면 RigidBody2D를 만들고 속성을 조정하면됩니다. 개체 쌓기(Stacking), 하강fallingl) 및 바운스(개체가 잘 튀는)는 물리 엔진에 의해 자동으로 계산됩니다.

However, if you do wish to have some control over the body, you should take care - altering the position, linear_velocity, or other physics properties of a rigid body can result in unexpected behavior. If you need to alter any of the physics-related properties, you should use the _integrate_forces() callback instead of _physics_process(). In this callback, you have access to the body’s Physics2DDirectBodyState, which allows for safely changing properties and synchronizing them with the physics engine.
그러나 body의 일부 제어하려는 경우 rigid body의 위치, 선형 속도 또는 기타 물리 특성을 변경하면 예기치 않은 동작이 발생할 수 있으므로 주의해야합니다. 물리 관련 속성을 변경해야하는 경우 _physics_process() 대신 _integrate_forces() 콜백을 사용해야합니다. 이 콜백에서는 본문의 Physics2DDirectBodyState에 액세스 할 수 있습니다. 이 속성을 사용하면 속성을 안전하게 변경하고 물리 엔진과 동기화 할 수 있습니다.

For example, here is the code for an “Asteroids” style spaceship:
예를 들어, "소행성"스타일의 우주선에 대한 코드는 다음과 같습니다.

extends RigidBody2D

var thrust = Vector2(0, 250)
var torque = 20000

func _integrate_forces(state):
    if Input.is_action_pressed("ui_up"):
        set_applied_force(thrust.rotated(rotation))
    else:
        set_applied_force(Vector2())
    var rotation_dir = 0
    if Input.is_action_pressed("ui_right"):
        rotation_dir += 1
    if Input.is_action_pressed("ui_left"):
        rotation_dir -= 1
	set_applied_torque(rotation_dir * torque)

Note that we are not setting the linear_velocity or angular_velocity properties directly, but rather applying forces (thrust and torque) to the body and letting the physics engine calculate the resulting movement.
linear_velocity 또는 angular_velocity 속성을 직접 설정하는 것이 아니라 몸체에 힘 (추력 및 토크)을 적용하고 물리 엔진이 결과 운동을 계산하게하는 것에 유의하십시오.

Note

When a rigid body goes to sleep the _integrate_forces() function will not be called. To override this behavior you will need to keep the body awake by creating a collision, applying a force to it, or by disabling the can_sleep property. Be aware that this can have a negative effect on performance.
rigid body가 수면(sleep) 상태가되면 _integrate_forces() 함수가 호출되지 않습니다. 이 동작을 무시하려면 충돌을 만들거나 강제로 적용하거나 can_sleep 속성을 비활성화하여 본문을 깨어있게 유지해야합니다. 이로 인해 성능에 부정적인 영향을 미칠 수 있습니다.

Contact reporting

By default, rigid bodies do not keep track of contacts, because this can require a huge amount of memory if many bodies are in the scene. To enable contact reporting, set the contacts_reported property to a non-zero value. The contacts can then be obtained via Physics2DDirectBodyState.get_contact_count() and related functions.
기본적으로 rigid body는 많은 body가 장면(scene)에있을 경우 엄청난 양의 메모리가 필요할 수 있으므로 contacts접촉)을 추적하지 않습니다. contact(접촉) 보고 기능을 사용하려면 contacts_reported 속성을 0이 아닌 값으로 설정하십시오. contacts는 Physics2DDirectBodyState.get_contact_count() 및 관련 함수를 통해 얻을 수 있습니다.

Contact monitoring via signals can be enabled via the contact_monitor property. See RigidBody2D for the list of available signals.
signals(신호)를 통한 접촉 모니터링은 contact_monitor 특성을 통해 작동 될 수 있습니다. 사용 가능한 신호 목록은 RigidBody2D를 참조하십시오.

KinematicBody2D

KinematicBody2D bodies detect collisions with other bodies, but are not affected by physics properties like gravity or friction. Instead, they must be controlled by the user via code. The physics engine will not move a kinematic body.
KinematicBody2D body는 다른 body와의 충돌을 감지하지만 중력이나 마찰과 같은 물리 특성에 영향을받지 않습니다. 대신 코드를 통해 사용자가 제어해야합니다. 물리 엔진은 kenematic body(운동개체)를 움직이지 않습니다.

When moving a kinematic body, you should not set its position directly. Instead, you use the move_and_collide() or move_and_slide() methods. These methods move the body along a given vector, and it will instantly stop if a collision is detected with another body. After the body has collided, any collision response must be coded manually.
kinematic body를 움직일 때 위치를 직접 설정해서는 안됩니다. 대신 move_and_collide() 또는 move_and_slide() 메서드를 사용합니다. 이 메소드는 주어진 벡터를 따라 몸체를 움직이며 다른 몸체와의 충돌이 감지되면 즉시 멈춥니다. body가 충돌 한 후 충돌 대응을 수동으로 코딩해야합니다.

Kinematic collision response

After a collision, you may want the body to bounce, to slide along a wall, or to alter the properties of the object it hit. The way you handle collision response depends on which method you used to move the KinematicBody2D.
충돌 후 본체가 튀거나 벽을 따라 미끄러지거나 충돌 한 물체의 속성을 변경하려고 할 수 있습니다. 충돌 대응 방법은 KinematicBody2D를 이동하는 데 사용 된 방법에 따라 다릅니다.

move_and_collide

When using move_and_collide(), the function returns a KinematicCollision2D object, which contains information about the collision and the colliding body. You can use this information to determine the response.
move_and_collide ()를 사용하면이 함수는 KinematicCollision2D 객체를 반환합니다. 이 객체에는 충돌 및 충돌 본문에 대한 정보가 들어 있습니다. 이 정보를 사용하여 응답을 결정할 수 있습니다.

For example, if you want to find the point in space where the collision occurred:
예를 들어 충돌이 발생한 공간에서 point(지점)을 찾으려면 다음을 수행하십시오.

extends KinematicBody2D

var velocity = Vector2(250, 250)

func _physics_process(delta):
    var collision_info = move_and_collide(velocity * delta)
    if collision_info:
        var collision_point = collision_info.position

Or to bounce off of the colliding object:
또는 충돌하는 물체로부터 튀어 나오기 :

extends KinematicBody2D

var velocity = Vector2(250, 250)

func _physics_process(delta):
    var collision_info = move_and_collide(velocity * delta)
    if collision_info:
        velocity = velocity.bounce(collision_info.normal)
move_and_slide

Sliding is a common collision response; imagine a player moving along walls in a top-down game or running up and down slopes in a platformer. While it’s possible to code this response yourself after using move_and_collide(), move_and_slide() provides a convenient way to implement sliding movement without writing much code.
슬라이딩(Sliding)은 일반적인 충돌 응답입니다; 플레이어가 하향식(top-down) 게임에서 벽을 따라 움직이거나 platformer에서 위아래로 움직이는 것을 상상해보십시오. move_and_collide()를 사용하면 이 응답을 직접 코딩 할 수 있지만 move_and_slide()는 많은 코드를 작성하지 않고, 슬라이딩 이동을 구현하는 편리한 방법을 제공합니다.

Warning

move_and_slide() automatically includes the timestep in its calculation, so you should not multiply the velocity vector by delta.
move_and_slide()는 자동으로 계산에 타임 스텝을 포함하므로 속도 벡터에 델타를 곱하면 안됩니다.

For example, use the following code to make a character that can walk along the ground (including slopes) and jump when standing on the ground:
예를 들어, 다음 코드를 사용하여지면을 따라 걷거나(경사면 포함), 지면에서 점프 할 수있는 캐릭터를 만드세요.

extends KinematicBody2D

var run_speed = 350
var jump_speed = -1000
var gravity = 2500

var velocity = Vector2()

func get_input():
    velocity.x = 0
    var right = Input.is_action_pressed('ui_right')
    var left = Input.is_action_pressed('ui_left')
    var jump = Input.is_action_just_pressed('ui_select')

    if is_on_floor() and jump:
            velocity.y = jump_speed
    if right:
            velocity.x += run_speed
    if left:
            velocity.x -= run_speed

func _physics_process(delta):
    velocity.y += gravity * delta
    get_input()
    velocity = move_and_slide(velocity, Vector2(0, -1))

See Kinematic Character (2D) for more details on using move_and_slide(), including a demo project with detailed code.
자세한 코드가 포함 된 데모 프로젝트를 포함하여 move_and_slide() 사용에 대한 자세한 내용은 Kinematic Character (2D)를 참조하십시오.

반응형

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

Godot3 API - Physics  (0) 2018.11.08
Godot3 API - Kinematic Character (2D)  (0) 2018.11.08
Godot3 API - Using KinematicBody2D  (0) 2018.11.06
Godot3 API - Ray-casting  (0) 2018.11.05
Godot3 API - InputDefault  (0) 2018.11.02