_process(delta)나 _physics_process(delta)처럼 _integrate_forces(state)안에서 delta값을 사용하고 싶을 때는 step을 사용한다.


func _physics_process(delta):
	print("Delta: ", delta)

func _integrate_forces(state):
	print("Step: ", state.step) # or print("Get_Step(): ", state.get_step())

1. move_and_slide_snap()함수 추가.

move_and_slide()함수 사용시 Shapping 문제(의도치 않게 경사면 끝자락에서 오브젝트가 날아가는 문제)를 해결.

 

2. RayCast Shape 추가.(4.0에서는 SeparationRayShape라고 이름이 바뀔 예정)

경사면에서 물리적으로는 맞지만, 시각적으로는 어색했던 움직임과 경사면의 각도나 위치에 따라서 RayCast를 여러개를 추가해서 사용해야 했던 문제 해결.

 

3. Sync To Physics 옵션 추가.

물리적인 동기화 문제로 인하여 발생했던 문제(예:플랫포머 위에서 오브젝트가 흐르는 듯한 현상)를 해결하기 위한 옵션으로 AnimationPlayer에서 애니메이션을 적용할때나, 오브젝트를 수동으로 위치나 회전 속성을 미세 조정할 때 유용.

 

<참고>
https://godotengine.org/article/godot-31-will-get-many-improvements-kinematicbody

1. RigidBody를 사용할 경우 KinematicBody에서와 같은 is_on_floor(), is_on_wall(), 그리고 is_on_celling()과 같은 함수를 지원하지 않는다.

2. RigidBody를 사용할 경우, 바닥을 체크할 수 있는 방법은 RayCast와 Area를 이용하는 방법이 있다.

3. RayCast를 이용하여 바닥을 체크할 경우, 위의 이미지와 같은 위치에 서 있을 경우 점프를 할 수 없는 경우가 생긴다.(바닥 상태여야만 점프를 할 수 있게 코딩을 한 경우에 해당)

4. 3번과 같은 경우는 RayCast를 여러개 사용하면 해결할 수 있다.

 

결론 : 바닥상태 체크는 오히려 Area를 사용하는 것이 더 좋을 것 같다.(3.1에서 RayCast Shape가 추가될 예정이라 위와 같은 문제가 해결될 수도 있슴.)

1. _physics_process()함수 안에 lerp()함수의 결과값을 RigidBody에 바로 적용시키지 말아야 한다. 적용시에 Snake, Frame drop이 일어나며, 심한 경우에는 Jittering까지 일어난다.

2. 실시간으로 lerp()함수의 결과값을 구하여 RigidBody에 적용하여 물리적 특성을 변경하고자 할 경우, _physics_process()함수 안에서 lerp()함수를 사용하여 결과값을 얻은 후에 _integrate_forces()함수 안에서 적용시켜야 한다.

1. 축(Axis)

X축은 빨간색(좌/우), Y축은 녹색(위/아래) 그리고 Z축은 파란색(앞/뒤)

 

2. 오일러각(Euler Angles)

Gimbal lock 문제가 있슴.

 

3. Transform

Local 변환 : transform

World 변환 : global_transform

 

4. Basis

transform.basis = Vector3(transform.basis.x, transform.basis.y, transform.basis.z)

var basis = Basis()
# Contains the following default values:
basis.x = Vector3(1, 0, 0) # Vector pointing along the X axis
basis.y = Vector3(0, 1, 0) # Vector pointing along the Y axis
basis.z = Vector3(0, 0, 1) # Vector pointing along the Z axis

 

5. 변환하기

x축 기준으로 180(PI)도 회전

# Rotate the transform about the X axis
transform.basis = Basis(Vector3(1, 0, 0), PI) * transform.basis
# shortened
transform.basis = transform.basis.rotated(Vector3(1, 0, 0), PI)

Spatial 노드를 회전할 경우

# Rotate the transform in X axis
rotate(Vector3(1, 0, 0), PI)
# shortened
rotate_x(PI)

Object의 Space(World)를 회전

# Rotate locally
rotate_object_local(Vector3(1, 0, 0), PI)

 

 

6. 직교 정규화

연속적으로 변환을 행한 경우, 부동 소수점으로 인하여 오차가 발생함. 이를 보정하기 위해 직교 정규화를 함.(프레임당 한번만)

transform = transform.orthonormalized()

주의할 점은 스케일(Scale)을 조정해야 할 경우, 하위 노드(예:MeshInstance)의 스케일을 조정하는 것을 권장하며, 직교 정규화를 한 후에 적용을 해야함.

transform = transform.orthonormalized()
transform = transform.scaled(scale)

 

7. 쿼터니언 보간

# Convert basis to quaternion, keep in mind scale is lost
var a = Quat(transform.basis)
var b = Quat(transform2.basis)
# Interpolate using spherical-linear interpolation (SLERP).
var c = a.slerp(b,0.5) # find halfway point between a and b
# Apply back
transform.basis = Basis(c)

 

<참고>
http://docs.godotengine.org/en/stable/tutorials/3d/using_transforms.html#problems-of-euler-angles

