본문 바로가기

Blender

[Blender]심플 비행기 모델링/Godot로 불러들이기

Blender 2.93에서 모델링한 비행기

Blender 2.93에서 간단한 비행기 모델링해서 glTF 2.0으로 익스포트한 뒤 아래 간단한 비행기 조종을 다룬 영상 보고 Godot 3.1에서 따라하기.

[Blender에서 Godot로 매시/매핑 불러들이기]

Blender에서 메뉴의 File-Export-glTF 2.0 선택(Format: glTF Embedded, Selected Object: On, Apply Modifiers: On)하여 Export.

Godot에서 새로 Assets 폴더 생성하고 그곳으로 생성한 gltf파일 옮기기.
Godot의 폴더구조에서 gltf 파일 선택, 씬(들) 열기, (무시하고 열기) 선택. 

Spatial에 우클릭, 타입변경, KinematicBody 선택. 

자식노드 추가(CollisionShape)하고 새 CylinderShape 선택.

- 씬 이름 위에 우클릭, '씬을 다른 이름으로 저장' 선택하고 Plane으로 변경.
- 스크립트 추가 버튼 클릭하여 코드 입력, 
- 프로젝트-프로젝트 설정, 입력설정에서 throttle_up~roll_right 입력 추가 생성하고 조이스틱 버튼과 축 설정하기. 
- 카메라는 InterpolatedCamera에 Target을 Plane으로 설정, 따라가는 카메라를 구현했다. 한데 현재 상태에선 속도가 0일 경우 카메라가 비행기 메시 안쪽으로 들어가버리는 문제가 있다. 
- 코드의 경우 내 비행기 모델의 불러들인 방향이 영상 모델과 다른 관계로 축들은 몇개 변경했고 비행기 프로펠러도 코드로 회전시키게 추가하다. 

단, 땅으로 설정한 Plane에 Collision Shape 적용법을 몰라서 땅에 닿아있는 효과는 구현 못한 상태. 

 

Godot에서 대략적인 세팅 마치고 비행 테스트.

- 피치/롤/요우 기동하는 비행기를 추력 높이기/줄이기 버튼(A/Z), 상하좌우 화살표로 조종.


Plane.gd==================================

extends KinematicBody

var min_flight_speed = 10 #최소 속도
var max_flight_speed = 30 #최대 속도
var turn_speed = 0.75 #좌우 회전 속도
var pitch_speed = 0.5 #피치 속도
var level_speed = 3.0 #롤 속도
var throttle_delta = 30 #추력
var acceleration = 6.0 #가속치

var forward_speed = 0
var target_speed = 0
var grounded = false #땅에 닿았는지 여부

var velocity = Vector3.ZERO
var turn_input = 0
var pitch_input = 0

func get_input(delta):
     if Input.is_action_pressed("throttle_up"):
          target_speed = min(forward_speed + throttle_delta * delta, max_flight_speed)

     if Input.is_action_pressed("throttle_down"):
          var limit = 0 if grounded else min_flight_speed
          target_speed = max(forward_speed - throttle_delta * delta, limit)

     turn_input = 0
     if forward_speed > 0.5:
          turn_input = Input.get_action_strength("roll_left") - Input.get_action_strength("roll_right")

     pitch_input = 0
     if not grounded:
          pitch_input -= Input.get_action_strength("pitch_down")
     if forward_speed >= min_flight_speed:
          pitch_input += Input.get_action_strength("pitch_up")

func _physics_process(delta):
     get_input(delta) #입력 받기

     #비행기 상하 회전(Pitch)
     transform.basis = transform.basis.rotated(transform.basis.x, pitch_input * pitch_speed * delta)

     #비행기 좌우 회전(Yaw)
     transform.basis = transform.basis.rotated(Vector3.UP, turn_input * turn_speed * delta)

     #비행기 동체 좌우회전에 따라 기울이기(Roll)
     if grounded:
          $Meshes/Plane.rotation.z = 0
     else:
          $Meshes/Plane.rotation.z = lerp($Meshes/Plane.rotation.z, turn_input * -1, level_speed * delta)

     $Meshes/PlaneWheel.rotate(Vector3.FORWARD, 30) #프로펠러 회전

     #비행기 추력 관련
     forward_speed = lerp(forward_speed, target_speed, acceleration * delta)
     velocity = -transform.basis.z * forward_speed
    
     if is_on_floor():
          if not grounded:
               rotation.x = 0
          grounded = true
          velocity.y -= 1
     else:
          grounded = false
    
     velocity = move_and_slide(velocity, Vector3.UP)

'Godot Recipe: Simplified Airplane Controller(14:28/KidsCanCode)'