본문 바로가기

개발일지

[Unity] 'Toms And Jerry' - 1인 미니게임개발기

#1 어떻게 하게 됐나?

#2 'Toms And Jerry' 인 이유

#3 게임 룰 및 조작법

#4 소스코드 리뷰

#5 게임플레이

#6 느낀점






#1 어떻게 하게 됐나?


 대학교에서 진행하는 특강을 한달동안 들으며, 결과물을 내고 싶어 만들었습니다. '안드로이드스튜디오', 'JavaFx', 'Unity' 를 맛보기로 배운 정도인데 그중에 가장 마음에 드는 툴이 Unity 였다. C#언어를 사용한다고 했지만 Java와 별 다른 점이 없었고, 객체지향언어이다보니 다가가기 쉬웠습니다. 3D게임개발이라는게 어렵게 느껴졌지만 한자리에서 공부를 한다고 잘 응용하는 타입이 아니고 부딪혀보고 에러에 익숙해지면서 성장해나가는 타입이라 그냥 부딪혀봤습니다.




[ Unity ]



#2 'Toms And Jerry'인 이유


 처음에 게임으로 정하기로했고, 미니게임을 좋아해서 미니게임을 만들게 되었습니다. 게임 스타일은 Unity 사이트 내에 Learn 이라는 게임개발예제들이있는데 그중에 'Survival Shooter'와 'Roll - A - Ball' 를 섞었습니다. 톰과 제리가 떠올라서 게임으로 어떻게 만들까 하다가 제리가 치즈를 좋아해서 치즈를 먹는걸로 만들면 좋겠다는 생각으로 만들었습니다. 톰은 제리를 따라다니지만 톰이 한마리이면 재미 없을것 같기도해서 톰은 여러마리로 만들었습니다. 

그래서 'Tom And Jerry'가 아닌 'Toms And Jerry' 입니다.





[Survival Shooting]

몬스터가 나오면 플레이어는 총을 쏴서 몬스터를 죽이는 게임이다.




[Roll a Ball]

공을 굴려서 노란색 큐브들을 먹는 게임이다.



# 게임 룰 및 조작법


[1]  게임이 시작되면 제리(Player)는 톰(Enemy)들을 피해서 치즈를 옮긴다.

[2]  치즈의 개수는 게임 스테이지마다 상이하다.

[3]  제리(Player)는 따라오는 톰(Enemy)를 막기위한 '벽'을 세울 수 있다. 

[4]  벽의 개수는 3개까지이며 3개가 세워지고 4개째를 세우려한다면 처음에 만들었던 벽이 제거되고 새로 생성된다.


방향키 : WASD / 방향키

마우스 좌클릭 : 벽 세우기





# 소스코드 리뷰 ( C# )


[EatCheese.cs]

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class EatCheese : MonoBehaviour {
	public Text chzText;
	public Text winText;
	private int chzCount;
	private int chzCountMax;
	private GameObject[] findChzCountMax;
	AudioSource audio;

	// Use this for initialization
	void Start () {
		chzCount = 0;
		findChzCountMax = GameObject.FindGameObjectsWithTag ("Cheese");
		chzCountMax = findChzCountMax.Length;
		chzText.text = "Cheese : " + chzCount.ToString ();
		audio = GetComponent<AudioSource> ();
	}

	void OnCollisionEnter(Collision col)
	{
		if (col.collider.tag == "Cheese")
		{
			audio.Play ();
			chzCount = chzCount + 1;
			SetChzCount ();
			if (chzCount == chzCountMax)
			{
				SetWinText ();
			}
			Destroy (col.gameObject);
		}
	}
	void SetChzCount()
	{
		chzText.text = "Cheese : " + chzCount.ToString ();
	}
	void SetWinText()
	{
		winText.text = "Jerry Win!";
		NextStage ();
	}
	void NextStage()
	{
		string nowStage;
		string nextStage;
		string nowStageNum;
		int nextStageNum;
		string nextStageStr;

		Scene scene = SceneManager.GetActiveScene(); 
		nowStage = scene.name;
		nextStage = "Stage0";
		nowStageNum = nowStage.Substring (nowStage.Length - 1);
		nextStageNum = int.Parse (nowStageNum);
		if (nextStageNum <= 6)
		{
			nextStageNum += 1;
			nextStageStr = nextStageNum.ToString ();
			nextStage += nextStageStr;
			SceneManager.LoadScene (nextStage);
		}
		if (nextStageNum == 7)
		{
			winText.text = "TOMS AND JERRY! END";
		}
	}
}



제리의 집이 치즈와 충돌을 하면 발생하는 이벤트를 담은 소스코드입니다.


void Start() 라는 메서드는 시작시에 초기화를 이루는 메서드이다. 그래서 초기화 작업들을 해주었습니다.

