본문 바로가기
프로젝트 기록부

개인프로젝트 02. - 캐주얼 웹 게임 개발

by Amins 2023. 2. 7.

Preview

Abstract

GOAL : 간단히 웹에서 즐길 수 있는 캐주얼 웹게임 개발
Benefit : 개임 개발 workflow 및 Unity 엔진 이해도 향상, 추후 게임 고도화를 통해 수익 창출 도모
Task : Unity 엔진 및 C# 프로그래밍 언어를 이용하여 게임을 개발하고, 이를 다른 유저들도 즐길 수 있게 배포

Solution Method
- Unity hub 웹앱을 이용해 각종 컴포넌트 및 게임 골격을 구현
- C# 으로 게임 내 필요한 스크립트들을 구현하고 해당하는 컴포넌트에 연결
- itch.io 웹사이트를 이용해 게임파일을 웹 게임으로 배포
- 원활환 코드 보수, 관리를 위해 클라우드에 게임 파일을 업로드
Tools
- Unity Hub
- Visual Studio code (C#)
- Github

Background

늘 게임개발자는 무엇을 하는 사람인지, 어떤 워크플로우를 가지고 있는지 궁금했다. 3D 렌더링 도구를 좋아했던 나로서는, 단순히 장면이나 캐릭터를 구현하는 것 뿐 아니라 요소들간의 상호작용 또한 구현해 보고 싶었다. 마침 주말에 시간이 생겼고, 바로 유튜브로 독학하며 제작 해 보기로 결심했다. 이 프로젝트를 통해 유니티 게임 개발 엔진을 숙달하고 워크플로우를 체험해 볼 수 있다는 점에서 의의가 깊다. 또 직접 제작한 게임을 웹사이트에 배포함으로서 유저의 피드백을 받고, 고도화시켜 수익창출에도 기여할 수 있을 것으로 기대한다.


1. 게임 구상

 

Concept

게임 컨셉과 기본적인 구상을 위해 스케치를 실시했다. 유니티 초보자 튜토리얼에 공 튀기기 게임강좌가 있어 나 또한 공을 조작해 목표지점까지 가는 형식의 게임을 구상했다. 또한 이러한 캐주얼 게임이 부담 없이 모두가 즐기기에 편할 것이라는 생각도 있었다.

 

Elements

목적지까지는 장애물들이 필요했다. 끊어진 길, 회전하는 막대나 움직이는 바닥 등을 생각했고, 유니티 엔진에서 제공하는 실시간 테스트 기능을 통해 장애물의 난이도나 갯수를 결정하고자 했다.

놀랍게도 스케치 입니다,,

Rules

맵 구성은 스테이지에 들어서면 엔드포인트를 향해 공을 조작하고, 공이 엔드포인트에 닿으면 다음 스테이지로 이동하는 방식을 채택했다. 공이 바닥으로 떨어지면 처음부터 다시 시작하는 페널티를 부여했고, 각각의 스테이지 맵을 짧게 구성했기 때문에  체크포인트는 따로 배치하지 않았다. 

 

2. 컴포넌트 제작

모든 컴포넌트는  Unity Hub에서 제작했다.

시작 페이지

시작페이지는 게임의 컨셉인 우주와 지구를 배경으로 설정해 유저에게 앞으로의 게임이 우주와 관련되어 있다는 사실을 암시한다. 시작버튼과 how to play 버튼을 화면 중앙에 배치했다.

 

how to play 상세페이지 + 버튼

How To Play 버튼을 누르면 이동하는 배경이다. 간단한 조작방법과 목표를 아이콘과 함꼐 알려주고, 메뉴로 돌아가는 버튼을 만들었다.

 

Stage 0 : introduction stage

Start 버튼을 누르면 이 맵으로 이동된다. 컴포넌트는 바닥의 역할을 하는 박스와 엔드포인트, 아이템 등을 구현했다. 첫 스테이지의 목표는 유저에게 조작과 클리어 목표를 알려주는 것이기 때문에, 별도의 어려운 장애물 컴포넌트는 배치하지 않았다.

 

Stage 1 : Easy Jump

본격적인 첫 스테이지다. 5개의 박스 컴포넌트를 만들었고, 유저가 점프를 해서 각각의 박스를 뛰어넘을 수 있게끔 거리를 조절했다. 

 

Stage 2 : Hard Jump

이 맵은 붉은 우주 배경을 도입해, 유저들에게 급격한 변화의 느낌을 부여하고자 했다. 본격적으로 어려운 난이도의 좁은 지형과 넓은 간격들로 구성했다. 

Stage 3 : Final Stage

마지막  맵이다. 중앙의 구 형태의 발판은 이동 경로의 수직 방향으로 왕복운동하고, 우측의 두개의 긴 막대는 회전하며 진로를 방해하는 역할이다. 마지막 엔드포인트 근처의 발판은 위아래로 움직여 유저가 타이밍을 맞춰 잘 올라타야 클리어 할 수 있게 배치했다. 

Stage 4 : Ending Scene

모든 스테이지를 클리어하면 다음과 같은 맵에 당도한다. 게임 컨셉에 맞게 지구에 도달한 것을 보여주는 지구 오브젝트와 엔딩 크레딧을 배치했다.

 

3. 스크립트 작성 (feat. C#) 

필요한 동작 및 상호작용이 있는 컴포넌트에는 C#을 이용해 스크립트를 작성, Unity Hub에서 연동시겼다. 유니티에서는 Visual Studio 앱을 연동하여 코드를 작성할 수 있게 도와준다. 이를 이용해 VScode의 다양한 확장 프로그램등을 이용해 더 원활한 코딩을 할 수 있다. 거의 모든 오브젝트에 스크립트가 적용되었지만, 이중 가장 중요한 공과 게임매니저에 대한 코드는 다음과 같다. 

 

Ball script

아래는 공에 대한 스크립트다. 해당 코드에서 구현된 기능은 다음과 같다.

 

  • 아이템 상호작용 관련 기능 (아이템에 공이 닿을 때 마다 카운팅 및 아이템 비활성화)
  • 점프 관련 기능 (점프 강도 조절, 더블 점프 방지)
  • 이동 기능 (방향키 입력에 따라 공 이동, 스페이스바 입력으로 점프 설정)
  • 엔드포인트 접촉시 맵 변경 기능
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;


public class Player_ball : MonoBehaviour
{
    public int itemCount;
    public float jumpPower = 10;
    public GameManagerLogic manager;
    bool isjump;
    Rigidbody rigid;
    AudioSource audio;


    //find the Gamemanager in game and attatch GameManagerLogic c# file
    void Start()
    {
        manager = GameObject.Find("GameManager").GetComponent<GameManagerLogic>();
    }

    void Awake()
    {
        isjump = false;
        rigid = GetComponent<Rigidbody>(); // bring rigidbody
        audio = GetComponent<AudioSource>();
    }

    void Update()
    {
        if(Input.GetButtonDown("Jump") && !isjump){ // for not eternal jump
            isjump = true;
            rigid.AddForce(new Vector3(0, jumpPower, 0), ForceMode.Impulse);
        }
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        float h = Input.GetAxisRaw("Horizontal"); // keyboard wasd
        float v = Input.GetAxisRaw("Vertical"); // keyboard wasd
        rigid.AddForce(new Vector3(h, 0, v), ForceMode.Impulse); //x,y,z : y is the jump = 0 now no jump

    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "floor")
            isjump = false;
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.tag == "items"){ // if collision with player
            itemCount++;
            audio.Play();
            other.gameObject.SetActive(false);
            manager.GetItemCount(itemCount);
        }
        else if(other.tag == "Finish"){
            //Next Level
            if(manager.TotalItemCount == itemCount){
                if(manager.stage == 4){
                    SceneManager.LoadScene(5);
                }
                else{
                    SceneManager.LoadScene(manager.stage+1);
                }
            }
            else{
                //Restart Game..
                SceneManager.LoadScene(manager.stage);
            }
        }

    }   

}

 

