<UI 기초>
- 기본 동작
1. Scene에서 마우스 왼쪽을 클릭하여 UI -> Button을 누르면 Scene에 커다란 Button이 생성된다.
다음과 같이 Scene에 Canvas아래에 Button이 생성되는 것을 확인할 수 있다.
* 아무 Game Obeject 생성 후 Button을 복사해서 Object 아래로 놓으면 아래에 보이는 것처럼 Button이 생성되지않음
=> 오직 Canvas 아래의 Button에서만 다음과 같이 나오는 것을 확인할 수 있다.
2. 다음과 같이 Canvas 아래에 Panel을 생성하고 아래에 Button을 위치시킨다. -> 후에 Button의 Rect Transform을 Reset한다.
2. UI를 동작할 때, Scene에서 2D 화면으로 보고 동작하는것이 더 유용하다. 물론 Button을 눌러서 W,E,R 기능을 모두 사용할 수 있다. 이때 새로운 T라는 기능이 추가된 것을 확인할 수 있다.
3. 조작 방법
- 왼쪽 마우스로 위치를 이동할 수 있다.
- 마우스 휠로 크기를 조절할 수 있다.
- Button을 클릭한 후, 위치를 옮기면 위치가 옮겨진다.
- 버튼의 모서리 부분을 통해 Button의 크기를 조절할 수 있다.
- shift 버튼을 누른 후 꼭지점으로 Button의 크기를 조절하면 비율을 유지하며 Button의 크기를 조절할 수 있다.
- 꼭지점에서 조금 떨어진 상태에서는 rotation을 조절할 수 있다.
- 중앙에 파란 원은 pivot으로 pivot을 중심으로 rotation을 조절한다. (근데 어떻게 pivot의 위치를 조정하는지 모르겠다. 강의에서는 누르면 바로 위치 조절이 가능한데... 이유가 뭐지)
- Global 모드와 Local 모두도 물론 있다. Global: UI 세상에서의 절대 좌표, Local: 상대 좌표
4. Anchors: Button에서 4개의 삼각형으로 이뤄진 것
카메라가 3D 모드를 투영시켜서 2D 모드로 담고 그것을 사용자가 게임 화면(Screen 좌표)으로 바라본다. 이때 Screen 좌표는 해상도에 영향을 받아서 3D 물체들은 자동적으로 보여지는 것
-> UI는 이러한 특성과 조금 다르다. 2D 원근법을 적용받지 않는다.
아래를 보면 Button 하나가 뒤로 가있지만, Game 화면에는 원근법을 적용받지 않아서 동일한 크기로 보여진다.
-> UI는 2D Object로 볼 수 있다.
- Rect Transform
: UI는 화면 비율에 따라 UI를 구성하는 객체의 비율이 바뀌어야한다. 이때, 단순히 화면 비율에 따라 객체를 줄였다가 늘리는 것은 좋지않다. 예를 들어 이미지파일의 경우 마음대로 비율을 조절하면, 이미지가 깨질 수 있다.
=> 융통성 있게 UI의 크기와 여백을 조절하도록
=> Rect Transform과 Anchors 이용
1. Anchor는 부모가 Rect Transform을 가지고 있어야지만, 이용할 수 있다.
* Button에서의 Anchor는 Button이 위치하는 좌표를 Panel(부모)를 기준으로 어떻게 할 것인지를 결정하는 것.
=> 어느 정도 비율로 결정한다.
▶ Panel(부모)의 꼭지점과 Anchor의 꼭지점 사이는 비율로 측정하고 Button의 꼭지점과는 절대 수치로 측정한다.
* 실제 모바일 기기의 디스플레이 길이에 따라 화면에서 측정된 비율만큼 Anchor를 찍어주고 해당 Anchor에서는 절대 수치의 Button의 꼭지점을 찍는어서 나타낸다.
2. 실제로 Panel의 크기를 조절하면 위의 공식▶에 따라 Button의 크기가 변화하는 것을 확인할 수 있다.
자주 사용되는 Anchor는 아래의 버튼을 누르면 확인할 수 있다.
3. 예를들어, Anchor가 모두 중앙에 모인 경우, 중앙과 부모의 꼭지점 사이의 비율에 상관없이 Button의 크기가 일정하게 유지된다.
Anchor가 부모의 꼭지점과 동일하다면, Button과 Panel의 비율이 일정하게 유지된다.
*참고: shift와 같이 Anchor의 2번의 버튼을 누르면 중심위치가 같이 변한다. Alt 버튼을 누르면 Button의 위치 또한 같이 변한다.
* 참고 Canvas에서 Render 모드를 카메라로 하여 3D로 UI를 제작하는 것 또한 가능하다.
- Button Event
UI에서 Button을 눌렀을 때 발생하는 이벤트를 처리한다.
1. 우선 Panel을 사용하지 않기 때문에 Button을 Canvas의 바로 아래 자식으로 두고 Panel을 지운다.
다음과 같이 Text UI를 추가한다.
2. Animation Event의 경우, 본인이 들고 있는 Component 중에 하나의 함수를 선택하도록 되어 있는데 UI의 경우, 다른 객체를 조작할 수 있기 때문에 객체를 선택하는 것과 Event 함수를 처리하는 것 둘 모두 가지고 있음.
=> Canvas에서 UI를 조절하도록 한다.
=> 나중에 Canvas 또한 Prefab으로 만들어서 사용할 수 있다.
=> Canvas가 UI 자체가 된다고 생각
* 현재 구조: Canvas -> UI_Button으로 이름을 바꾼다.
3. Script -> UI를 조작하는 UI 폴더 만들고 UI_Button cs 파일을 만든다. UI_Button의 Component로 해당 cs 파일을 drag drop한다.
Start와 Update에 대한 내용 필요 없기 때문에 지우고 다음과 같이 코딩을 한다.
*UI_Button cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UI_Button : MonoBehaviour
{
public void OnButtonClicked()
{
Debug.Log("Button Click");
}
}
4. Button의 Event처리는 Animation과 마찬가지로 Event를 추가한다. 이때 Object는 UI_Button이고 UI_Button의 OnButtonClicked 함수를 부른다.
5. 이렇게 하여 Play를하면, 다음과 같이 Console 창에 뜨는 것을 확인할 수 있다.
=> 문제, Button을 클릭했는데 Input Manager에서 UI 화면과 Click Event 분리를 하지않아서, Player가 움직인다.
6. InputManager.cs 파일에서 UI 클릭시 바로 return 하도록 다음과 같이 코드 변경
using System.Collections;
using System; // Action 을 위해
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class InputManager
{
public Action KeyAction = null;
public Action<Define.MouseEvent> MouseAction = null;
// mouse의 상태를 저장하는 boolean 변수
bool _pressed = false;
// Update is called once per frame
public void OnUpdate()
{
/* 아무 key도 누르지않은 상태
if (Input.anyKey == false)
return;
*/
// UI인지 확인하는 부분
if (EventSystem.current.IsPointerOverGameObject()) // UI가 Click된 상황인지 알 수 있음.
return;
// mouse를 떼는 부분도 action이라고 안식해야하므로 Input.anyKey
if (Input.anyKey && KeyAction != null)
KeyAction.Invoke(); // keyaction이 있었다고 전파
if(MouseAction != null)
{
if (Input.GetMouseButton(0)) // 왼쪽 클릭 0번
{
MouseAction.Invoke(Define.MouseEvent.Press); // Press event를 알려줌
_pressed = true;
}
else
{
// Mouse를 눌렀다가 떼는 순간이 click
if (_pressed)
MouseAction.Invoke(Define.MouseEvent.Click);
_pressed = false;
}
}
}
}
7. Play시 Button을 누를 때 Player가 같이 움직이지않고 console창에 event 함수에서의 내용이 뜨고 다른 게임 속 화면 을 클릭하면 Player가 제대로 움직이는 것을 확인할 수 있다.
- Button Event - 심화
Button을 누르면 Text의 글자가 바뀌도록 해야함. => Text 객체와 연결해야한다.
1. 다음과 같이 SerializeField를 사용하여 코드를 짠다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UI_Button : MonoBehaviour
{
// tool에서 Text 객체 설정을 위해 선언
[SerializeField]
Text _text;
int _score = 0;
public void OnButtonClicked()
{
Debug.Log("Button Click");
_score++;
_text.text = $"점수: {_score}";
}
}
2. tool에서 다음과 같이 Text 객체를 drag drop해서 설정해 준 후, 플레이를한다. Button을 누를 때마다 score가 올라가는 것을 확인할 수 있다.
3. 이렇게 완성된 UI_Button를 Prefabs으로 drag drop하여 사용하도록한다. Scene에서의 UI_Button을 삭제한다.
=> 일반 게임화면에서 UI를 불러서 UI 화면이 나오도록 동작하게
=> Managers.Resource.Instantiate("경로 ") 를 통해서 불러온다.
*PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
float _speed = 10.0f;
//bool _moveToDest = false;
Vector3 _destPos; // 옮겨가야할 포인트
// Start is called before the first frame update
void Start()
{
/*
Managers.Input.KeyAction -= OnKeyboard;
Managers.Input.KeyAction += OnKeyboard;
*/
Managers.Input.MouseAction -= OnMouseClicked;
Managers.Input.MouseAction += OnMouseClicked;
// UI불러오기
Managers.Resource.Instantiate("UI/UI_Button");
}
4. Prefabs에서 동일한 UI_Button 두 개를 Scene에 넣으면 다음과 같이 게임 화면에서 겹쳐서 보인다.
=> 뒤에 배경을 따로 두거나, Sort Order를 통해 UI의 순서를 조정한다. Sort Order는 UI에서 팝업 창과 같이 순서가 필요한 화면을 관리할 때 쓰인다 .
=> 위의 UI의 문제점
: 소규모의 프로젝트라면 다음과 같이 tool을 이용하여 객체와 mapping 하는 것이 가능하지만, 대규모의 프로젝트라면 위에서 처럼 Event 처리를 위해 모든 객체에 대해 tool로 관리하는 것이 더 복잡
▶ code로 불러서 할 수 있음
'Development > 유니티' 카테고리의 다른 글
[섹션 7] UI Manager (0) | 2021.07.30 |
---|---|
[섹션7] UI - UI 자동화 (0) | 2021.07.29 |
[섹션6] 애니메이션(Animation) - 심화 (0) | 2021.07.22 |
[섹션6] 애니메이션(Animation) (0) | 2021.07.21 |
[섹션5]Camera(카메라) (0) | 2021.07.13 |