유니티에서 사용자의 명령을 감지할 수 있는 수단으로 사용자는 외부 장치를 이용하여 게임을 제어할 수 있다.
유니티는 다양한 타입의 입력기기(키보드 및 마우스, 조이스틱, 터치스크린 등)를 지원한다.
// <Device>
// 특정한 장치를 기준으로 입력 감지
// 특정한 장치의 입력을 감지하기 때문에 여러 플랫폼에 대응이 어려움
private void InputByDevice()
{
// 키보드의 입력감지
if (Input.GetKey(KeyCode.Space))//누르는 동안
Debug.Log("Space key is pressing");
if (Input.GetKeyDown(KeyCode.Space))//눌렀을 때
Debug.Log("Space key is down");
if (Input.GetKeyUp(KeyCode.Space))//눌렀다 땔 때
Debug.Log("Space key is up");
// 마우스의 입력감지
if (Input.GetMouseButton(0))//누르는 동안
Debug.Log("Mouse left button is pressing");
if (Input.GetMouseButtonDown(0))//눌렀을 때
Debug.Log("Mouse left button is down");
if (Input.GetMouseButtonUp(0))//눌렀다 땔 때
Debug.Log("Mouse left button is up");
}
// <InputManager>
// 여러 장치의 입력을 입력매니저에 이름과 입력을 정의
// 입력매니저의 이름으로 정의한 입력의 변경사항을 확인
// 유니티 에디터의 Edit -> Project Settings -> Input Manager 에서 관리
// 단, 유니티 초창기의 방식이기 때문에 키보드, 마우스, 조이스틱에 대한 장치만을 고려함
// 추가) VR Oculus Integraion Kit 같은 경우 입력매니저와 유사한 방식을 사용
private void InputByInputManager()
{
// 축 입력
// Horizontal(수평) : 키보드(a,d / ←, →), 조이스틱(왼쪽 아날로그스틱 좌우)
float x = Input.GetAxis("Horizontal");
// Vertical(수직) : 키보드(w,s / ↑, ↓), 조이스틱(왼쪽 아날로그스틱 상하)
float y = Input.GetAxis("Vertical");
transform.position += new Vector3(x *3* Time.deltaTime, y * Time.deltaTime, 0);
// 버튼 입력
// Fire1 : 키보드(Left Ctrl), 마우스(Left Button), 조이스틱(button0)으로 정의됨
if (Input.GetButton("Fire1"))
Debug.Log("Fire1 is pressing");
if (Input.GetButtonDown("Fire1"))
Debug.Log("Fire1 is down");
if (Input.GetButtonUp("Fire1"))
Debug.Log("Fire1 is up");
}
// <InputSystem>
// Unity 2019.1 부터 지원하게 된 입력방식
// 컴포넌트를 통해 입력의 변경사항을 확인
// GamePad, JoyStick, Mouse, Keyboard, Pointer, Pen, TouchScreen, XR 기기 등을 지원
private void InputByInputSystem()
{
// InputSystem은 이벤트 방식으로 구현됨
// Update마다 입력변경사항을 확인하는 방식 대신 변경이 있을 경우 이벤트로 확인
// 메시지를 통해 받는 방식과 이벤트 함수를 직접 연결하는 방식 등으로 구성
}
// Move 입력에 반응하는 OnMove 메시지 함수
private void Onmove(InputValue value)
{
Vector2 inputDir = value.Get<Vector2>();
Debug.Log(inputDir);
}
private void OnJointBreak(InputValue value)
{
bool inputButton = value.isPressed;
Debug.Log(inputButton);
}
//활용 예시
Vector3 moveDir;
private void OnMove(InputValue value)
{
Vector2 inputDir = value.Get<Vector2>();
moveDir.x = inputDir.x;
moveDir.z = inputDir.y;
}
private void Move()
{
transform.position += moveDir * 3f * Time.deltaTime;
}
public Rigidbody rigid;
private void OnJump(InputValue value)
{
Jump();
}
private void Jump()
{
rigid.AddForce(Vector3.up * 5f, ForceMode.Impulse);
}
private void Update()
{
Move();
}
}
게임오브젝트의 위치, 회전, 크기를 저장하는 컴포넌트이며, 게임오브젝트의 부모-자식 상태를 저장하는 컴포넌트이다.
게임오브젝트는 반드시 하나의 트랜스폼 컴포넌트를 가지고 있으며 추가 & 제거할 수 없다.
//<트랜스폼 접근>
private void TransformReference()
{
thisTransform = transform; //자신의 트랜스폼 직접 가리키기
}
// <트랜스폼 이동>
// Translate : 트랜스폼의 이동 함수
private void TranslateMove()
{
// 월드를 기준으로 이동
transform.Translate(1, 0, 0, Space.World);
// 자신을 기준으로 이동, Space 생략 시 자신 기준
transform.Translate(1, 0, 0, Space.Self);
// position을 이용한 이동, 월드기준
transform.position += new Vector3(1, 0, 0);
}
// <트랜스폼 회전>
// Rotate : 트랜스폼의 회전 함수
private void Rotate()
{
// 월드를 기준으로 회전
transform.Rotate(1, 0, 0, Space.World);
transform.Rotate(Vector3.up, 30 * Time.deltaTime, Space.World);
// 자신을 기준으로 회전
transform.Rotate(1, 0, 0, Space.Self);
transform.Rotate(Vector3.up, 30 * Time.deltaTime, Space.Self);
// 특정 위치를 기준으로 회전
transform.RotateAround(new Vector3(0, 0, 0), Vector3.up, 30*Time.deltaTime);
transform.RotateAround(Camera.main.transform.position, Vector3.up, 1);
// 위치를 바라보는 회전
transform.LookAt(new Vector3(0, 0, 0));
}
//<트랜스폼 축>
private void Axis()
{
// 트랜스폼의 x축
Vector3 right = transform.right;
// 트랜스폼의 y축
Vector3 up = transform.up;
// 트랜스폼의 z축
Vector3 forward = transform.forward;
}
//비교 예시
public Transform sphere;
public Transform cube;
public void Update()
{
sphere.position = transform.position + 3 * Vector3.forward;
cube.position = transform.position + 3 * transform.forward;
}
// <트랜스폼 부모-자식 상태>
// 트랜스폼은 부모 트랜스폼을 가질 수 있음
// 부모 트랜스폼이 있는 경우 부모 트랜스폼의 위치, 회전, 크기 변경이 같이 적용됨
// 이를 이용하여 계층적 구조를 정의하는데 유용함 (ex. 팔이 움직이면, 손가락도 같이 움직임)
// 하이어라키 창 상에서 드래그 & 드롭을 통해 부모-자식 상태를 변경할 수 있음
private void TransformParent()
{
GameObject newGameObject = new GameObject() { name = "NewGameObject" };
// 부모 지정
transform.parent = newGameObject.transform;
// 부모를 기준으로한 트랜스폼
// transform.localPosition : 부모트랜스폼이 있는 경우 부모를 기준으로 한 위치
// transform.localRotation : 부모트랜스폼이 있는 경우 부모를 기준으로 한 회전
// transform.localScale : 부모트랜스폼이 있는 경우 부모를 기준으로 한 크기
// 부모 해제
transform.parent = null;
// 월드를 기준으로한 트랜스폼
// transform.localPosition == transform.position : 부모트랜스폼이 없는 경우 월드를 기준으로 한 위치
// transform.localRotation == transform.rotation : 부모트랜스폼이 없는 경우 월드를 기준으로 한 회전
// transform.localScale : 부모트랜스폼이 없는 경우 월드를 기준으로 한 크기
}
// <Quarternion & Euler>
// Quarternion : 유니티의 게임오브젝트의 3차원 방향을 저장하고 이를 방향에서 다른 방향으로의 상대 회전으로 정의
// 기하학적 회전으로 짐벌락 현상이 발생하지 않음
// EulerAngle : 3축을 기준으로 각도법으로 회전시키는 방법
// 직관적이지만 짐벌락 현상이 발생하여 회전이 겹치는 축이 생길 수 있음
// 짐벌락 : 같은 방향으로 오브젝트의 두 회전 축이 겹치는 현상
// Quarternion을 통해 회전각도를 계산하는 것은 직관적이지 않고 이해하기 어려움
// 보통의 경우 쿼터니언 -> 오일러각도 -> 연산진행 -> 결과오일러각도 -> 결과쿼터니언 과 같이 연산의 결과 쿼터니언을 사용함
private void Rotation()
{
Quaternion rotation = transform.rotation;
Vector3 position = transform.position;
Vector3 scale = transform.localScale;
// 트랜스폼의 회전값은 Euler각도 표현이 아닌 Quaternion을 사용함
transform.rotation = Quaternion.identity;
// Euler각도를 Quaternion으로 변환
transform.rotation = Quaternion.Euler(0, 90, 0);
// Vector3 rotation = transform.rotation.eulerAngles;
}
}