GameManager Script

게임매니저는 게임의 배경에 가상으로 존재하는 오브젝트로, 게임의 각종 설정 및 세팅 값들을 지녔다. 해당 오브젝트에서 구현한 기능은 다음과 같다.

 

  • 게임 종료 키 구현 (ESC 키로 게임 종료)
  • 아이템 획득 현황 화면 표시 구현 (Updated!)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class GameManagerLogic : MonoBehaviour
{
    public int TotalItemCount;
    public int stage;
    public Text stageCountText;
    public Text playerCountText;

     


    void Awake() 
    {
        stageCountText.text = "/ " + TotalItemCount;
    }

    public void GetItemCount(int count)
    {
        playerCountText.text = count.ToString();
    
    }

    void Update() 
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        { 
            Application.Quit();
        }
    }


    private void OnTriggerEnter(Collider other)
    {
        if(other.gameObject.tag == "Player")
        {
            SceneManager.LoadScene(stage);
        }
    }
}

 

이외에도 장애물, 지구, 카메라 등 무수한 오브젝트에 대한 코드를 작성했다. 게임 관련 모든 코드는 아래 해당 프로젝트 깃허브에 업로드 되어 있다. 

https://github.com/haminse/Unity_project/tree/main/Moon_quest/script

 

GitHub - haminse/Unity_project

