본문 바로가기
메타버스기반게임콘텐츠기획/그날의 강의

(10-1) 유니티unity 클리커 게임 만들기 - 버튼을 누르면 골드를 획득하는 스크립트

by Queenut 2021. 12. 27.

 * 클리커 게임에 필요한 기능.

- UI(User Interface)로 화면을 표시해줌(버튼, 텍스트 출력)

  - 무엇을 출력? 현재 골드량, 클릭시 획득 가능한 골드, 초당 획득 골드

- 무엇을 만들 것? 부위별 업그레이드-클릭 당 골드량을 증가

                       아이템 업그레이드: 초당 골드량을 증가.

- 저장/불러오기 기능

  - 그러기 위해? 각종 공식 활용, 스크립트와 UI간의 기능 연결

   >> 버튼 UI 만들고, 중앙에 둔 후, 클릭버튼이라는 C# Script를 만든다.

 

 

 

C#은 3단계로 이뤄져 있다.

Namespace 여러 개의 Class를 제작해서 대표 이름을 붙임.
Type 구조. Structure. 문서의 형식. class도 타입의 일종이다. class, Struct, Enum, Inerface, Delegate...
Member Field(변수), Method(function), Property, Event...

 

(컴포넌트를 조립하면 게임오브젝트가 된다.)

 

 

 * "버튼을 누르면 일정 골드를 획득한다"는 Script를 만든다면?

 - 만들기 위해 필요한 것들

 1. 기존 골드

 2. 클릭 당 골드

 3. 기능1. 클릭을 체크할 수 있는 기능

 4. 기능2. 클릭 당 획득 가능한 골드량

 5. 기능3. 기존 골드의 변화

 6. 기능4. 기존 골드 표시 변경

 

 

 

 - 먼저, DataController Script를 만든다.

Hierarchy에 Empty Object를 만들어서 헷갈리지 않도록 스크립트와 같은 이름을 붙여주자.

 : 스크립트가 늘어날 수록 각각의 스크립트마다 생기는 변수가 어마어마하게 늘어난다. 때문에 변수들을 통합관리해서 보다 쉽게 제어하는 것이 좋다. 필요할 때마다 이 오브젝트를 넣어 사용할 수 있으니 훨씬 편하다!

 

 

아래는 DataController 스크립트 내용.

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

namespace. 여러가지 클래스 및 구조체 등을 묶은 네임스페이스를 불러온다 - 라이브러리 호출

 

 - using System.Collections : "Collections자료구조 클래스를 가져온다."

 : Object형식을 사용해 데이터를 관리한다. 박싱(Object로 형변환 되는 것)과 언박싱(Object에서 원래 타입으로 변환하는 것.)이 발생해서 하도 오류가 많다보니 C#에서는 사용하지 않는다. 이 문장을 지워도 실행에는 문제가 없다...

 

 - using System.Collections.Generic: "Collections.Generic자료구조 클래스를 가져온다."

 : 데이터 형식을 일반화하여 사용하기 때문에 Collections보다 성능 저하가 적다. 형변환을 거치지 않는다.

 

 - using UnityEngine : "UnityEngine의 API(컴퓨터 프로그램 사이의 연결 서비스)를 가져온다."

 : API를 가져왔기 때문에, 직접 새로 만들지 않고도 유니티엔진 내의 여러가지를 가져와 사용할 수 있게된 것이다. 스크립팅 API는 너무 많기 때문에 일일이 외우기보단 검색하는 것이 낫다.

 

 아래는 유니티 공식 사이트, API 목록. 버전별로 조금 다르다.

https://docs.unity3d.com/kr/530/ScriptReference/index.html

 

Unity - 스크립팅 API:

Welcome to the Unity Scripting Reference! This section of the documentation contains details of the scripting API that Unity provides. To use this information, you should be familiar with the basic theory and practice of scripting in Unity which is explain

docs.unity3d.com

해당 사이트는 유니티 에디터 내에 리본메뉴 → HELP → Scripting Reference를 눌러도 쉽게 연결된다.

 

 

 

