[Unity/프로젝트] 03 룰렛(2)
개요
게임에 필요한 핵심 기능들을 구현합니다. 본문에서 다룰 기능들은 다음과 같습니다.
- 회전하는 룰렛 이미지
- 파워 게이지
- 입력 제한
- 결과값 추출
구현
우선 게임을 상태별로 나누어서 구현할 수 있도록 게임의 상태를 열거형으로 변수화 합니다.
public enum GameState
{
PowerIng = 0, // 대기 상태
RotateIng = 1, // 룰렛 회전 상태
GameEnd = 2 // 게임 종료 상태
}
PowerIng
사용자 입력을 받아 파워 값 설정이 가능한 상태입니다.
RotateIng
룰렛이 회전 중인 상태로 룰렛 회전 관련 사용자의 입력을 모두 무시합니다.
GameEnd
5회 시행을 마치고 게임이 종료된 상태입니다.
회전하는 룰렛 이미지
룰렛 회전시키기 기능 관련 세부 단계는 다음과 같습니다.
- 대기 상태(PowerIng) 에서 사용자가 게임 화면 내부에서 좌클릭을 유지하면 회전 속도값 변수 rotSpeed 을 서서히 증가시킵니다.
- 사용자가 입력을 종료하면 룰렛 회전 상태(RotateIng) 로 전환하고 rotSpeed 을 회전 속도로 설정합니다.
- 룰렛이 회전하면 rotSpeed 을 지속적으로 감소시킵니다.
- 회전 속도가 0이 되면 시행을 종료하고 상태를 전환합니다.
코드는 다음과 같습니다.
void Update()
{
/* 입력 제한 코드 */
if (GameMgr.s_State == GameState.PowerIng)
{
if (Input.GetMouseButton(0) == true)
{
// 회전 속도를 증가시킨다.
this.rotSpeed += (Time.deltaTime * 50.0f);
if (m_MaxPower < rotSpeed)
rotSpeed = m_MaxPower;
}
else if (Input.GetMouseButtonUp(0) == true)
{
GameMgr.s_State = GameState.RotateIng;
}
}
else if (GameMgr.s_State == GameState.RotateIng) //룰렛이 돌아가는 상태
{
// 회전 속도만큼 룰렛을 회전시킨다.
transform.Rotate(0, 0, rotSpeed);
// 룰렛을 감속시킨다.
this.rotSpeed *= 0.98f;
if (this.rotSpeed <= 0.1f)
{
this.rotSpeed = 0.0f;
GameMgr.s_State = GameState.PowerIng;
/* 결과값 추출 코드 */
}
}
/* 파워 게이지 코드 */
}
파워 게이지
Image 컴포넌트의 Image Type 속성 중 Filled 타입을 이용해 값의 변화에 따라 이미지가 채워지는 게이지 바를 구현합니다. 구현 방법은 다음과 같습니다.
① Image 컴포넌트의 Image Type 속성을 Filled 타입으로 설정합니다.
Image Type 속성의 하위 속성인 Fill Method 값에 따라 다양한 형태의 게이지 바를 생성할 수 있습니다. 수평으로 차오르는 막대 게이지 바를 구현하기 위해 Fill Method 를 Horizontal 로 설정합니다. Fill Amount 는 게이지 크기를 0~1 실수로 수치화 하는 속성입니다. Fill Amount 값은 게이지가 없을 경우 0, 가득 찼을 경우 1입니다.
② 스크립트에서 해당 이미지의 Image 컴포넌트를 가져와 인스턴스 속성인 fillAmount 에 현재 회전 속도를 대입합니다.
void Update()
{
// :
// 게이지 바 수치를 이미지에 반영한다.
m_PwBarImg.fillAmount = rotSpeed / m_MaxPower;
// 게이지 바 수치를 0~100 정수로 출력한다.
PwText.text = (int)(m_PwBarImg.fillAmount * 100) + " / 100";
}
fillAmount 의 범위는 0~1 실수이므로 (회전 속도 / 최대 속도) 값을 대입합니다. fillAmount 에 100을 곱한 후 정수로 형변환 하면 0~100 정수로 표현할 수 있습니다.
입력 제한
룰렛의 회전 속도를 변화시키기 위해 사용자가 게임 화면을 클릭하는 과정에서 Input.GetMouseButton 이벤트 메서드를 사용했습니다. 이는 게임 내에서 발생하는 모든 마우스 버튼 입력을 대상으로 하기 때문에 해당 마우스 포인터 위치에 다른 UI가 존재하더라도 같이 동작하게 됩니다. 서로 다른 이벤트가 동시에 발생하는 것을 막기 위해 입력 시 해당 마우스 포인터 위치에 다른 UI가 존재할 경우 예외 처리하도록 합니다. 예외 처리 코드는 다음과 같습니다.
void Update()
{
// 현재 마우스 포인터가 UI 위에 있으면 예외 처리
if (GameMgr.IsPointerOverUIObject())
return;
/* 회전하는 룰렛 코드 */
/* 파워 게이지 코드 */
}
// UGUI의 UI들이 먼저 피킹되는지 확인하는 메서드
public static bool IsPointerOverUIObject()
{
// 마우스 포인터 관련 EventSystem 객체 a_EDCurPos
PointerEventData a_EDCurPos = new PointerEventData(EventSystem.current);
// a_EDCurPos 의 위치를 현재 마우스 포인터 위치로 조정
a_EDCurPos.position = Input.mousePosition;
// Raycast 에 의해 감지된 객체 정보를 저장할 리스트 results
List<RaycastResult> results = new List<RaycastResult>();
// 현재 마우스 포인터 위치에 존재하는 UI 대상으로 Raycast
EventSystem.current.RaycastAll(a_EDCurPos, results);
// 감지된 대상이 존재하면 true 존재하지 않으면 false
return (0 < results.Count);
}
예외 처리로 인해 마우스 입력 위치에 다른 UI가 존재할 경우 룰렛이 회전하지 않게 됩니다.
결과값 추출
다음은 초기 상태의 룰렛입니다.
예를 들어 8이 당첨되기 위한 회전각 차의 범위는 17.5~54.5, 9가 당첨되기 위한 회전각 차의 범위는 54.5~90.0 입니다. 이와 같이 나올 수 있는 모든 결과값(0~9)은 회전각 차의 범위로 구분할 수 있습니다. 따라서 룰렛의 회전각 값을 변수화하여 범위 체크를 통해 결과값을 추출하면 됩니다.
3D 뷰를 통해서 보면 룰렛의 회전축은 z축(파란색 축) 임을 알 수 있으므로, z축 기준의 룰렛의 현재 회전각 값을 가져오는 코드는 다음과 같습니다.
float a_Angle = transform.eulerAngles.z;
따라서 회전각 차를 이용해 결과값을 가져오는 코드는 다음과 같습니다.
// 회전각 차를 결과값으로 치환하는 메서드
int GetCurNumber()
{
float a_Angle = transform.eulerAngles.z;
int a_Num = 0;
if (17.5f <= a_Angle && a_Angle < 54.5f) a_Num = 8;
else if (54.5f <= a_Angle && a_Angle < 90.0f) a_Num = 9;
else if (90.0f <= a_Angle && a_Angle < 125.5f) a_Num = 0;
else if (125.5f <= a_Angle && a_Angle < 162.0f) a_Num = 1;
else if (162.0f <= a_Angle && a_Angle < 198.0f) a_Num = 2;
else if (198.0f <= a_Angle && a_Angle < 234.0f) a_Num = 3;
else if (234.0f <= a_Angle && a_Angle < 270.0f) a_Num = 4;
else if (270.0f <= a_Angle && a_Angle < 306.0f) a_Num = 5;
else if (306.0f <= a_Angle && a_Angle < 342.0f) a_Num = 6;
else a_Num = 7;
return a_Num;
}
결과
Unity - Scripting API: EventSystems.EventSystem.RaycastAll
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see: You've told us there are code samples on this page which don't work. If you know ho
docs.unity3d.com
Unity - Scripting API: Transform.eulerAngles
The x, y, and z angles represent a rotation z degrees around the z axis, x degrees around the x axis, and y degrees around the y axis. Only use this variable to read and set the angles to absolute values. Don't increment them, as it will fail when the angl
docs.unity3d.com