본문 바로가기
Hello, World!/Unity

유니티 2D 런게임을 만들자(9)

by 27일 낮 2022. 3. 16.
728x90

[ UI/UX 를 신경써보자 ]

 

 

 

에셋 스토어에서 다운받자!

2D Pixel Item Asset Pack (링크)

 

 

 

유니티에서 다운 받은 에셋 가져오는 법

Window - Package Manager

 

 

해당 에셋 Download 눌러주면 저렇게 Import / Re-Download로 바뀜!

Import 해주면 된다

(Import는 내 프로젝트에 삽입하는 것!)

 

 

 

필요한 것만 가져오자

최상단 2D Pixel Item Pack 체크 해제해주면 선택이 전부 해제됨!

필요한 거 체크하고 Import를 눌러주자

 

 

 


UI부터 구현해보자

버튼을 구현해보자 ! ! !

 

 

UI는 캔버스 내부에 만들기 때문에 Canvas - UI - Panel 생성

패널은 하나하나 그룹 개념으로 사용한다

 

 

이름은 HP Panel로 해주고 

앵커프리셋을 Top - Right 으로 설정해준다

(Alt + Shift 눌러주면 됨)

 

 

 

사이즈는 150 * 50 으로 해주고, 위치를 맞춰주자

 

패널을 만들면 기본적으로 이미지 패널이 들어가 있음

이쪽 구역은 무엇이 들어간다고 사용자한테 구분해서 보여줄 수 있음!

 

 

색상도 바꿔도 됨!

투명도 125로만 설정해주었다

 

 


 

남은 생명 표시! 하트 이미지를 첨부해줄거임

 

HP Panel 안에 Heart Image란 이름의 이미지 생성

 

 

앵커 프리셋 middle + left 로 맞춰줌!

 

 

Source Image 에 하트 이미지를 넣어주자

Set Native Size를 눌러서 원래 사이즈로 맞춰준 후 사이즈 조정하자

 

 

 

이제 텍스트를 만들어보자

이름은 HP Count

앵커 프리셋으로 middle + right 로 기준 잡아줌

 

 

 

위치 조정, 텍스트 작성, 폰트, 사이즈, 정렬을 맞춰준다

 

 


 

메뉴 버튼을 만들어보자

Canvas 안에 UI - Button 생성

이름은 Menu Button

 

 

메뉴 버튼 이미지를 Source Image에 넣어주자

앵커프리셋은 Top + Left 

Set Native Size 적용 후 원하는 사이즈와 위치로 변경해준다

 

 

 

 

Button을 생성하면 Image와 Button이 기본으로 있다

그리고 Button 컴포넌트에는 On Click이라는 이벤트가 존재한다!

유니티를 시작할 땐 내가 설계한 대로 플레이 되는 것뿐임

사용자가 게임 진행 중 무언가를 클릭하거나 반영을 시킨다는 건 이벤트 요소임

이러한 모든 걸 유니티에선 이벤트라고 한다

 

한번 클릭했을 때 발생되는 이벤트 라서 On Click임

 

 

 

Button에는 Transition이 있음

얘는 버튼 관련 각각의 상황들에 대한 변화를 설정할 수 있음!

None, Color Tint, Sprite Swap, Animation 이 있다.

 

 

 

Color Tint를 봐보자

색을 입히는 거라고 생각하면 됨

Highlighted Color, Pressed Color, Selected Color를 바꿔보았다

 

 

우선 Highlighted Color는, 해당 버튼 위에 마우스를 갖다대면 변화한다

 

 

 

Pressed Color : 버튼을 꾸우우욱 누르고 있을 때

 

 

 

Selected Color : 눌렀을 때

 

 

 

Sprite Swap 을 봐보자

얘는 이미지를 넣어서 바꿀 수 있다

 

 

 

Animation

애니메이션도 가능

 

 

 

우린 걍 None으로 하자


이제 메뉴를 만들어보자

Canvas에 Menu Panel 생성

 

메뉴창을 전체적으로 덮어주자

앵커 프리셋은 stretch + stretch

 

 

Menu Panel 안에 Restart Button 생성 그 안에 Text 도 생성해줌

수정할거 하고 그대로 복사해서 Exit Button을 만들어줌

