일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- project3
- TiL
- 크래프톤정글
- 유니티
- 전쟁-전투
- 크래프톤정글4기
- 티스토리챌린지
- 연결리스트
- User Stack
- 크래프톤 정글
- 백준
- 다익스트라
- 네트워크
- 오블완
- pintos
- KRAFTON JUNGLE
- 4기
- 알고리즘수업-너비우선탐색2
- 파이썬
- Unity
- BFS
- 핀토스
- anonymous page
- 알고리즘
- 크래프톤 정글 4기
- kraftonjungle
- 이벤트 함수 실행 순서
- c#
- 추상클래스와인터페이스
- C
- Today
- Total
말감로그
[Unity] 1. 로또번호 룰렛판 돌리기 본문
0~9 까지 있는 숫자판을 게이지의 파워만큼 돌려 5개의 로또 번호를 뽑는 룰렛 게임을 만들어보도록 합니다.
- 화면에 놓일 오브젝트를 모두 나열한다.
- 룰렛(roulette) , 바늘(needle) , 게이지바(PwBar, PwText) , 문구(HelpText) , 리셋 버튼(Reset_Btn), 숫자표시 UI
- 오브젝트를 움직일 수 있는 컨트롤러 스크립트를 정한다.
- Roulette Controller
- 오브젝트를 자동으로 생성할 수 있도록 제너레이터 스크립트를 정한다.
- 해당하는 오브젝트가 없으므로 사용 X
- UI를 갱신할 수 있도록 감독 스크립트를 준비한다.
- GameMgr
- 스크립트를 만드는 흐름을 생각한다.
- 컨트롤러 스크립트 -> 제너레이터 스크립트 -> 감독 스크립트 순서로 만든다.
RouletteController
1. 룰렛판 돌리기
회전 속도와 최대 힘(속도) 멤버 변수를 선언해 줍니다.
public class RouletteController : MonoBehavior
{
float rotSpeed = 0; //회전 속도
float m_MaxPower = 80.0f; //최대 힘(속도) 변수
Update()함수에 마우스를 누르고 있는 동안 회전 속도를 설정하고 손가락을 떼는 순간 회전 속도 만큼 회전시키도록 구현한다.
if(Input.GetMouseButton(0) == true 는 마우스를 누르고 있는 동 true를 리턴하는 함수이고,
(0)은 왼쪽 마우스 클릭, (1)은 오른쪽 마우스 클릭, (2)는 휠 클릭을 의미한다.
Input.GetMouseButtonDown(0) //왼쪽 마우스를 눌렀을 때
회전속도(rotSpeed)가 최대 속도(m_MaxPower, 80.0f)보다 커지면 회전속도를 최대 속도(80.0f)로 지정한다.
또한 회전속도(rotSpeed)가 0.1f보다 작거나 같아지면 룰렛이 멈춘 상태로 판단하여 룰렛을 완전 멈추게 한다.
void Update()
{
//마우스를 누르고 있는 동안 회전 속도를 설정한다.
if(Input.GetMouseButton(0) == true)
{
this.rotSpeed += (Time.deltaTime* 50.0f); //누르고 있는 동안 속도가 조금씩 증가
if(m_MaxPower < rotSpeed)
rotSpeed = m_MaxPower;
}
//마우스를 누르고 있다가 손가락을 떼는 순간 회전시킨다.
if(Input.GetMouseButtonUp(0) == true)
{
transform.Rotate(0, 0, this.rotSpeed); //회전 속도만큼 회전시킨다.
this.rotSpeed *= 0.98f; //룰렛을 감속시킨다.
if(this.rotSpeed <= 0.1f) //룰렛이 멈춘 상태로 판단
this.rotSpeed = 0.0f; //룰렛을 완전 멈춤
}
}
2. 게이지 바 채우기
UI 멤버 변수를 생성하고 Update 함수 안에 fillAmount 를 사용하여 바를 채워주고 텍스트를 표시해준다.
fillAmount는 0~1의 값을 가지고 있으며 그 사이의 값을 이용해서 비율대로 이미지가 표시됩니다. 0이면 아무것도 보이지 않고 1이면 100% 다 보이게 되는 방식이다.
public class RouletteController : MonoBehavior
{
float rotSpeed = 0; //회전 속도
float m_MaxPower = 80.0f; //최대 힘(속도) 변수
public Image m_PwBarImg = null; //게이지 바 이미지 연결용 UI 변수
public Text m_PwText = null; //게이지 바 텍스트 연결용 UI 변수
:
void Update()
{
:
m_PwBarImg.fillAmount = rotSpeed / m_MaxPower; //0 ~ 1 사이 값으로 바 채워줌
m_PwText.text = (int)(m_PwBarImg.fillAmount * 100.0f) + "/100";
}
3. 숫자 값을 얻어오는 함수 생성
EulerAngle(오일러 각)을 활용하여 바늘이 가리키고 있는 숫자 값을 가져온다.
EulerAngle은 x,y,z 3개의 축을 기준으로 0~360도만큼 회전시키는 기능으로 0~359.999f까지의 값을 환산해서 전달해 준다.
a_Angle은 z축(회전축)이다.
//룰렛이 멈췄을 때 바늘이 가리키고 있는 숫자 값을 얻어오는 함수
void GetCurNumber()
{
float a_Angle = transform.eulerAngles.z;
int a_Num = 0;
if((342.0f <= a_Angle && a_Angle <360.0f) ||
(0.0f <= a_Angle && a_Angle <18.0f))
{
a_Num = 7;
}
else if (18.0f <= a_Angle && a_Angle < 54.0f)
{
a_Num = 8;
}
else if (54.0f <= a_Angle && a_Angle < 90.0f)
{
a_Num = 9;
}
else if (90.0f <= a_Angle && a_Angle < 126.0f)
{
a_Num = 0;
}
else if (126.0f <= 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;
}
룰렛이 멈췄을 때 바늘이 가리키고 있는 숫자 값을 얻어와야 하기 때문에 룰렛이 멈췄을 때 코드 밑에 GetCurNumber() 함수를 작성한다.
if(this.rotSpeed <= 0.1f)
{
this.rotSpeed = 0.0f;
GetCurNumber();
}
4. GameMgr에 있는 SetNumber() 호출하기
GetCurNumber()로 바늘이 가리키고 있는 숫자 값을 얻어왔으니 이 번호를 표시할 수 있도록 GameMgr에 있는 SetNumber() 함수를 호출한다.
GameMgr a_GameMgr = null;
GameMgr a_GObj = GameObject.Find("GameMgr"); //Hierarchy 목록에서 GameMgr 찾음
if(a_GObj != null) //잘 찾았으면
a_GameMgr = a_GObj.GetComponent<GameMgr>(); //GameMgr 스크립트를 찾아와
if(a_GameMgr != null) //스크립트를 잘 찾았으면
a_GameMgr.SetNumber(a_Num); //SetNumber 호출해줘
완성 소스
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class RouletteController : MonoBehaviour
{
float rotSpeed = 0; //회전 속도
float m_MaxPower = 80.0f; //최대 힘(속도) 변수
public Image m_PwBarImg = null;
public Text m_PwText = null;
void Start()
{
Application.targetFrameRate = 60; //실행 프레임 속도 60프레임으로 고정 시키기.. 코드
QualitySettings.vSyncCount = 0;
//모니터 주사율(플레임율)이 다른 컴퓨터일 경우 캐릭터 조작시 빠르게 움직일 수 있다.
}
void Update()
{
if(GameMgr.s_State == GameState.PowerIng)
{
// 마우스를 누르고 있는 순간 회전 속도를 설정한다.
if(Input.GetMouseButton(0)==true)
{
// 마우스가 UI 위에 있다면..
if (IsPointerOverUIObject() == true)
return;
this.rotSpeed += (Time.deltaTime * 50.0f); //속도 조금씩 증가
if (m_MaxPower < rotSpeed)
rotSpeed = m_MaxPower;
}
//마우스를 누르고 있다가 손가락을 떼는 순간
if(Input.GetMouseButtonUp(0)==true)
{
GameMgr.s_State = GameState.RotateIng; //룰렛 회전 상태
}
}
else if(GameMgr.s_State == GameState.RotateIng)
{
transform.Rotate(0, 0, this.rotSpeed); // 회전 속도만큼 룰렛을 회전시킨다.
this.rotSpeed *= 0.98f; // 룰렛을 감속시킨다.
if(this.rotSpeed <= 0.1f) //룰렛이 멈춘 상태로 판단
{
this.rotSpeed = 0.0f; //룰렛을 완전 멈춤
GameMgr.s_State = GameState.PowerIng; //다시 힘 조절 상태로 변경
GetCurNumber();
}
}
m_PwBarImg.fillAmount = rotSpeed / m_MaxPower; //0 - 1사이 값으로 바 채워줌
m_PwText.text = (int)(m_PwBarImg.fillAmount * 100.0f) + "/100";
}
//룰렛이 멈췄을 때 바늘이 가리키고 있는 숫자 값을 얻어오는 함수
void GetCurNumber()
{
float a_Angle = transform.eulerAngles.z; //회전 축
int a_Num = 0;
if ((342.0f <= a_Angle && a_Angle < 360.0f) ||
(0.0f <= a_Angle && a_Angle < 18.0f))
{
a_Num = 7;
}
else if (18.0f <= a_Angle && a_Angle < 54.0f)
{
a_Num = 8;
}
else if (54.0f <= a_Angle && a_Angle < 90.0f)
{
a_Num = 9;
}
else if (90.0f <= a_Angle && a_Angle < 126.0f)
{
a_Num = 0;
}
else if (126.0f <= 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;
}
GameMgr a_GameMgr = null;
GameObject a_GObj = GameObject.Find("GameMgr");
if (a_GObj != null)
a_GameMgr = a_GObj.GetComponent<GameMgr>();
if (a_GameMgr != null)
a_GameMgr.SetNumber(a_Num);
}
public static bool IsPointerOverUIObject() //UGUI의 UI들이 먼저 피킹되는지 확인하는 함수
{
PointerEventData a_EDCurPos = new PointerEventData(EventSystem.current);
#if !UNITY_EDITOR && (UNITY_IPHONE || UNITY_ANDROID)
List<RaycastResult> results = new List<RaycastResult>();
for (int i = 0; i < Input.touchCount; ++i)
{
a_EDCurPos.position = Input.GetTouch(i).position;
results.Clear();
EventSystem.current.RaycastAll(a_EDCurPos, results);
if (0 < results.Count)
return true;
}
return false;
#else
a_EDCurPos.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(a_EDCurPos, results);
return (0 < results.Count);
#endif
}
}
- UI 위에 마우스가 있는지? 확인하는 함수
- using UnityEngine.EventSystems; 필요
public static bool IsPointerOverUIObject() //UGUI의 UI들이 먼저 피킹되는지 확인하는 함수
{
PointerEventData a_EDCurPos = new PointerEventData(EventSystem.current);
#if !UNITY_EDITOR && (UNITY_IPHONE || UNITY_ANDROID)
List<RaycastResult> results = new List<RaycastResult>();
for (int i = 0; i < Input.touchCount; ++i)
{
a_EDCurPos.position = Input.GetTouch(i).position;
results.Clear();
EventSystem.current.RaycastAll(a_EDCurPos, results);
if (0 < results.Count)
return true;
}
return false;
#else
a_EDCurPos.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(a_EDCurPos, results);
return (0 < results.Count);
#endif
GameMgr 스크립트 작성
1. enum 열거형을 사용하여 게임의 상태를 나타낸다. 정수값 대신 사용되는 별칭 집합으로 가독성을 높여줍니다.
public enum GameState
{
PowerIng = 0, // 파워를 올릴 수 있는 상태
RotateIng = 1, // 룰렛이 돌고 있는 상태
GameEnd = 2 // 게임 종료 상태를 의미함
}
2. 로또 번호를 표시하는 SetNumber() 함수를 작성합니다.
RouletteController 스크립트 GetCurNumber 함수에서 숫자 값을 얻어온 변수 a_Num을 가져와 로또 번호를 표시해줍니다.
public class Gamemgr : MonoBehaviour
{
public static GameState s_State = GameState.PowerIng;
int m_NumCount = 0; // 로또 번호 인덱스 카운트용 변수
public Text[] NumberTexts; // 로또 번호 표시 UI 연결용 변수
:
public void SetNumber(int a_Num)
{
if(m_NumCount < NumberTexts.Length)
{
NumberTexts[m_NumCount].text = a_Num.ToString();
m_NumCount++;
if(NumberTexts.Length <= m_NumCount) //5개 번호 다 표시되면
{
s_State = GameState.GameEnd; // 게임 종료
}
}
}
3. Reset 버튼 함수를 작성합니다.
리셋 버튼을 누르면 GameScene으로 씬 전환할 수 있도록 SceneManager.LoadScene() 함수를 사용합니다.
using UnityEngine.SceneMangement;
SceneManager.LoadScene() 를 사용하기 위해서는 코드 상단에 Scene을 관리하는 SceneManagement를 추가해줍니다.
public class GameMgr : MonoBehaviour
{
:
public Button Reset_Btn = null; //리셋버튼 UI 연결용 변수
void Start()
{
s_State = GameState.PowerIng; //초기화
if(Reset_Btn != null) //Reset_Btn이 잘 연결되어 있으면
Reset_Btn.onClick.AddListener(ResetClick);
}
:
void ResetClick()
{
s_State = GameState.GameEnd; //게임 종료 상태
SceneManager.LoadScene("GameScene"); //GameScene으로 씬전환
}
}
완성 소스
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public enum GameState //정수값 대신 사용되는 별칭 집합
{
PowerIng = 0, //파워를 올릴 수 있는 상태
RotateIng = 1, //룰렛이 돌고 있는 상태
GameEnd = 2 //게임 종료 상태를 의미함
}
public class GameMgr : MonoBehaviour
{
public static GameState s_State = GameState.PowerIng; //GameState를 PowerIng로 설정
int m_NumCount = 0; //로또 번호 인덱스 카운트용 변수
public Text[] NumberTexts; //로또 번호 표시 UI 연결용 변수
public Button Reset_Btn =null;
void Start()
{
s_State = GameState.PowerIng; // 초기화
if (Reset_Btn != null)
Reset_Btn.onClick.AddListener(ResetClick);
}
void Update()
{
}
public void SetNumber(int a_Num) //숫자 등록
{
if(m_NumCount < NumberTexts.Length)
{
NumberTexts[m_NumCount].text = a_Num.ToString();
m_NumCount++;
if(NumberTexts.Length <= m_NumCount)
{
//게임 종료
s_State = GameState.GameEnd;
}
}
}
void ResetClick() //Reset
{
s_State = GameState.GameEnd;
SceneManager.LoadScene("GameScene");
}
}
'Unity' 카테고리의 다른 글
[Unity] 싱글톤 패턴 (2) | 2024.07.17 |
---|---|
[Unity] 유니티 이벤트 함수의 실행 순서 (0) | 2024.07.12 |
[Unity] Mathf.Sign() 부호 반환 함수 (2) | 2024.06.27 |
Unity Cinemachine (0) | 2024.04.20 |
[Unity] 유니티 3D 모바일 조이스틱 플레이어 움직임 (0) | 2024.04.08 |