유니티( Unity 3D ) 헬기 비행 시뮬레이션 만들기 Part 04
수직 상승/강하 비행 구현
앞장에서는 지상에서 헬기가 이동하면 방향 및 속도를 변경할 수 있었고 브레이크를 작동하여 정지하는 기능도 구현해봤습니다.
이번에는 드디어 3차원 세상으로 진입하는 수직상승 강하 비행을 구현해보겠습니다.
테스트화면을 GIF 애니메이션으로 캡쳐하여 보니 초당 프레임 수가 낮아서 부드럽게 보이지는 않지만 실제로는 훨씬 더 부드럽고 실감나게 느껴집니다
헬기가 지면에서 상승하다가 다시 내려와서 지면에 닿으면 하강을 멈춰야 하는데, 그렇게 하기 위해서는 헬기가 지면에 닿는 것을 인지해야 합니다.
지면은 유니티에서 기본적으로 제공하는 Cube를 이용해서 평평한 바닥을 만들 수 있고, Cube 에 Box Collider를 설정하여 Is Trigger 항목을 선택해주면 바닥에 충돌하는 다른 오브젝트는 OnTriggerEnter() 함수를 구현하여 지면에 닿는 순간을 포착할 수 있습니다.
지면으로 사용된 Cube는 납작하게 크기를 조절하고 Tag를 설정할 때 'ground' 라는 이름을 지정해주면 지면에 착륙하는 헬기의 OnTriggerEnter() 함수 안에서 if( transform.gameObject.tag=='ground' ) 와 같이 지면에 닿는 순간을 포착할 수 있습니다
OnTriggerEnter() 함수가 호출되게 하려면, 헬기 오브젝트에 RigidBody 콤포넌트를 추가하고 또 헬기에 Collider도 추가해 주어야 합니다.
이렇게 하면 헬기가 지면에 착륙하는 순간 OnTriggerEnter() 함수가 호출되므로 이 함수 안에서 착륙시 필요한 작업을 수행하면 됩니다.
그리고 헬기가 지면에서 이륙하는 순간에는 OnTriggerExit() 함수가 호출되므로 이륙시의 필요한 작업을 수행하는 용도로 사용하면 됩니다
참고로, 여기서는 아직 비행원리에 입각한 정교한 비행을 구현하는 것이 아니라 대충 그럴싸한 이륙, 상승, 비행 및 접근, 착륙이 가능하도록 흉내를 내는 것으로 만족하고 점차 실제 비행과 비슷한 수준까지 구현해보려고 합니다.
다른 소스파일을 앞장과 동일하며 Helicopter.cs 의 내용이 아래와 같이 달라졌다.
Helicopter.cs
using UnityEngine; using System.Collections; public class Helicopter : MonoBehaviour { public float rotSpeed; public float moveSpeed; public float TOW; // Take Off Weight public float power; float powerDelta; public float verticalSpeed; Vector3 movingVector; int STATUS; int STATUS_GROUND; int STATUS_AIR; int STATUS_HOVER; int STATUS_FLYING; void Start () { rotSpeed = 0.0f; moveSpeed = 0.0f; TOW = 100f; power = 50f; verticalSpeed = 0f; //transform.Translate(Vector3.up*0.1f); powerDelta = 0f; STATUS = 1; STATUS_GROUND = 0; STATUS_HOVER = 1; STATUS_AIR = 2; STATUS_FLYING = 3; } void Update () { // A키는 좌회전, D키는 우회전 if (Input.GetKey (KeyCode.A)) { rotSpeed += -0.2f; } else if (Input.GetKey (KeyCode.D)) { rotSpeed += 0.2f; } else { if(rotSpeed>0) rotSpeed += -0.4f; else if(rotSpeed<0) rotSpeed += 0.4f; } // 지상에서 헬기동체의 Y축 중심 회전 transform.Rotate (Vector3.up * Time.deltaTime * rotSpeed); //UP, DOWN 키를 동시에 누르면 브레이크를 작동한다 if (Input.GetKey ("up") && Input.GetKey ("down")) { if (moveSpeed > 0) moveSpeed += -0.01f; else if (moveSpeed < 0) moveSpeed += 0.01f; if (Mathf.Abs (moveSpeed) < 0.05f) moveSpeed = 0f; } else { // UP 키는 전방속도, DOWN키는 후방속도 조절 if (Input.GetKey ("up")) { moveSpeed += 0.004f; } else if (Input.GetKey ("down")) { moveSpeed += -0.004f; } } if(STATUS==STATUS_FLYING && moveSpeed<0.5f) { STATUS = STATUS_HOVER; print ("HOVER"); }else if(STATUS==STATUS_HOVER && moveSpeed>0.5f) { STATUS = STATUS_FLYING; print ("FLYING"); } // W키가 눌리면 동력증가, S키는 동력감소 if (Input.GetKey (KeyCode.W)) { powerDelta += 0.04f; //print ("W, power="+power); } else if (Input.GetKey (KeyCode.S)) { if(power>0f) { powerDelta += -0.04f; //print ("S, power="+power); } } else { powerDelta = 0f; } power += powerDelta; // 동력이 이륙중량을 초과하면 상승시작, if (power > TOW) { verticalSpeed = power / TOW - 1f; } else if (power < TOW) { if(STATUS==STATUS_GROUND) verticalSpeed = 0f; else if(transform.position.y>=0) verticalSpeed = power / TOW - 1f; } transform.Translate (Vector3.up * Time.deltaTime * verticalSpeed); transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed); } void OnTriggerEnter(Collider other) { if (other.gameObject.tag == "ground") { STATUS = STATUS_GROUND; verticalSpeed = 0f; print ("On Ground"); } } void OnTriggerExit(Collider other) { if(other.gameObject.tag=="ground") { STATUS = STATUS_HOVER; print ("HOVER"); } } }
다음 장에서는 좀더 사실감 있는 비행을 구현하기 위해서 비행중 헬기의 동체가 경사진 방향으로 서서히 선회가 될 수 있도록 구현해 보겠습니다