Contribute to haminse/Unity_project development by creating an account on GitHub.

github.com

 

 

4. 베타 테스트

배포 전 마지막으로 주변 지인들에게 베타 테스트를 실시했다. 총 20명의 사용자들이 의견을 보내 주었고, 이에 따른 기능 추가는 다음과 같다.

 

난이도 일부 조정

일부 맵의 장애물들이 너무 어렵게 고안되어 플레이에 불편함을 주는 경우가 있었다. 특히 마지막 스테이지의 회전하는 막대 장애물이 너무 빠르게 돌아서 힘들다는 의견이 주류를 이루었고, 이에 따라 막대의 너비를 줄이고 속도를 경감시켰다.

변경후 막대 회전 속도

 

아이템 관련 기능 수정, 추가 (배치 변경, 룰 변경, 아이템 획득 현황 표시)

처음에 아이템은 그저 맵의 장식 그 이상도, 이하도 아니였다.

유저들의 플레이는 나의 예상과 매우 달랐다. 내가 예상했던 경로 외에 수많은 다른 방식으로 엔드포인트로 향하는 유저들이 종종 발생했다. 이 때문에 유저들이 내가 만든 길을 정확히 따라 올 수 있게 유도할 수 있는 방법이 필요했다. 아이템을 이용하는 것이었다. 맵에 있는 모든 아이템을 먹어야 다음 스테이지로 가게끔 룰을 변경하고 내가 원하는 경로에 아이템들을 배치하기로 했다. 이 업데이트를 통해 유저들은 아이템을 모두 먹기 위해 내가 원하는 방향으로 움직이기 시작했다. 또한 유저가 미처 보지 못하고 아이템을 놓치는 경우를 방지하기 위해, 화면 좌측 상단에 아이템 획득 현황을 표시하는 기능을 삽입했다.

좌측 상단 아이템 획득 현황 표시 기능 추가

 

5. 배포

게임 배포는 가장 간단한 itch.io 사이트를 이욯했다. 이 사이트는 게임 zip 파일 업로드를 통해 손쉬운 게임 배포를 가능하게 해준다.

Dashboard > Create new Project > Uploads > Upload the all zip files

회원 가입 후 대시보드에서 새로운 프로젝트를 추가했다. 모든 유니티 스크립트와 파일들을 zip 파일로 한데 묶어 업로드했다. 아래는 배포된 게임 주소이다.

https://aminse.itch.io/moon-quest

 

Moon Quest by aminse

Bring the moon back to Earth!

aminse.itch.io

해당 주소로 들어가면 게임이 가능하다. 로딩 시간이 조금 걸리니 주의..!

이후 코드의 유지 및 보수, 관리를 위해 깃허브에 업로드했다. 

 

 

6. Review

게임 개발의 워크플로우를 모두 체험 해 볼 수 있었다는 점에서 의미가 있었고, 유니티 엔진과 VScode를 왔다갔다 하면서 개발하는 과정이 여 타 프로그래밍과는 상이해 다소 정신없었다. 작성된 코드의 결과를 바로바로 게임 내에서 시각적으로 확인할 수 있다는 점이 매력적인 분야인 것 같다. 작은 세상을 하나하나 창조해 나가는 느낌이라 즐거웠다.

 

아쉬운 점은, 개발 전 구상 및 계획을 더 철저하게 세워야 했었다는 것이다. 기본적인 컨셉과 뼈대만 잡고 바로 개발에 착수했는데, 정확한 유저들의 니즈나 행동 양식에 대한 예상이 빗나가 코드 및 게임 구조를 수정하는 데 많은 시간이 할애되었다. 개발 전 유저 설문이나 마켓 리서치 등을 통해 어떤 니즈가 있는지, 어떤 요소들이 필요한지를 생각 이상으로 상세하게 파악해야겠다고 느꼈다. 

게임 페이지에 달린 리뷰

배포 후 한 유저가 코멘트를 달아주었다.(감사하게도..!) 카메라는 플레이어 공의 뒷면에 고정해서 부착했는데, 이 때문에 조작 시 약간의 답답함을 느꼈던 것 같다. 추후 업데이트는 카메라 각도를 옮길 수 있는 기능을 추가해 봐야겠다. 

 

댓글