이제 Menu Panel 체크 해제하자

 

 


메뉴를 키는 스크립트를 작성하자!

 

GameManager.cs

...
public class GameManager : MonoBehaviour
{
    ...
    public GameObject menuPanel;
    
    ...
        public void OnMenu()
    {
        menuPanel.SetActive(true);
    }
}

 

 

 

Menu Button의 Button - On Click에 +를 누르고 

오브젝트화 되어있는 GameManager를 넣어줌

그리고 function에 GameManager - OnMenu() 눌러줌

 

 

GameManager의 Menu Panel 에 할당해줌

 

플레이를 해보자!

메뉴를 누르면 창이 뜬다~ 힛힛

 

 

 

이제 메뉴 끄는 걸 해보자

GameManager.cs 

...
	public void OnMenu()
    {
        ...
    }

    public void OffMenu()
    {
        menuPanel.SetActive(false);
    }
}

Menu Panel에 Button컴포넌트를 추가해주고

On Click에 추가해줌

 

 

 

그럼 메뉴를 눌렀을 때 Restart, Exit를 제외한 부분을 누르면 메뉴가 나가진다!

 

 

이제 게임 일시정지도 해보자!

플레이 하면 유니티엔진의 시간이 1배속으로 재생되고 있는 것을 의미함

 

우리는 메뉴를 눌렀을 때 재생속도를 0이 되도록 바꿔주면 된다

 

GameManager.cs

    public void OnMenu()
    {
        menuPanel.SetActive(true);
        Time.timeScale = 0f;
    }

    public void OffMenu()
    {
        menuPanel.SetActive(false);
        Time.timeScale = 1f;
    }

(기본 재생 속도가 1임)

 

 

플레이 해보면 메뉴를 들어가면 게임 화면이 멈추고,

메뉴를 나갔을 때 게임 화면이 다시 재생된다!

 


 

이제 Restart 버튼과 Exit 버튼을 활성화 해보자

 

 

Exit부터 해보자

...
    public void OffMenu()
    {
		...
    }

    public void Exit()
    {
        Application.Quit();
    }
}

근데 이거는 유니티 안에서는 적용이 안되고 빌드 후에 확인할 수 있음!

apk 깔아서 해보면 꺼짐

 

 

 

Exit Button에 연결하자

 

 

 

Restart 해보자

...
	public void OffMenu()
    {
        ...
    }

    public void Exit()
    {
        ...
    }

    public void Restart()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        Time.timeScale = 1f;
    }
}

메뉴를 누른 후 플레이 속도가 0인 상태였음

그래서 Restart를 했을 때 플레이 속도를 1로 다시 바꿔줘야 함!

 

 

Restart Button의 On Click에 적용해줌

 

 

와 그럼 모든 버튼 완성!

근데 이렇게 하나하나 메서드로 만들면 귀찮잖아여

다른 방법????

 

 

    public void MenuPanelControl(bool isActive)
    {
        menuPanel.SetActive(isActive);
    }

메뉴패널 관련 메서드를 이렇게 boolean 형식으로 써서

On Click에 추가하고 true/false 체크해서도 가능함

 

 

 

또는, 지금 만든 모든 걸 switch문으로도 작성해도 됨

public void UIControl(string type)
    {
        switch (type)
        {
            case "menuOn":
                menuPanel.SetActive(true);
                Time.timeScale = 0f;
                break;
            case "menuOff":
                menuPanel.SetActive(false);
                Time.timeScale = 1f;
                break;
            case "restart":
                SceneManager.LoadScene(SceneManager.GetActiveScene().name);
                Time.timeScale = 1f;
                break;
            case "exit":
                Application.Quit();
                break;
        }
    }

 

 

그래서 On Click엔 이런 식으로!!!!

 

 


스크립트를 안쓰고 UI 구성하기도 해보자!

Restart, Exit 는 어쩔 수 없이 스크립트 적어야함

 

 

On Click에서 직접 컨트롤할 오브젝트 자체를 연결해주면 됨!

Menu Button의 Button - On Click에 Menu Panel을 연결하자

그리고 function에 SetActive(bool)을 눌러주면 됨

 

 

체크를 해줘야 SetActive(true)가 됨!

