0. 들어가기 전에
이번에는 점토 구매, 집 업그레이드, 야생 UI 버튼을 만들고 애니메이션을 적용했다.
버튼을 눌렀을 때 구매창, 업그레이드 창이 뜨도록 하는 기능과 야생 씬으로 전환되는 기능은 다음에 구현할 것이다. 이번엔 그냥 버튼만 만들었다.
1. UI 버튼 제작
본격적으로 캔버스에 이미지와 버튼을 추가한다.
1.1 UI 버튼 생성
왼쪽 하단을 보면 버튼 3개가 있는 모습을 볼 수 있다.
먼저 캔버스에 판넬 이미지를 하나 게임 오브젝트로 만들어 준 후, 그 판넬의 자식 오브젝트로 3개의 버튼을 만들어주었다.
세 개의 버튼은 왼쪽부터 차례로 점토 구매 버튼, 집 업그레이드 버튼, 야생 버튼이다.
1.2 UI 버튼 스프라이트 Swap
Button 의 Transition 을 Sprite Swap 으로 설정해준다.
Highlighted Sprite, Pressed Sprite, Selected Sprite 칸에 버튼이 눌린 상태를 표현할 스프라이트를 할당해준다. 나는 기존 버튼에서 색을 채운 스프라이트를 할당해줬다.
이러면 마우스를 버튼에 가져다 대었을 때, 버튼을 클릭했을 때 스프라이트가 바뀐다.
2. UI 버튼 애니메이션
버튼에 생동감을 주기 위해서 애니메이션을 추가했다.
2.1 애니메이터 제작
버튼의 애니메이션은 각자의 캔버스상 position 을 이용할 것이기 때문에 부득이하게 세 개의 애니메이터를 만들었다.
그런데 세 개의 버튼의 애니메이터 구성은 똑같고 사용하는 애니메이션만 다를 뿐이므로 그냥 애니메이터를 세 개 무작정 만드는 것보다 하나의 애니메이터를 만든 후 오버라이드 컨트롤러를 2개 만들어주었다.
오버라이드 컨트롤러는 애니메이터의 구성을 건드릴 수 없고 애니메이션만 할당해줄 수 있다.
PlantButton 과 WorldButton 컨트롤러는 ClayButton 컨트롤러를 오버라이드 한 컨트롤러이다.
즉, 이제 ClayButtonClick 과 ClayButtonDrag 에 자신에게 맞는 애니메이션을 할당해주면 된다.
2.2 ClayButton 컨트롤러의 구성
컨트롤러의 구성은 위 사진과 같다. Idle 은 버튼이 그냥 가만히 있는 상태, Click 은 마우스로 버튼을 클릭했을 때, Draged 는 마우스를 버튼위에 올려놓은 상태이다.
버튼이 가만히 있는 상태에서는 Click 과 PointerOn 두 개의 상태로 갈 수 있다. Click 상태로 가기 위해서는 Parameter 인 clicked 의 값이 true 가 되어야 하고, PointerOn 이 되기 위해서는 draged 의 값이 true 가 되어야 한다.
버튼이 클릭 상태일 때는 끝나고 Idle 로만 돌아가는 길을 만들었다. Idle 로 넘어가기 위해서는 Parameter 의 closed 가 true 가 되어야 한다.
마우스를 버튼에 가져다 댄 상태에서는 Idle 과 Click 두 개의 상태로 갈 수 있다. click 상태로 가기 위해서는 Parameter 인 clicked 의 값이 true 가 되어야 하고, Idle 이 되기 위해서는 draged 가 false 가 되어야 한다.
2.3 ButtonMove 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ButtonMove : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
[Header("Animation")]
Animator anim;
[Header("Sprite")]
public Sprite nonClicked;
public Sprite clicked;
[Header("Button UI")]
public Button uiButton;
public Button[] otherButtons;
void Start()
{
anim = GetComponent<Animator>();
uiButton = GetComponent<Button>();
}
void Update()
{
}
public void ButtonMoveStart()
{
// 이미 버튼이 눌려있는 상태에서 마우스를 가져다대면 위아래로 움직이는 모션이 실행되지 않도록..
if (!anim.GetBool("clicked"))
{
anim.SetBool("draged", true); // 값을 true 로 줘서 Draged 애니메이션 실행
}
else
{
// 버튼이 눌린 상태면 버튼으로 마우스 갖다대도 false 로..
anim.SetBool("draged", false);
}
}
public void ButtonMoveEnd()
{
anim.SetBool("draged", false); // 값을 false 로 줘서 Idle 애니메이션 실행
}
public void ButtonClicked()
{
for (int i=0; i<otherButtons.Length; i++)
{
// 자신을 제외한 다른 버튼 모두 끄기
otherButtons[i].GetComponent<ButtonMove>().ResetButtonSprite();
}
uiButton.image.sprite = clicked; // 스프라이트를 click 상태로
anim.SetBool("clicked", true);
anim.SetBool("closed", false);
}
// Event Handler 이용
public void OnPointerEnter(PointerEventData eventData)
{
ButtonMoveStart();
}
public void OnPointerExit(PointerEventData eventData)
{
ButtonMoveEnd();
}
public void OnPointerClick(PointerEventData eventData)
{
ButtonClicked();
}
public void ResetButtonSprite()
{
// 버튼 스프라이트를 nonClick 상태로 다시 바꿔주기
uiButton.image.sprite = nonClicked;
anim.SetBool("clicked", false);
anim.SetBool("closed", true);
}
}
2.4 ButtonMove 스크립트 설명
ButtonMove 스크립트에 대한 설명은 다음과 같다.
1. 변수
버튼의 Animator 컴포넌트를 이용하기 위해 Animator 타입의 anim 변수를 선언했다.
버튼이 클릭된 상태랑 아닌 상태를 구분하기 위해 스프라이트를 교체해야 하는데 이를 위해 nonClicked, clicked 변수 두 개를 선언했다. nonClicked 에는 버튼이 눌리기 전 상태의 스프라이트, clicked 에는 눌린 상태의 스프라이트를 넣어준다.
Button 의 스프라이트를 교체하기 위해서는 일단 Button 게임 오브젝트가 필요하다. Button 타입의 변수인 uiButton 을 선언해서 버튼 게임 오브젝트를 할당한다.
otherButtons 는 자신이 아닌 다른 2개의 버튼을 넣어놓는 용도로 사용한다. 나중에 버튼을 클릭했을 때, 자신이 아닌 다른 2개의 버튼이 Click 애니메이션 상태를 빠져나오도록 하기 위함이다.
[Header("Animation")]
Animator anim;
[Header("Sprite")]
public Sprite nonClicked;
public Sprite clicked;
[Header("Button UI")]
public Button uiButton;
public Button[] otherButtons;
2. 변수에 값 할당
anim 과 uiButton 에 값을 할당해주었다.
void Start()
{
anim = GetComponent<Animator>();
uiButton = GetComponent<Button>();
}
3. ButtonStart(), ButtonEnd() 메서드
- ButtonMoveStart()
ButtonMoveStart() 는 마우스가 버튼 위에 진입 했을 때 호출되는 함수이다.
버튼을 눌렀을 때, 만약 이미 버튼이 눌린 상태라면 마우스를 가져다 대도 draged 상태를 false 로 바꿔준다. 버튼이 눌린 상태가 아닐 때 값을 true 로 주었다.
- ButtonMoveEnd()
ButtonMoveEnd() 는 마우스가 버튼을 빠져나갈 때 호출되는 함수이다. draged 상태를 false 로 준다.
public void ButtonMoveStart()
{
// 이미 버튼이 눌려있는 상태에서 마우스를 가져다대면 위아래로 움직이는 모션이 실행되지 않도록..
if (!anim.GetBool("clicked"))
{
anim.SetBool("draged", true); // 값을 true 로 줘서 Draged 애니메이션 실행
}
else
{
// 버튼이 눌린 상태면 버튼으로 마우스 갖다대도 false 로..
anim.SetBool("draged", false);
}
}
public void ButtonMoveEnd()
{
anim.SetBool("draged", false); // 값을 false 로 줘서 Idle 애니메이션 실행
}
4. ButtonClicked() 메서드
이 메서드는 버튼을 클릭할 때 호출되는 함수이다.
버튼을 클릭했을 때, 클릭된 버튼이 아닌 다른 버튼은 모두 Click 애니메이션 상태에서 벗어나야 하므로 otherButtons 에 저장해놓았던 요소들에 모두 접근해서 ResetButtonSprite() 메서드를 호출했다.
그리고 클릭된 버튼의 스프라이트를 click 상태로 바꿔주고, clicked 와 closed 의 값을 각각 true 와 false 로 바꿔주어 애니메이션이 제대로 작동하도록 해주었다.
public void ButtonClicked()
{
for (int i=0; i<otherButtons.Length; i++)
{
// 자신을 제외한 다른 버튼 모두 끄기
otherButtons[i].GetComponent<ButtonMove>().ResetButtonSprite();
}
uiButton.image.sprite = clicked; // 스프라이트를 click 상태로
anim.SetBool("clicked", true);
anim.SetBool("closed", false);
}
5. ResetButtonSprite() 메서드
이 메서드는 버튼의 스프라이트를 nonClick 상태로 바꿔주고, clicked 와 closed 의 값을 각각 false 와 true 로 설정해준다.
public void ResetButtonSprite()
{
// 버튼 스프라이트를 nonClick 상태로 다시 바꿔주기
uiButton.image.sprite = nonClicked;
anim.SetBool("clicked", false);
anim.SetBool("closed", true);
}
5. Event Trigger 컴포넌트의 메서드
Event Trigger 컴포넌트를 이용한다. 이 컴포넌트가 가지는 메서드는 여러 종류가 있지만 내가 쓰고자 하는 메서드는 총 3개이다. 목록은 다음과 같다.
- OnPointerEnter(PointerEventData eventData)
- OnPointerExit(PointerEventData eventData)
- OnPointerClick(PointerEventData eventData)
OnPointerEnter 는 마우스가 게임 오브젝트 위에 올라갔을 때 자동으로 호출되는 함수이다. 이 함수의 내용을 다음과 같이 만들어주었다. ButtonMoveStart() 는 위에서 설명한 직접 만든 함수이다.
public void OnPointerEnter(PointerEventData eventData)
{
ButtonMoveStart();
}
OnPointerExit 는 마우스가 게임 오브젝트를 빠져나갈 때 자동으로 호출되는 함수이다. 이 함수의 내용을 다음과 같이 만들어주었다. ButtonMoveEnd() 는 위에서 설명한 직접 만든 함수이다.
public void OnPointerExit(PointerEventData eventData)
{
ButtonMoveEnd();
}
OnPointerClick 은 마우스가 게임 오브젝트를 클릭할 때 자동으로 호출되는 함수이다. 이 함수의 내용을 다음과 같이 만들어주었다. OnPointerClick() 는 위에서 설명한 직접 만든 함수이다.
public void OnPointerClick(PointerEventData eventData)
{
ButtonClicked();
}
이 세 개의 메서드를 이용하기 위해서는 다음과 같이 수정해야 한다. 사용하고자 하는 이벤트 핸들러를 나열해야 한다.
public class ButtonMove : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
3. 결과물
UI 버튼의 애니메이션이 잘 작동하는 것을 확인할 수 있다.
4. 참고 자료
Event Trigger 를 잘 설명해놓은 글이 있길래 가져와봤다.
4.1 Event Trigger