void OnCollisionEnter() 충돌시 이벤트 처리입니다. '제리의 집'이 치즈를 먹는 것이기 때문에 제리의 집과 치즈사이의 충돌을 처리햇습니다.


void SetChzCount()

void SetWinText() 

치즈카운트와 승리텍스트를 관리하는 메서드


[PlayerControl.cs]

 using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
using UnityEngine.SceneManagement;


public class PlayerControl : MonoBehaviour {
	public Text health;
	public Text winText;
	AudioSource audio;

	private int hp;
	// Use this for initialization
	void Start ()
	{
		hp = 20;
		health.text = "Health : " + hp.ToString ();
		winText.text = "";
		audio = GetComponent<AudioSource> ();
	}
	
	// Update is called once per frame
	void Update () {
		
	}
	void OnTriggerEnter(Collider col)
	{
		if (col.tag == "Enemy" && hp >= 1) 
		{
			hp = hp - 1;
			if (hp == 0)
			{
				winText.text = "Jerry Lose!";
			}
			audio.Play ();
			SetHealth ();
		}

	}

	void SetHealth()
	{
		health.text = "Health : " + hp.ToString ();
	}
	public void Restart()
	{
		Scene scene = SceneManager.GetActiveScene(); 
//		Scene scene = SceneManager.LoadScene("Stage02");
		SceneManager.LoadScene(scene.name);
	}
}


제리(Player)를 움직이면 발생되는 이벤트를 담은 소스코드입니다.


void OnTriggerEnter() 라는 메서드는 톰(Enemey)과 충돌시 hp를 깎는 메서드이며 깎이면 SetHealth()를 통해 Text로 표현됩니다.

void SetHealth()  라는 메서드는 화면에 제리(Player)의 Hp를 표시해줍니다.



[PlayerCreateWall.cs]

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

public class PlayerCreateWall : MonoBehaviour {
	public GameObject wall;
	private int limit;
	private List<GameObject> walls;
	// Use this for initialization
	void Start () {
		walls = new List<GameObject> ();
		limit = 0;
	}

	// Update is called once per frame
	void Update () {
		if (Input.GetMouseButtonDown (0))
		{
			if (limit < 4)
			{
				limit += 1;
				GameObject g = Instantiate (wall, transform.position, transform.rotation);
				walls.Add(g);
			}
			if (limit >= 4)
			{
				GameObject g = walls[0];
				walls.Remove (g);
				Destroy (g);
				limit -= 1;
			}
		}
	}
}


PlayerCreateWall.cs에는 3개의 벽이 생기고 4개째를 생성할때 첫번째 생성했던 벽이 지워지는 알고리즘이며, Update()함수에 담았습니다.


void Update() 는 매 프레임마다 호출이 되는 함수입니다. 


Input.GetMouseButtonDown(0) 을 하게되면 마우스 왼쪽클릭을 했다는 뜻입니다.

Instantiate 함수는 게임 실행중에 생성시키고 싶은 prefab을 넣어줍니다. 




# 게임플레이



[초기 실행 화면]

좌측 상단 : restart버튼

우측 상단 : Player의 hp, 제리의 집에 넣은 치즈의 개수



[벽을 생성한 Player]

총 세개 까지 만들 수 있고, 세개 이상이 되면 만든 순서대로 제거되고 새로 생성



[Player Hp가 0이 된 화면]

화면 중앙에 Jerry Lose! 라는 문구가 생성, restart버튼으로 재시작



[치즈를 다 먹은 이후 다음 단계로 넘어간 모습]

총 7단계까지있으며 7단계는 Ending이다.





# 느낀점


 Unity에서 캐릭터 모델링은 'magica voxel'이라는 픽셀 툴로 만들었습니다. 


Magica Voxel 다운로드 : https://ephtracy.github.io/


Unity와 C#이라는 새로운 언어와 개발툴이었지만 좌충우돌 그냥 부딪혀봤는데 재미있었습니다. 항상 콘솔로만 결과를 보다가 표현이 되니 정말로 게임이구나 라는 생각도 들었고, 비록 퀄리티가 낮은 게임이지만 여러가지로 배운게 된것, 알게된것이 많아 좋았고, 겁먹지않고 무작정 부딪혀보는 것이 정답이라는 생각이 들었습니다. 감사합니다.


Download Link : http://goo.gl/Xnrywo


BGM은 좋아하시는 음악 틀으시면서 하시면 됩니다 ㅎㅎ


'개발일지' 카테고리의 다른 글

[Web] Twitter 개발기  (0) 2018.10.02
[개발일지] '용사가 되자' part 3  (0) 2018.01.16
[개발일지] '용사가 되자' part 2  (0) 2018.01.08
[개발일지] '용사가 되자' part 1  (0) 2018.01.07