김김김의 게임개발
  • Unity 게임 개발 #4 - 고양이 밥주기 슈팅 게임<catvsdog>
    2023년 07월 31일 20시 59분 41초에 업로드 된 글입니다.
    작성자: noun06

    유니티를 사용하여 개발한 고양이 밥주기 슈팅 게임입니다.


    1. 기본 씬 세팅

    • 메인 씬 및 메뉴 씬 세팅.

     

    2. 투사체 쏘기

    • 투사체 프리팹 생성 후 위로 발사, 화면 밖으로 나갈 시 비활성화.
    //food.cs
    
    void Update()
    {
    	transform.position += new Vector3(0.0f, 0.5f, 0.0f); //y축 방향으로만 이동
    	if (transform.position.y > 26.0f)
    	{
    		Destroy(gameObject);
    	}
    }

     

    3. 투사체 세팅

    • 변수 food, dog 선언 후, dog 오브젝트의 위치 값에 따라 food를 생성하는 makeFood() 함수 생성.
    • InvokeRepeating()을 통해 0.2 마다 계속 함수 실행.

    • Quaternion은 유니티에서 사용되는 각도의 단위로, 회전을 표현하기 위해 사용되는 구조체.
    • Quaternion.identity는 회전 없음을 의미함(프리팹의 원래 회전각도만을 적용함).

    //gameManager.cs
    
    public GameObject dog;
    public GameObject food;
    
    void Start()
    {
        InvokeRepeating("makeFood", 0.0f, 0.09f); //투사체 연사 조절
    }
    
    void makeFood()
    {
        float x = dog.transform.position.x;
        float y = dog.transform.position.y + 2.0f;
        Instantiate(food, new Vector3(x, y, 0), Quaternion.identity);
    }

     

    4. 플레이어 움직이기

    • 마우스 위치값 중 x위치에 따라 플레이어인 dog를 이동.
    • -8.5f ~ 8.5f의 범위 내에서만 움직일 수 있도록 설정.
    //dog.cs
    
    void Update()
    {
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    
        float x = mousePos.x;
    
        if (x > 8.5f)
        {
            x = 8.5f;
        }
        if (x < -8.5f)
        {
            x = -8.5f;
        }
    
        transform.position = new Vector3(x, transform.position.y, 0);
    }

     

    5. 적 프리팹 세팅

    • normalCat / fatCat 두가지 타입의 적 오브젝트 생성 및 애니메이션 세팅 후 프리팹화.
    • 에너지 바 UI 생성, 이 때 pivot 값 조정을 통해 오브젝트의 기준점 변경.

     

    6. 적 이동

    • 랜덤한 x 위치에서 적 생성, 30.0f의 y 위치 화면 밖에서 내려오게 하기.
    //cat.cs
    
    void Start()
    {
    	float x = Random.Range(-8.5f, 8.5f);
    	float y = 30f;
    	transform.position = new Vector3(x, y, 0);
    }
    
    void Update()
    {
    	transform.position += new Vector3(0.0f, -0.5f, 0.0f);
    }

     

    7. 적 에너지 채우기

    • food gameobject에 rigidbody와 collider 세팅 후 rigidbody의 body type을 kinematic 으로 변경(중력의 영향 x).
    • collider의  isTrigger에 체크하여 중력이 없는 상황에서 충돌 감지하게 하기.

    • isTrigger 속성을 체크하면 충돌 감지는 되지만 물리적 충돌은 발생하지 않음.
    • OnTriggerEnter : 트리거와 물체가 충돌할 때 한 번 실행
    • OnTriggerStay : 트리거와 물체가 충돌하는 동한 실행
    • OnTriggerExit : 트리거와 물체의 충돌이 끝날 때 한 번 실행

    • 에너지가 full 값보다 작을 때 food와 충돌 시 에너지가 1.0f 만큼 증가하고 food 오브젝트 파괴.
    • 에너지 바의 x scale을 enrgy/full 값으로 조절.
    • 게이지가 모두 찼으면 hungry 오브젝트 비활성화, full 오브젝트 활성화.
    //cat.cs
    
    float full = 5.0f;
    float energy = 0f;
    
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "food")
        {
            if(energy < full) 
            {
                energy += 1.0f;
                Destroy(collision.gameObject);
                gameObject.transform.Find("hungry/Canvas/front").transform.localScale = new Vector3(energy/ full, 1.0f, 1.0f);
            }
            else
            {
                gameObject.transform.Find("hungry").gameObject.SetActive(false);
                gameObject.transform.Find("full").gameObject.SetActive(true);
            }
        }
    }

     

    • 에너지가 full인 경우 x 좌표에 따라 적 오브젝트 왼쪽 혹은 오른쪽으로 이동 후 3초 뒤 삭제.
    //cat.cs
    
    void Update()
    {
    	if (energy < full)
    	{
    		transform.position += new Vector3(0.0f, -0.5f, 0.0f);
    	}
    	else
    	{
    		if (transform.position.x > 0)
    		{
    			transform.position += new Vector3(0.5f, 0.0f, 0.0f);
    		}
    		else
    		{
    			transform.position += new Vector3(-0.5f, 0.0f, 0.0f);
    		}
    		Destroy(gameObject, 3.0f);
    	}
    }

     

    • 적이 1초마다 계속 생성하는 makeCat() 함수 생성.
    //gameManager.cs
    
    public GameObject normalCat;
    
    void Start()
    {
    	InvokeRepeating("makeFood", 0.0f, 0.2f);
    	InvokeRepeating("makeCat", 0.0f, 1.0f);
    }
    
    void makeCat()
    {
    	Instantiate(normalCat);
    }

     

    8. 게임 종료

    • 게임 재시작 함수 ReGame()생성 및 버튼 생성.
    //retryBtn.cs
    
    using UnityEngine.SceneManagement;
    
    public void ReGame()
    {
        SceneManager.LoadScene("MainScene");
    }

     

    • gameManager 싱글톤화 후 재시작 버튼을 활성화하는 gameOver() 함수 생성.
    //gameManager.cs
    
    public static gameManager I;
    
    public GameObject retryBtn;
    
    void Awake()
    {
    	I = this;
    }
    
    public void gameOver()
    {
    	retryBtn.SetActive(true);
    	Time.timeScale = 0.0f;
    }

     

    • 적 오브젝트가 -16.0f의 y 값 이하로 이동하면 gameOver() 함수 호출.
    //cat.cs
    
    void Update()
    {
    	if (energy < full)
    	{
    		//...
    		if (transform.position.y < -16.0f)
    		{
    			gameManager.I.gameOver();
    		}
    	}
    }

     

    9. 레벨 구성

    • 레벨 UI 생성 및 세팅.
    • 특정조건에 의한 레벨 로직, 레벨을 올리는 addCat() 함수 생성.
    //gameManager.cs
    
    int level = 0;
    int cat = 0;
    
    public void addCat()
    {
    	cat += 1;
    	level = cat / 5;
    }

     

    • 적이 full인 상태일 때 addCat() 함수 호출.
    • 상태 변수 isfull 선언 후, false인 상황에서 addCat() 호출 및 상태값 전환.
    //cat.cs
    
    bool isFull = false;
    
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "food")
        {
            if(energy < full) 
            {
                //...
            }
            else
            {
                if (isFull == false)
                {
                gameManager.I.addCat();
                //...
                isFull = true;
                }
            }
        }
    }

     

    • levelText와 levelFront 변수 선언 후 레벨업 될 때 마다 레벨 UI 값 증가. 
    //gameManager.cs
    
    public Text levelText;
    public GameObject levelFront;
    
    public void addCat()
    {
        cat += 1;
        level = cat / 5;
        levelText.text = level.ToString();
        levelFront.transform.localScale = new Vector3((cat - level *5) /5.0f,1.0f,1.0f);
    }

     

    • 적 타입 변수 선언 후 fatCat 프리팹을 타입 1로 지정.
    • 타입 1일 때 full 에너지를 10으로 세팅, 속도를 -0.03f으로 세팅.
    //cat.cs
    
    public int type;
    
    void Start()
    {
        float x = Random.Range(-8.5f, 8.5f);
        float y = 30f;
        transform.position = new Vector3(x, y, 0); 
    
        if (type == 1)
        {
            full = 10.0f;
        }
    }
        
    void Update()
    {
        if (energy < full)
        {
            if (type == 0)
            {
                transform.position += new Vector3(0.0f, -0.05f, 0.0f);
            }
            else if (type == 1)
            {
                transform.position += new Vector3(0.0f, -0.03f, 0.0f);
            }
            else //타입 0, 1이 아닐 시 속도가 더 빠름
            {
                transform.position += new Vector3(0.0f, -0.1f, 0.0f);
            }
            //...
        }
        else
        {
            //...
        }
    }

     

    • 레벨 값에 따라 고양이 생성 수 증가, 레벨 3 이상일 시 fatCat 출현, 4 이상일 시 pirateCat 출현.
    //gameManager.cs
    
    void makeCat()
    {
        Instantiate(normalCat);
    
        if (level == 1)
        {
            float p = Random.Range(0, 10);
            if (p < 2) Instantiate(normalCat);
        }
        else if (level == 2)
        {
            float p = Random.Range(0, 10);
            if (p < 5) Instantiate(normalCat);
        }
        else if (level == 3)
        {
            float p = Random.Range(0, 10);
            if (p < 6) Instantiate(normalCat);
            Instantiate(fatCat);
        }
        else if(level >= 4)
        {
            float p = Random.Range(0, 10);
            if(p < 6) Instantiate(normalCat);
            Instantiate(pirateCat);
        }
    }

     

    10. 버그 잡기

    • Replay 버튼 클릭 후 총알 발사 안되는 버그 발생.
    • 게임 시작 시 timeScale을 1.0으로 세팅하여 해결.
    //gameMaanger.cs
    
    void Start()
    {
        time.timeScale = 1.0f;
        //...
    }

     

    11. 결과물

     

     

    댓글