그럼 Menu Button을 눌렀을 때 Menu Panel이 보이겠죵

 

 

메뉴창 끄기는

Menu Panel의 Button - On Click에 Menu Panel을 넣으면 됨

그리고 체크 해제하여 false로 만들어준다!

 

 

활성/비활성! 굿굿

 

근데 우린 게임 멈추고도 해야하니까

실행시킬 기능이 여러개니까 소스코드를 작성하는 게 좋음

 

근데 머 여기선 On Click에 작성해주었던걸 추가해주면 됨 ㅎㅎ

 

 


이제 생명 깎는거 해보자

 

 

UI는 GameManager에서 하고있음

GameManager.cs

public class GameManager : MonoBehaviour
{
    ...

    public GameObject menuPanel; // 메뉴 패널 변수

    public int hpCount = 2; // 실제 사용자 생명력
    public Text hpText; // 사용자에게 보여질 생명력 UI
    
    private void Awake()
    {
    	...
    }
    
    private void Start()
    {
        // 사용자에게 보여질 생명력을 실제 생명력으로 등록
        hpText.text = hpCount.ToString();
    }
    
    ...

 

 

발판에서 떨어지면 데드존에 닿아 죽는 건 그대로 두고,

장애물을 밟으면 생명이 깎여서 2~3번 정도는 봐주고 싶음

 

근데 뭘 밟은지 어케 앎? = 태그!

 

현재 장애물, 데드존 둘다 Dead 태그를 달고 있다!

장애물 태그를 바꿔주자

 

Platform 프리팹 ㄱㄱ

Spark 태그 추가하자

 

 

장애물들 태그를 Spark로 다 바꿔줌

 

 

PlayerController.cs 

private void OnTriggerEnter2D(Collider2D collision)
    {
        // 트리거 콜라이더를 가진 장애물과의 충돌 감지

        // 충돌한 상대방의 태그가 Dead 이면서, 아직 사망하지 않았다면
        if (collision.tag == "Dead" && !isDead )
        {
            ...
        }
        else if (collision.tag == "Spark" && !isDead)
        {
			...
        }

OnTriggerEnter2D 안에 else if문을 추가해주었다.

닿았는데, 태그가 Spark이고 죽은 상태가 아니라면? 피가 깎여야 함

얘는 게임매니저에서 적어주자

 

 

GameManager.cs

    public void Crash()
    {
        //hpCount--;
        //hpText.text = hpCount.ToString();

        hpText.text = ""+--hpCount;
    }

주석 처리된 거로 써도 됨! 같은 의미임

--hpCount는 연산이기 때문에 ToString()이 안 먹음

그래서 ""를 붙여준 것!

 

 

 

다시 PlayerController.cs에 돌아와서 게임오브젝트에 있는 Crash에서 실행시켜줌

    private void OnTriggerEnter2D(Collider2D collision)
    {
        ...
        else if (collision.tag == "Spark" && !isDead)
        {
            GameManager.instance.Crash();
        }

 

 

GameManager의 Hp Text에 HP Count를 할당해주자

 

 

 

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

계속 마이너스 됨

 

 

 

플레이어가 죽는다는 처리는 플레이어 컨트롤러가 가지고 있음!

 

 

GameManager.cs

    public bool Crash()
    {
        //hpCount--;
        //hpText.text = hpCount.ToString();
        hpText.text = "" + --hpCount;
        if (hpCount <= 0) return true;
        return false;
    }

void는 메서드를 만들 때 반환형식 없으면 void라고 명시

반환형식이 있다면 void대신 데이터 타입 적어주기! 여기선 bool

 

 

PlayerController.cs

    private void OnTriggerEnter2D(Collider2D collision)
    {
        ...
        if (collision.tag == "Dead" && !isDead )
        {
            ...
        }
        else if (collision.tag == "Spark" && !isDead)
        {
            if (GameManager.instance.Crash()) Die(); 
            
        }

GameManager.cs에서 hpCount가 0보다 같거나 작게 되면 true를 출력하게 해놨기 때문에

else if문에 if문을 넣어서 true면 Die()가 실행되게 했음!

 

 

 

+

전처리기 지시어

 

유니티 조건부 컴파일(Conditional Compilation) (링크)

C# preprocessor directives (링크)

댓글