유니티는 C# 언어를 사용하는 대표적인 게임 엔진 중 하나입니다. 위의 사진은 유니티의 생명주기로 호출되는 순서라고 생각하시면 됩니다.
<Rigidbody, Collider>
오늘은 유니티의 기초적인 기능인 이동, 충돌, 물리를 다뤄보겠습니다. 우선 Empty, Capsule, plane 생성하고 시작합니다. 오늘 다뤄야할 충돌, 물리에 필요한 Rigidbody, Collider을 알아보겠습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LifeCycleTest : MonoBehaviour // MonoBehaviour: 유니티가 제공하는 FlameWork
{
//가장 먼저 호출되는 Awake 함수
//여기서 보통 변수를 초기화 함.
//함수 순서 상관없이 무조건 Awake 함수 우선 호출.
private void Start()
{
//Awake 다음으로 호출되는 Start함수
//보통 Awake에서 초기화한 변수를 조작함.
//함수 순서 상관없이 무조건 Awake 함수 다음으로 호출.
Debug.Log("Start 호출됨.");
}
//게임오브젝트가 활성화 될 때 호출되는 함수
private void OnEnable()
{
Debug.Log("Onenable 호출됨.");
}
private void Awake()
{
//Debug.Leg(string) Unity의 콘솔창에 메세지를 띄우는 함수
Debug.Log("Awake 호출됨.");
}
}
위의 코드(Script)처럼 Start함수가 처음오고 OnEnable, Awake 함수가 들어오면 어떤 함수가 먼저 호출될까요? 바로 Awake 함수입니다. 만약 Awake함수가 없다면 OnEnable 함수가 먼저 호출되겠죠? 즉, 위의 생명주기에 따른 함수 호출 순서는 고정이라는 뜻입니다. 함수에 따른 특징은 주석으로 붙여놓았습니다. 이 개념을 숙지한 상태로 Capsule 오브젝트를 Player로 간주하고 C# Script를 짜보겠습니다. 그 전에 오브젝트들에게 충돌과 물리 기능을 추가해주겠습니다.
인스펙터(Inspector)창에 Add Component를 통해 Rigidbody(물리)와 Capsule Collider(캡슐 충돌)를 추가합니다. 여기서 중요한건 3D 오브젝트이기 때문에 Rigidbody 2D가 아닌 일반 Rigidbody를 추가합니다. 그 후, script 생성과 추가합니다. 이름은 Player로 추가합니다. 그 후, C# Script에서 특정값을 다루기 위해선 변수를 생성해야합니다. 우리의 목표는 Rigidbody와 Collider를 다루는 것입니다. 때문에 그에 따른 변수를 생성합니다.
public class Player : MonoBehaviour
{
//RigidBody라는 컴포턴트를 조작하기 위해서
//RigidBody 타입의 변수를 만들고
//아무것도 안들어가 있으니까 null로 초기화 해줌.
private Rigidbody rigidBody = null;
private CapsuleCollider capsuleCollider = null;
}
C#에서 변수 생성 문법은 접근제한자 자료형 변수명; 입니다. 그런데 위의 코드에서 우리가 아는 자료형 int, float 등 형태가 아닙니다. 이는 유니티(Unity) 자체의 표현법입니다.
위의 Inspector창에서 우리가 다룰 건 Capsule Collider과 Rigidbody입니다. 이들은 이름 자체가 자료형이기도 합니다. 그렇기 때문에 Rigidbody의 자료형은 Rigidbody, Capsule Collider 자료형은 CapsuleCollider입니다. 그 후, Awake 함수에서 각 변수에서 다룰 정확한 기능들을 선언해주십시다.
rigidBody = GetComponent<Rigidbody>();
capsuleCollider = GetComponent<CapsuleCollider>();
rigidBody 변수엔 GetComponent의 Rigidbody 기능을, capsuleCollider 변수엔 GetComponent의 CapsuleCollider 기능을 다루겠다고 선언합니다.
public class Player : MonoBehaviour
{
//OnCollisionEnter
//떨어져 있던 물체가 충돌했을 때 호출됨
//인자로 들어오는 Collision 객체는 충돌한 오브젝트의
//정보를 가지고 있음.
void OnCollisionEnter(Collision collision)
{
//collision.gameObject.name
//충돌한 물체의 게임오브젝트의 이름을 가져옴.
Debug.Log("OnCollisionEnter 호출됨. " + collision.gameObject.name);
}
//OnCollisionExit
//물체가 붙어있다가 떨어질 때 호출됨
private void OnCollisionExit(Collision collision)
{
Debug.Log("OnCollisionExit 호출됨. " + collision.gameObject.name);
}
//OnCollisionStay
//물체가 충돌 중인 상태일 때 호출됨
private void OnCollisionStay(Collision collision)
{
Debug.Log("OnCollsionStay 호출됨. " + collision.gameObject.name);
}
//OnTriggerEnter
//Collider에 부딪힌 오브젝트의 정보가 담겨 있음.
private void OnTriggerEnter(Collider other)
{
Debug.Log("OnTriggerEnter 호출됨. " + other.gameObject.name);
}
//충돌했다가 떨어질때 호출되는 Trigger함수
private void OnTriggerExit(Collider other)
{
Debug.Log("OnTriggerExit 호출됨. " + other.gameObject.name);
}
//충돌 중일 때 호출되는 Trigger함수
private void OnTriggerStay(Collider other)
{
Debug.Log("OnTriggerStay 호출됨. " + other.gameObject.name);
}
}
위는 생명주기에 OnCollisionXXX, OnTriggerXXX를 다룹니다. 여기서 Trigger란 Collider에서 다루는 기능으로 오브젝트 통과에 대한 기능입니다. 예시로 게임 중에는 카트라이더 아이템전이 있습니다.
여기에서 아이템은 Trigger가 켜져있는 상태입니다. 아이템과 플레이어가 충돌 감지 시 아이템 오브젝트 꺼지며 효과가 발생하도록 코딩된 것입니다. 만약 Trigger가 꺼져있었다면? 아이템을 먹으려다 충돌하여 레이싱을 방해하게됩니다. Trigger기능은 충분히 이해됐을 것이라 생각하고 다음으로 넘어가겠습니다. 위는 충돌에 대한 각 기능별 함수들입니다.
- OnColliderEnter: Collider이 켜져있는 상태에서 충돌 당시 호출되는 함수
- OnColliderExit: Collider이 켜져있는 상태에서 충돌 후 떨어질 때 호출되는 함수
- OnColliderStay: Collider이 켜져있는 상태에서 충돌하는 중에 호출되는 함수
- OnTriggerEnter: Trigger이 켜져있는 상태에서 충돌 당시 호출되는 함수
- OnTriggerExit: Trigger이 켜져있는 상태에서 충돌 후 떨어질 때 호출되는 함수
- OnTriggerStay: Trigger이 켜져있는 상태에서 충돌하는 중에 호출되는 함수
<Input.GetKey>
이 키워드는 키보드에서 특정 키를 사용하는 기능입니다.
private void Update()
{
//Input.GetKeyDown(KeyCode)
//해당 키를 누를 때 true 반환
//Update에서 작업하고 있으니까 매 프레임 키가 눌러졌는지 안눌러졌는지 체크
//그러다가 눌러지면 true값을 반환하고 if조건문의 로직이 수행됨.
if(Input.GetKeyDown(KeyCode.A))
{
//A키를 누르면 RigidBody의 useGravity 속성을 false로 만듦
//체크 해제 상태로 변환
rigidBody.velocity = new Vector3(0, 0, 0);
rigidBody.useGravity = false;
}
else if(Input.GetKeyDown(KeyCode.S))
{
//S키를 누르면 RigidBody의 useGravity 속성을 true로 만듦
//체크된 상태로 변환
rigidBody.useGravity = true;
}
if(Input.GetKeyDown(KeyCode.D))
{
capsuleCollider.isTrigger = true;
}
else if(Input.GetKeyDown(KeyCode.F))
{
capsuleCollider.isTrigger = false;
}
}
위의 코드는 Input.GetKey에 대한 함수들입니다. 위에서 다루는 함수들에 대한 설명입니다.
- velocity: Velocity는 가속력에 대한 키워드로, Gravity(중력)에 따른 물체의 일정 속도를 지정합니다.
- useGravity: Rigidbody 에서 use Gravity 기능 ON/OFF할지 키워드
- isTrigger: Collider 에서 Trigger 기능 ON/OFF할지 키워드
위의 GetKey에도 여러 종류가 있습니다.
- GetKeyUp: 특정 키를 누르고 뗄 때 관련 기능이 호출됩니다.
- GetKeyDown: 특정 키를 누른 당시에 관련 기능이 호출됩니다.
- GetKey: 특정 키를 누른 상태에 관련 기능이 호출됩니다.
GetKey는 Stay와 같은 키워드라고 생각하시면 됩니다. 위를 이용해 Player 오브젝트 이동을 해보겠습니다.
public class Player : MonoBehaviour
{
private Transform tr = null;
private void Awake()
{
tr = GetComponent<Transform>();
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.UpArrow))
{
tr.position += new Vector3(0, 0, 1);
}
if(Input.GetKeyDown(KeyCode.DownArrow))
{
tr.position += new Vector3(0, 0, -1);
}
if(Input.GetKeyDown(KeyCode.LeftArrow))
{
tr.position += new Vector3(-1, 0, 0);
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
tr.position += new Vector3(1, 0, 0);
}
}
}
이동은 위치값인인 Transform의 Position을 이용합니다.
Transform의 자료형은 Transform입니다. 그에 따라 변수 tr을 생성합니다. 그리고 tr은 Awake함수를 통해 GetComponent<Transform>으로 tr의 Transform을 다룹니다. 키를 누르는지를 계속 감지해야하므로 Update() 함수에 각 GetKeyDown 조건문으로 방향키에 따라 좌표값 변경 조건문을 생성합니다. new로 위치를 동적으로 변환합니다.
tr.position += new Vector( , , );
끝
'유니티(Unity) 프로그래밍' 카테고리의 다른 글
유니티3D 아날로그 시계 (0) | 2024.09.19 |
---|---|
Unity3D 추격2 (1) | 2024.09.18 |
Unity3D 추격 (1) | 2024.09.12 |
Unity3D에 유용한 기능들 (1) (2) | 2024.09.04 |
Unity3D에서의 상속 (1) | 2024.09.04 |