(C# 혹은 유니티의 메모리를 이해하기 위한 참고자료1)

스택과 큐 방식: 

스택은 후입선출(나중에 들어간게 먼저 나와)(편의점..)

큐 방식은 선입선출. 먼저 넣은게 먼저 나옴. > 주소나 이런걸 굳이 지정할 필요 없음. 

메모리 데이터를 쓰는 방법을 말하는 것.

https://namsieon.com/245

 

[기본원리] 메모리의 스택과 큐의 이용.

배열과 메모리의 관계에 이은 스택과 큐 에 대한 내용입니다. 2010/07/15 - [Programing/기본원리] - 프로그래머가 본 메모리의 내부. 읽기전에 손가락 한번 클릭~ >_< 고마워요 ~ Chu ~ ♥ 스택과 큐 스택

namsieon.com

(참고자료2)

C# 콜렉션, 제너릭

컬렉션: https://blog.naver.com/tutorials_korea/221610337593

 

C#배열,컬렉션(Collection) 자료구조 정리

C# 자료구조 정리 아래의 링크를 클릭해서 보세요. (링크 없는 글은 향후 추가 예정) 1. C# 자료구조 정...

blog.naver.com

(참고자료3)

제너릭: https://coderzero.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-C-%EA%B0%95%EC%A2%8C-21-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%BB%AC%EB%A0%89%EC%85%98General-Collection

 

[유니티 C# 강좌] 21. 제네릭 컬렉션(General Collection)

1. 컬렉션(Collection) 클래스 프로그래밍에서 데이터(자료)를 효율적으로 관리하는 것은 아주 중요한 일입니다. 자료구조란, 데이터를 구조적으로 표현하고, 구현하는 중요한 알고리즘입니다. 컬

coderzero.tistory.com

 

>>VS는 무거운 소프트웨어라서 연산량이 많아서 메모리나 자료구조를 디테일하게 봐야 한다.

 

 

 

 

public class DataController : MonoBehaviour
{
    public int m_gold = 0;
    private int m_goldPerClick = 0;
    ...

저번 주에도 썼지만, 클래스의 이름DataController은 이 C# Script파일 이름과 같아야 한다.

그렇지 않으면 이 스크립트를 붙여 컴포넌트를 만들 때 오류가 난다!

 

MonoBehaviour : 모든 Unity 스크립트가 파생되는 기본 클래스. 상위 클래스로 <Behaviour <Component <Object를 받는다.

 

public으로 현재 골드량을 의미하는 m_gold (전역)변수를,

private으로 클릭 당 골드량을 의미하는 m_goldPerClick (전역)변수를 선언하고 각각 0을 대입했다.

 

 

 

    private void Awake()
    {
        m_gold = PlayerPrefs.GetInt("Gold");
        m_goldPerClick = PlayerPrefs.GetInt("GoldPerClick", 1);
    }

Awake() : 스크립트 인스턴스가 로딩될 때, 게임이 시작되기 전에, 모든 변수와 게임의 상태를 초기화하기 위해 딱 한 번 호출되는 메서드.

PlayerPrefs : 게임 세션 사이에 Preference를 저장하고, 접근하는 클래스. 이곳에 저장하기 때문에, 설령 프로그램을 껐다 키더라도 로드가 가능해진다.

이런 데이터를 쉽게 수정할 수 있으면 골드 복사나 능력치 뻥튀기가 가능해질 것이다. 그래서 대부분의 게임들은 서버를 만들어서 일괄적으로 이런 세이브 데이터를 보관한다.

 

왜 이 함수를 리셋 이후 가장 먼저 실행되는 Awake()로 넣냐면, 두 번째로 실행(클릭)될 때, 로드를 하고 이어서 작업해야 하기 때문이다.

m_goldPerClick 또한 m_gold와 마찬가지이지만 값에 변화를 주기 위해 1을 추가로 넣었다.

 

 

 

    public void SetGold(int newGold)
    {
        m_gold = newGold;
        PlayerPrefs.SetInt("Gold", m_gold);
    }

"정수 newGold를 매개변수로 갖는 메서드를 만들고"

"PlayerPrefs에 "Gold"로 식별된 Preference의 값을 m_gold로 설정한다."

 

즉, 현재 골드량(m_gold)을 저장하는 메서드를 만든 것이다. 나중에 불러올 수 있도록!

 

Q. 왜 굳이 매개변수를 또 만들어서 집어넣어야 할까? 다른 메서드에서도 써먹으려고? 아니면 변수는 매개변수로 쓸 수 없어서?

A. (초보자가 이해하기 쉽도록) 기본 형식을 갖추려고 " m_gold = newGold; " 문장을 사용했을 뿐, 사실 이 문장은 없어져도 괜찮다. C# 스크립트는 똑똑해서 알려주지 않아도 자동으로 최신 데이터로 업데이트하기 때문에.

 

 

 

    public void AddGold(int newGold)
    {
        m_gold += newGold;
        SetGold(m_gold);
    }

    public void SubGold(int newGold)
    {
        m_gold -= newGold;
        SetGold(m_gold);
    }

골드량을 추가하거나(AddGold()) 감소시키는(SubGold()) 메서드를 만든다.

각각의 메서드는 전역변수 m_gold 에 각 메서드의 인수 newGold를 더하거나 뺀다.

 

그리고 중요한 점!

바로 위에 만든 SetGold()로 그 값들을 저장한다. 

 

 

 

    public int GetGold()
    {
        return m_gold;
    }

마지막으로 이렇게 만든 현재 골드량(m_gold)를 리턴하도록 한다.

 

(번외)

int가 정수형이듯, void 역시 형이다. 의미는 아무것도 없음.

모든 함수는 리턴이 있어야 하는데 void는 생략된다.

 

 

 

    public void SetGoldPerClick(int newGoldPerClick)
    {
        m_goldPerClick = newGoldPerClick;
        PlayerPrefs.SetInt("GoldPerClick", m_goldPerClick);
    }

앞선 m_gold와 마찬가지로, m_goldPerClick도 값을 저장해야 한다.

 

우린 클릭 당 골드량도 이후 여러 업그레이드를 통해 증가시키고자 한다. 때문에 이 값도 저장을 하고 로드를 해야 업그레이드 된 정보를 계속 가질 수 있다.

 

 

    public int GetGoldPerClick()
    {
        return m_goldPerClick;
    }

마지막으로 클릭 당 골드량을 리턴하고 끝.

 

 

 

완성된 스크립트

DataController.cs
0.00MB

 

 

 

 

 - 버튼에 적용되는 ClickButton 스크립트를 만든다

먼저 버튼 스크립트를 적용할 UI 생성.

Hierarchy 우클릭 → UI → Button.

 

그럼 Canvas에 Button과, EventSystem 오브젝트가 만들어진다.

 

버튼의 이름을 스크립트와 일치시키고, UI를 이것저것 건드려준다.

그리고ClickButton이란 C# 스크립트를 만들어서 컴포넌트로 추가(①)해준다.

②은 스크립트를 작성한 후에 한다.

 

 

아래는 ClickButton 스크립트. (이미 위에 설명한 부분들은 생략)

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

public class ClickButton : MonoBehaviour
{
    public DataController dataController;
    public int gold;

    public void Awake()
    {
        gold = dataController.m_gold;
    }

    public void OnClick()
    {
        int goldPerClick = dataController.GetGoldPerClick();
        dataController.AddGold(goldPerClick);
    }

앞에 나온 스크립트, DataController가 맞다.

인스턴스화해서, 다른 스크립트(클래스)의 멤버를 가져온다.

가져온 멤버: m_gold, m_goldPerClick, SetGold, AddGold, subgold, GetGold, SetGoldPerClick(), GetGoldPerClick(), Awake()...

다만 수식자가 Public이므로 유니티 에디터 내에서 지정해줘야 한다. DataController라고 만들고, 같은 이름의 스크립트를 집어넣은 '오브젝트'로(①에).

 

 

OnClick() 메서드를 통해

정수형 변수 goldPerClick에 DataController에 있는 GetGoldPerClick()메소드의 을 대입해주고,

을 AddGold 메서드의 인수로 넣어, 실행시킨다.

 

 

 

그리고 버튼 내의 컴포넌트, Button에 '누르면 실행되는 기능'을 지정할 수 있는 칸(On Click)이 있다(②). 

그곳에 해당 버튼 오브젝트를 끌어오면 끝!

 

Q. 왜 이미 스크립트(ClickButton)를 넣었는데 또 넣어야 하나요?

A. 스크립트 자체로는 실행할 수 없다. 그래서 스크립트를 가진 오브젝트를 불러와야 하는데 그게 자기 자신밖에 없어서 해당 버튼 오브젝트를 끌어온 것이다.

No Function을 누르고 맨 밑, Click Button안에 방금 만든 메서드(OnClick())이 있다.

 

 

 

Q. 매개변수, 인수의 차이가 뭐지?

    public void AddGold(int newGold)
    {
        m_gold += newGold;
        SetGold(m_gold);
    }

A. (앞에 사용한 메서드를 예시로 들어서) 메서드의 괄호 안에 들어가는 int newGold가 매개변수이다.

인수는 이 int newGold에 실질적인 값을 넣은 것을 말한다.

 

 

 


(번외)
https://itmir.tistory.com/296

 

변수의 스코프란?

정말 오랜만의 java강좌네요. ㅎㅎㅎ 책으로는 공부했지만 강좌를 올릴 여건이 안되서. ㅎㅎ;; 으아 책 진도는 지금 메소드 다 끝났는데 ㅎㅎ;; 아무튼 빨리 시작하겠습니다. 스코프란? 영역이라

itmir.tistory.com