UnityChan을 활용하여 가위바위보 게임 만들기

728x90

유니티 개발자라면 누구나 한 번씩은 다뤄본 유니티짱 패키지 파일을 활용하여 간단한 가위바위보 게임을 만들어 보려고 한다. 기본적인 게임 제작에 앞서, 유니티짱을 터치했을 때 머리/가슴 부위가 서로 다른 상호작용을 하게 세팅해보았다.

먼저 머리/가슴을 클릭하면 반응 할 수 있도록 유니티짱 모델 내 Character1_Head와 J_Mun_root_00에 박스 콜라이더를 추가해주었다. 그리고 각각 Head와 Breast로 태그를 생성해주었다. 그리고 유니티짱 - Animator - Controller에 UnityChan 애니메이터를 연결해주어 기본 세팅을 완료했다.

 

1. Touch 컨트롤

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Touch : MonoBehaviour
{

    public AudioClip voice_01; //univ_1000
    public AudioClip voice_02; //univ_1091

    private Animator animator;
    private AudioSource univoice;

    private int motionIdol = Animator.StringToHash("Base Layer.Idol");

    void Start()
    {
        animator = GetComponent<Animator>();
        univoice = GetComponent<AudioSource>();
    }

    void Update()
    {
        animator.SetBool("Touch", false); //터치 애니메이션 실행 X
        animator.SetBool("TouchHead", false);
        Ray ray;
        RaycastHit hit; //ray를 쏘았을 때 hit된 오브젝트의 정보를 가져온다
        GameObject hitObject;
        if(Input.GetMouseButtonDown(0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if(Physics.Raycast(ray, out hit, 100)) // 인자는 (시작점, 방향, 최대거리)
            {
                hitObject = hit.collider.gameObject;
                if(hitObject.gameObject.tag == "Head")
                {
                    animator.SetBool("TouchHead", true); //터치 애니메이션 실행
                    univoice.clip = voice_01; //터치 효과음
                    univoice.Play(); //실행

                    animator.SetBool("Face_Happy", true);
                    animator.SetBool("Face_Happy", false);
                }
                else if(hitObject.gameObject.tag == "Breast")
                {
                    animator.SetBool("Touch", true); //터치 애니메이션 실행
                    univoice.clip = voice_02; //터치 효과음
                    univoice.Play(); //실행

                    animator.SetBool("Face_Happy", false);
                    animator.SetBool("Face_Happy", true);
                }
            }
        }
        //재생 도중인 애니메이션이 Idol 애니메이션인지 체크
        if(animator.GetCurrentAnimatorStateInfo(0).nameHash == motionIdol)
        {
            animator.SetBool("Motion_Idle", true);
        }

        else
        {
            animator.SetBool("Motion_Idle", false);
        }
    }
}

여기서 마우스를 클릭할 때 반응한다는 개념을 Raycast로 가져왔다. 특정 부분을 마우스로 클릭했을 때, 즉 ray를 쏘았을 때 hit된 Object의 콜라이더가 반응하게 하여 명령을 호출한다는 스크립트를 작성했다. Head 태그가 걸려있는 부분(머리)을 클릭 시, univ_1000라는 오디오가 생성되면서 UnityChan 애니메이터 내 BaseLayer의 TouchHead 애니메이션이 작동하게 된다. 그리고 Breast 태그가 걸려있는 부분(가슴)을 클릭 시, univ_1091라는 오디오와 함께 Head 애니메이션이 생성되게 된다. 아무런 클릭을 하지 않으면 Idol 기본 애니메이션이 세팅된다. (지금까지 사용한 오디오 소스와 애니메이션은 유니티짱 패키지를 임포트하면 자동적으로 받아진다.)

 

2. 가위바위보 컨트롤

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class JanKen : MonoBehaviour
{
    bool flgJanken = false; //가위바위보 모드 플래그
    int modeJanken = 0;
    public AudioClip voice_janken_start;
    public AudioClip voice_janken_pon;
    public AudioClip voice_janken_goo;
    public AudioClip voice_janken_choki;
    public AudioClip voice_janken_par;
    public AudioClip voice_janken_win;
    public AudioClip voice_janken_loose;
    public AudioClip voice_janken_draw;

    const int JANKEN = 0;
    const int GOO = 1;
    const int CHOKI = 2;
    const int PAR = 3;
    const int DRAW = 4;
    const int WIN = 5;
    const int LOOSE = 6;

    private Animator animator;
    private AudioSource univoice;

    int myHand;
    int unityHand;
    int flgResult;
    float waitTime;

    public GUIStyle btStyleMode; //버튼에 이미지 설정
    public GUIStyle btStyleGoo;
    public GUIStyle btStyleChoki;
    public GUIStyle btStylePar;

    private  void Start()
    {
        animator = GetComponent<Animator>();
        univoice = GetComponent<AudioSource>();
    }
    private void OnGUI()
    {
        if(flgJanken == false)
        {
            if(GUI.Button(new Rect(10, Screen.height - 110, 100, 100), "가위바위보", btStyleMode))
            {
                flgJanken = true;
            }
        }
        if(modeJanken == 1)
        {
            if(GUI.Button(new Rect(Screen.width/2 - 120, 400, 100, 100), "바위", btStyleGoo))
            {
                myHand = GOO;
                modeJanken++;
            }
            if (GUI.Button(new Rect(Screen.width / 2, 400, 100, 100), "가위", btStyleChoki))
            {
                myHand = CHOKI;
                modeJanken++;
            }
            if (GUI.Button(new Rect(Screen.width / 2 + 120, 400, 100, 100), "보", btStylePar))
            {
                myHand = PAR;
                modeJanken++;
            }
        }
    }
    void Update()
    {
        if(flgJanken)
        {
            switch(modeJanken) //가위바위보 모드
            {
                case 0:
                    UnityChanAction(JANKEN);
                    modeJanken++; break; //가위바위보 시작
                case 1:
                    animator.SetBool("Janken", false);
                    animator.SetBool("Aiko", false);
                    animator.SetBool("Goo", false);
                    animator.SetBool("Choki", false);
                    animator.SetBool("Par", false);
                    animator.SetBool("Win", false);
                    animator.SetBool("Loose", false);
                    break; //플레이어의 입력을 기다림
                case 2:
                    flgResult = -1;
                    unityHand = Random.Range(GOO, PAR + 1);
                    UnityChanAction(unityHand);

                    if (myHand == unityHand) flgResult = DRAW;
                    else
                    {
                        switch(unityHand)
                        {
                            case GOO: if (myHand == PAR) flgResult = LOOSE; break;
                            case CHOKI: if (myHand == GOO) flgResult = LOOSE; break;
                            case PAR: if (myHand == CHOKI) flgResult = LOOSE; break;
                        }
                        if (flgResult != LOOSE) flgResult = WIN;
                    }
                    modeJanken++;
                    break; //판정
                case 3:
                    waitTime += Time.deltaTime;
                    if(waitTime > 1.5)
                    {
                        UnityChanAction(flgResult);
                        waitTime = 0;
                        modeJanken++;
                    }
                    break; //결과
                case 4: flgJanken = false;
                    modeJanken = 0;
                    break;
            }
        }
    }
    void UnityChanAction(int action) //유니티찬의 액션
    {
        switch(action)
        {
            case JANKEN:
                animator.SetBool("Janken", true);
                univoice.clip = voice_janken_start; break;
            case GOO:
                animator.SetBool("Goo", true);
                univoice.clip = voice_janken_goo; break;
            case CHOKI:
                animator.SetBool("Choki", true);
                univoice.clip = voice_janken_choki; break;
            case PAR:
                animator.SetBool("Par", true);
                univoice.clip = voice_janken_par; break;
            case DRAW:
                animator.SetBool("Aiko", true);
                univoice.clip = voice_janken_draw; break;
            case WIN:
                animator.SetBool("Win", true);
                univoice.clip = voice_janken_win; break;
            case LOOSE:
                animator.SetBool("Loose", true);
                univoice.clip = voice_janken_loose; break;   
        }
        univoice.Play();
    }
}

먼저 OnGUI() 메서드를 가져와 버튼을 제작했다. 보통은 UI - Button을 통해서 버튼 UI를 직접 제작하지만 그런 과정 없이 스크립트만으로도 제작할 수 있다. OnGUI()메서드가 기본적으로 제공하는 세부 변수들이 많기 때문에 해당 함수를 가져와서 다양한 인자를 설정할 수 있다. 먼저 bool 형식과 if문을 활용하여 가위/바위/보 조건을 세팅하고 , 가로세로 10짜리 정사각형 rec과 포지션, 그리고 btStyleMode를 오버로딩해주어 버튼 이미지까지 추가해주었다. 그리고 유니티짱이 내는 가위바위보는 unityHand라는 변수와 random.range() 함수를 선언해 주었고, 플레이어와의 승부 결과 승/패/비김 은 switch case문으로 하나씩 설정했다.

추가적으로 UnityChanAction()메서드를 새로 생성해주어 각각의 승부 결과마다 다른 애니메이션 Action과 Voice를 보여주도록 설정했다. 참고로 JanKen(가위바위보), Goo(가위) ,Choki(바위), Par(보), Aiko(비김)을 의미한다.

스크립트 작성 후 인스펙터 창의 스크립트 빈 공간에 다음과 같이 연결해주었다. BtStyleMode에서 Normal(기본 배경), Hover(마우스 커서를 버튼에 올려놓은 경우), Active(클릭한 경우)를 다음과 같이 이미지로 연결해주었다. 그리고 이렇게 할 경우 각각 버튼에 이미지와 함께 "가위바위보/가위/바위/보" 글자가 남겨지는데 이를 제거해주기 위해 인스펙터 하단 부분에 위치한 image position에서 image only로 변경해주면 된다.

아래 bt Style Goo / bt Style Choki / bt Style Par도 위와 동일하게 이미지를 연결해주고 Image Only 세팅을 해주면 끝난다.

최종적으로 다음과 같은 UI가 나오고 게임을 진행하면 설정했던 애니메이션과 오디오가 함께 출력될 것이다

728x90