Area2D

  • 감지(detection)와 영향(influence) 기능 제공
  • Area2D에 오브젝트가 겹치고 들어오고, 나가는 때 signal 표현 가능
  • Area2D를 사용한 Scene에 정의된 중력이나 댐핑(damping) 같은 물리속성을 무시할 수 있다.(물리 속성을 재정의 가능)
  • 마우스 및 터치 스크린 입력도 가능

 

StaticBody2D

  • 고정된 Body.(주로 고정되거나 움직이는 Platform, 컨베이어 벨트, 벽 및 기타 장애물에 쓰임)
  • 충돌 감지는 하지만 충돌 이후의 물리적인 운동을 하지 않는다. 그러나 충돌한 Body에게는 이동이나 회전을 부여해 줄 수 있다.(관련 특성:constant_linear_velocity, constant_angular_velocity)

 

RigidBody2D

  • 다음과 같은 4가지 모드가 제공된다.
    1. Rigid - 기본모드. 외력에 의한 물리적인 반응(다른 Body와의 충돌이나 임의로 힘을 가한 경우)을 한다.
    2. Static - StaticBody2D와 같고 움직이지 않음.
    3. Character - Rigid와 비슷하지만, 회전은 할 수 없다.(아마 외력에 의한 회전이 안된다는 의미인 듯)
    4. Kinematic - KinematicBody2D처럼 물리적인 반응을 하며, 이동은 직접 코드를 작성해야 함.
  • position, linear_velocity 및 기타 다른 물리적 특성을 변경하면, 정상적으로 동작하지 않을 수 있다.(직접 제어를 하지 말아야 함)
  • 물리적인 특성을 변경해야 하는 경우가 생긴다면, _physics_process() 대신에 _integrate_forces()를 이용하면 된다.
  • RigidBody가 sleeping 상태가 되면 _integrate_forces() 함수는 호출되지 않는다.(can_sleep을 비활성화 시키거나, 충돌이 일어났을때만 호출함. 대신 이렇게 하면 성능 저하가 생길 수 있다고 매뉴얼에 써 있다.)
  • Scene 안에 RigidBody가 많으면 많을 수록 필요한 메모리가 늘어난다. 그래서 Godot에서는 contact_reported가 0으로 설정(추적 안함)되어 있다. 추적을 하려면 0대신 다른 값으로 설정한다.

 

KinematicBody2D

  • 다른 Body와 충돌만 감지. 중력이나 마찰 같은 물리 특성에 영향을 받지 않는다. 이부분은 직접 코드로 구현해야 한다.
  • move_and_collide()나 move_and_slide()를 이용해야지 직접 position을 건드리면 안된다.
  • 충돌이 감지되면 즉시 멈추므로, 충돌 후 반응은 직접 코드로 구현해야 한다.
  • move_and_collide()와 move_and_slide()는 _physics_process() 안에서 사용할 수 있고, move_and_slide() 함수에 벡터를 넣을 때, delta(Timestep)를 곱하지 않아야 한다.(move_and_slide()함수는 자동으로 Timestep를 적용해서 계산함)

 

<참고>
http://docs.godotengine.org/en/3.0/tutorials/physics/physics_introduction.html

Unity 혹은 그외에 다른 엔진에서 LerpAngle() 함수가 있다. 이 함수는 선형보간함수인 Lerp() 함수에 각도 A에서 각도 B로 회전을 할 경우, [0, π] 범위내의 회전각으로 각도 B에 도달할 수 있는 기능이 추가된 함수이다.

이 함수는 2D나 3D에서 매우 자주 쓰인다(예:캐릭터의 회전). 하지만 아쉽게도 Godot Engine(3.0.4 기준)에서는 lerp() 함수는 지원하지만 Unity의 LearAngle() 같은 함수는 아직 지원하지 않는다.

func lerp_angle(from_angle, to_angle, weight_value):
	if abs(from_angle - to_angle) >= PI: 
		if from_angle > to_angle:
			to_angle += 2 * PI
		else:
			from_angle += 2 * PI
	return lerp(from_angle, to_angle, weight_value)

<참고>
https://godotengine.org/qa/28776/rotate-kinematicbody2d-based-mouse-position-varying-rate

1. 2.x버전의 _fixed_process() 함수가 3.x버전부터는 _physics_process() 함수로 변경되었다.

2. _physics_process(delta) 함수내에 코드가 작성된 상태라면, _ready() 함수내에서 set_physics_process(true)를 자동으로 호출한다. 물론 필요에 따라서 수동으로 set_physics_process(false)를 하여 _physics_process() 함수를 비활성화 할 수도 있다.

3. _process() 함수를 사용하여, 2D 혹은 3D에서 오브젝트(나의 경우는 RigidBody)를 이동시킬 때, 오브젝트가 shaking(간혈적으로 흔들리거나 떨리는) 현상이 발생한다면, _physics_process() 함수로 변경하면 shaking 현상이 호전되거나 사라질 수 있다. 하지만 Jittering 현상이면 이걸로는 해결할 수 없다.

+ Recent posts