본문 바로가기

Unity 개발 공부

[내배캠] 본캠 9일차. 메서드 연산자 복습 , 그리고 TextRpg 진행과정

-----------------------
라이브강의

메서드, 연산자

양치하기라는 메서드를 만든다고 생각
품목
일어남
욕실감
칫솔집음
치약짬
입에 칫솔넣음
3분닦음
물로헹굼
칫솔정리함

매번 이런 절차를 매번 복붙하면 중복도 많고 실수도있음
그래서 이걸 하나로 묶어서 '양치하기'라고 할 수 있다.

void BrushTeeth ()
{
 Debug.Log("욕실로감");
 Debug.Log("칫솔집음");
...



}


// 메서드 콜
BrushTeeth();

그런데 메서드를 사용할때 이 값을 가지고 처리해줘라고 할때 매개변수를 쓴다.

void BrushTeeth (string toothpaste)
{
 Debug.Log($"[{toothpast}] 치약으로 양치를 시작합니다");
 Debug.Log("칫솔집음");
...

}

//
BrushTeeth("딸기맛");


양치를 잘해서 용돈을 받는다면? (반환값)

int BrushTeethAndGetReward()
{
 Debug.Log("양치완료!");
 return 500;
}

int reward = BrushTeethAndGetReward();
Debug.Log($"받은 용돈: {reward}원")

메서드는 코드블록

리턴타입이 있다면 
스코프안에 무조건 리턴이 존재해야함.

if문을 사용하면 한 메서드에서 리턴이 여러개 존재할수도있음.
반환해주는 값들은 어딘가에 할당하지않으면 그냥 반환만되는것뿐임.


------
메서드 오버로딩 // 오버라이딩이랑 헷갈리지말기. 

이름은 같지만 매개변수가 다르면 다른 메서드로 인식된다.
오버로딩은 컴퓨터가 어떤 메서드를 로딩할때, 읽어올때를 말함

같은이름의 메서드인데 매개변수가 다른것을 오버로딩이라고함.
이럴때 다른 메서드로 인식됌.
단, 반환값이 다른것도 다른것이냐? 하면 취급하지않음. 
반환되기전에 컴퓨터가 인지할수없음.
매개변수의 갯수, 자료형이 다르거나 할때 오버로딩

int Add(int a, int b)
{
  return a+b;
}


float Add(float a, float b)
{
  return a+b;
}

float Add(float a, float b, float c)
{
  return a+b+c;
}

모호성 문제가 있을수있음. 초기화 세팅때문에 발생가능.
아래에서 추가로 다룰것.

float Add(float a, float b, float c= 1) < 이런식으로 기본값 설정가능

이러면 Add(1.0f, 2.0f); 이런식으로 생략가능 
근데 만약 위에 매개변수 2개짜리가 이미 있다면 모호성이 일어난다 컴퓨터가 뭐가 진짠지 헷갈림
그러므로 이렇게 겹치지않도록 잘 코드를 짜줘야한다.


------------
ref, out 매개변수
참조 전달방법 (주소 전달방법)

ref 외부에서 값을 받아와서 안에서 수정하고 수정된 값을 다시 바깥에 전달.

void AddOne(ref int number)
{
  number += 1;
}

int value = 5;
AddOne(ref value)
Debug.Log(value); // 출력 : 6

만약 ref 가 아니었다면 그냥 5가 출력될것임. 반환하지도않았고
그냥 스코프안에서 지역변수에 할당되면서 끝나버림.
ref로 연결하게되면 실제 value의 참조값을 넘겨주기때문에, 수정하게되면
실제 value 값도 바뀌는 것이다.

Unity 제공해주는 메서드들은 ref, out 을 많이쓴다.
반환값이 하나뿐인데, 메서드가 실행된 이후에 두개 또는 세개의 값을 전달받고싶을때도 마찬가지로
이렇게 여러개 값이 바뀔수있음.
ref는 참조로 준것이므로 값을바꿔도되고 안바꿔도된다.

out 키워드

void GetPlayerInfo( out string name, out int level)
{
 name = " 김영호";
 level = 7;
}

string playerName;
int playerLevel;

GePlayerInfo( out playerName, out playerLevel);

out 값은 메서드 내에서 반드시 할당(초기화)해야한다. 그리고 그것을 빼낸다.
즉 out이 있다면 반드시 매개변수를 받아서 메서드내에서 변경된 후 값으로 쓰인다는것을
알아야만한다.

ref, out이 남용하면 코드가 헷갈릴 수 있음.
ref는 무조건 좋지는 않음. 메서드를 실행해봐야만 결과를 알수있어서...

-----------

연산자

간혹 비교연산자 뒤에 증감을 같이 비교하는 경우가 있는데 앞에가 true면 읽지않으니 주의

true인 조건 || 또다른 조건 및 증감
앞에가 true가되버리면 뒤에는 안보고 넘어간다 컴퓨터는... 그러니 증감이 안될수있음

-----

디버깅

f5 디버깅시작
f9 브레이크포인트 찍기
f10 넘어가기
f11 들어가기
shift f11 나오기

해당라인 가져다대면 연산되고 값들을 띄워줌, 

호출스택은 위로갈수록 최신으로 쌓인것
특정 구간까지 왔다가 반환되면 위에서부터 다시 덜어내며 사라진다.

출력부 에서 조사식으로 라인 긁어서 집어넣으면 값들을 확인가능,
조사식에 넣어서 많이 체크한다.

라인브레이크포인트 오른쪽마우스버튼, 조사에서 특정상황에서만 멈추도록 하게
할수있음. 그래서 문제들을 분석가능.

디버깅 동작중에 받는 값 실제로 바꾸는게아니라 테스트로 바꿔보고싶음

직접실행창에 value =10 으로 해당라인중에 바꿔보면 바꿀수있음
디버그는 특정한 시점을 잡는게 어려움. 다시 돌아와야함...
그러니 직접실행창에 직접 메서드를 실행하거나 값들을 넣어보면서 테스트해볼수있다.











-----------------------------
Text RPG

필수기능

-게임시작화면
1. 간단한 소개말과 마을에서 할수있는 행동알려주기
2. 원하는 행동의 숫자 타이핑하면 실행
1~3이외 입력시 잘못된 입력입니다 출력

"
스파르타 마을에 오신 여러분 환영합니다.
이곳에서 던전으로 들어가기전 활동을 할 수 있습니다.

1. 상태 보기
2. 인벤토리
3. 상점

원하시는 행동을 입력해주세요.
>>
"


-상태보기
1. 캐릭터 정보 표시
2. 7개의 속성 가지고있음
레벨/ 이름/ 직업/공격력/방어력/체력/Gold
3. 처음 기본값은 이름을 제외하고는 아래와 동일하게만들기
4. 이후 장착한 아이템에 따라 수치가 변경 될 수 있습니다.
"
상태 보기
캐릭터의 정보가 표시됩니다.

Lv. 01      
Chad ( 전사 )
공격력 : 10
방어력 : 5
체 력 : 100
Gold : 1500 G

0. 나가기

원하시는 행동을 입력해주세요.
>>
"




-인벤토리
보유중인 아이템을 전부보여줌
이때 장착중인 아이템 앞에는 [E]표시를 붙여주기.
처음시작시에는 아이템이 없음
"
인벤토리
보유 중인 아이템을 관리할 수 있습니다.

[아이템 목록]

1. 장착 관리
0. 나가기

원하시는 행동을 입력해주세요.
>>
"


-장착관리
장착관리가 시작되면 아이템 목록앞에 숫자가 표시됨
일치하는 아이템을 선택했다면(1~3)
장착중이지않다면 -> 장착
[E] 표시 추가
이미 장착중이라면 -> 장착해제
[E]표시 없앰
일치하는 아이템을 선택하지않았다면(1~3 이외 선택)
잘못된 입력입니다 출력
아이템의 중복장착을 허용합니다
창과 검 동시장착
갑옷도 동시 껴입기
장착 갯수 제한 x
"
인벤토리 - 장착 관리
보유 중인 아이템을 관리할 수 있습니다.

[아이템 목록]
- 1 [E]무쇠갑옷      | 방어력 +5 | 무쇠로 만들어져 튼튼한 갑옷입니다.
- 2 [E]스파르타의 창  | 공격력 +7 | 스파르타의 전사들이 사용했다는 전설의 창입니다.
- 3 낡은 검         | 공격력 +2 | 쉽게 볼 수 있는 낡은 검 입니다.

0. 나가기

원하시는 행동을 입력해주세요.
>>
"
"
상태 보기
캐릭터의 정보가 표시됩니다.

Lv. 01      
Chad ( 전사 )
공격력 : 17 (+7)
방어력 : 10 (+5)
체 력 : 100
Gold : 1500 G

0. 나가기

원하시는 행동을 입력해주세요.
>>
"



-상점
보유중인 골드와 아이템의 정보, 가격이 표시된다.
아이템 정보 오른쪽에는 가격이 표시가 된다.
이미 구매를 완료한 아이템이라면 구매완료로 표시된다.

"
상점
필요한 아이템을 얻을 수 있는 상점입니다.

[보유 골드]
800 G

[아이템 목록]
- 수련자 갑옷    | 방어력 +5  | 수련에 도움을 주는 갑옷입니다.             |  1000 G
- 무쇠갑옷      | 방어력 +9  | 무쇠로 만들어져 튼튼한 갑옷입니다.           |  구매완료
- 스파르타의 갑옷 | 방어력 +15 | 스파르타의 전사들이 사용했다는 전설의 갑옷입니다.|  3500 G
- 낡은 검      | 공격력 +2  | 쉽게 볼 수 있는 낡은 검 입니다.            |  600 G
- 청동 도끼     | 공격력 +5  |  어디선가 사용됐던거 같은 도끼입니다.        |  1500 G
- 스파르타의 창  | 공격력 +7  | 스파르타의 전사들이 사용했다는 전설의 창입니다. |  구매완료

1. 아이템 구매
0. 나가기

원하시는 행동을 입력해주세요.
>>
"

-아이템구매
아이탬구매를 선택하면 아이템 목록앞에 숫자가 표시된다.
일치하는 아이템을 선택했다면(1~6선택시)
이미 구매한 아이템이라면
-이미 구매한 아이템입니다 출력
구매가 가능하다면
보유금액이 충분하다면
-구매를 완료했습니다 출력
재화감소/인벤토리에 아이템추가/상점에 구매완료표시

보유금액이 부족하다면
-gold가 부족합니다 출력

일치하는 아이템을 선택하지않았다면(1~6 외에 선택)
잘못된 입력입니다 출력

"
상점 - 아이템 구매
필요한 아이템을 얻을 수 있는 상점입니다.

[보유 골드]
800 G

[아이템 목록]
- 1 수련자 갑옷    | 방어력 +5  | 수련에 도움을 주는 갑옷입니다.             |  1000 G
- 2 무쇠갑옷      | 방어력 +9  | 무쇠로 만들어져 튼튼한 갑옷입니다.           |  구매완료
- 3 스파르타의 갑옷 | 방어력 +15 | 스파르타의 전사들이 사용했다는 전설의 갑옷입니다.|  3500 G
- 4 낡은 검      | 공격력 +2  | 쉽게 볼 수 있는 낡은 검 입니다.            |  600 G
- 5 청동 도끼     | 공격력 +5  |  어디선가 사용됐던거 같은 도끼입니다.        |  1500 G
- 6 스파르타의 창  | 공격력 +7  | 스파르타의 전사들이 사용했다는 전설의 창입니다. |  구매완료

0. 나가기

원하시는 행동을 입력해주세요.
>>
"



----------------
도전기능

-아이템 정보를 클래스/ 구조체로 활용 //진행

-아이템 정보를 배열로 관리 //진행

-아이템 추가- 나만의 새로운 아이템을 추가 //보류 혹은 애초에 이름바꿔서


-휴식기능추가 // 보류 중복


-판매하기 기능추가 // 진행해보기
상점에 아이템 판매기능을 추가.
판매시 구매가격 85% 가격에 판매
판매시 장착하고있는 아이템이 있다면 해제됌.
"
상점
필요한 아이템을 얻을 수 있는 상점입니다.

[보유 골드]
800 G

[아이템 목록]
- 수련자 갑옷    | 방어력 +5  | 수련에 도움을 주는 갑옷입니다.             |  1000 G
- 무쇠갑옷      | 방어력 +9  | 무쇠로 만들어져 튼튼한 갑옷입니다.           |  구매완료
- 스파르타의 갑옷 | 방어력 +15 | 스파르타의 전사들이 사용했다는 전설의 갑옷입니다.|  3500 G
- 낡은 검      | 공격력 +2  | 쉽게 볼 수 있는 낡은 검 입니다.            |  600 G
- 청동 도끼     | 공격력 +5  |  어디선가 사용됐던거 같은 도끼입니다.        |  1500 G
- 스파르타의 창  | 공격력 +7  | 스파르타의 전사들이 사용했다는 전설의 창입니다. |  구매완료

1. 아이템 구매
2. 아이템 판매
0. 나가기

원하시는 행동을 입력해주세요.
>>
"

-장착개선 // 진행
각 타입별로 하나의 아이템만 장착가능하게 (방어구/무기)
방어구를 장착하면 기존 방어구가 있다면 해제하고 장착
무기를 장착하면 기존무기가 있다면 해제하고 장착

"
인벤토리 - 장착 관리
보유 중인 아이템을 관리할 수 있습니다.

[아이템 목록]
- 1 [E]무쇠갑옷      | 방어력 +5 | 무쇠로 만들어져 튼튼한 갑옷입니다.
- 2 [E]스파르타의 창  | 공격력 +7 | 스파르타의 전사들이 사용했다는 전설의 창입니다.
- 3 낡은 검         | 공격력 +2 | 쉽게 볼 수 있는 낡은 검 입니다.

0. 나가기

원하시는 행동을 입력해주세요.
>>
"

-던전입장 기능 추가 // 도전시간되면

던전은 3가지 난이도 존재
방어력으로 던전을 수행할수 있을지 판단
권장 방어력보다 낮다면
40%확률로 던전실패
보상없고 체력감소절반

권장방어력보다 높다면
던전클리어
권장방어력 +-에 따라 종료시 체력 소모 반영

기본체력감소량
20~35 랜덤
(내 방어력 - 권장방어력)만큼 랜덤 값에 설정
ex) 권장 방어력 5, 내 방어력 7
20(-2) ~ 35(-2) 랜덤
ex) 권장방어력 11 내방어력 5
20(+6) ~35(+6) 랜덤

공걱력으로 던전 클리어시 보상을 어느정도 얻을지 계산한다.
각 던전별 기본 클리어보상
쉬운던전 -1000G
일반던전 -1700G
어려운 던전 -2500G

공격력~공격력*2의 %만큼 추가 보상 획득가능
ex) 공격력 10, 쉬운던전
기본보상 1000G
공격력으로 인한 추가보상 10~20%
ex) 공격력 15, 어려운 던전
기본보상 2500G
공격력으로 인한 추가보상 15~30%
"
스파르타 마을에 오신 여러분 환영합니다.
이곳에서 던전으로 들어가기전 활동을 할 수 있습니다.

1. 상태 보기
2. 인벤토리
3. 상점
4. 던전입장

원하시는 행동을 입력해주세요.
>>
"
"
던전입장
이곳에서 던전으로 들어가기전 활동을 할 수 있습니다.

1. 쉬운 던전     | 방어력 5 이상 권장
2. 일반 던전     | 방어력 11 이상 권장
3. 어려운 던전    | 방어력 17 이상 권장
0. 나가기

원하시는 행동을 입력해주세요.
>>
"
"
던전 클리어
축하합니다!!
쉬운 던전을 클리어 하였습니다.

[탐험 결과]
체력 100 -> 70
Gold 1000 G -> 2200 G 

0. 나가기

원하시는 행동을 입력해주세요.
>>
"


-레밸업 기능 추가 // 도전 시간되면
던전 여러번 클리어하면 레벨 증가
lv1 -> lv2 1회클리어
lv2 -> lv3 2회클리어
lv3 -> lv4 3회 클리어
lv4 -> lv5 4회 클리어

레벨업시 기본 공격력이 0.5 방어력이 1증가


게임 저장하기 추가 // 도전시간되면, 난이도 어려움

앱을 껏다켜도 사용되던 정보를 유지하도록

--------------------
만들면서 지식

1. 폴더를 만들면 해당 폴더가 프로젝트명인 최상위 네임스페이스의 차상위로 된다.
그안에 스크립트를 만들면 또다시 차차상위가 된다.
해당 스크립트의 변수나 메서드등을 다른 차상위 네임스페이스로 
가져올때 using문으로 차상위 네임스페이스를 선언해주면된다.

2. 전역변수로 데이터값들을 끌어오기보다는, private으로 필요한 타입의 필드를 선언하고(다른곳에서가져올것)
생성자로 객체생성한 해당 타입인스턴스를 받아서 private 필드 변수에 할당하면 좋다.
private 필드말고 readonly로 사용하면 한번만 설정되고 화면 라이프사이클 내내 안전하게 사용할수도있다.
Player player = new Player(); 로 객체를 생성 // Player 클래스가 만들어져있는 상태
다른 클래스에서 해당 타입을 가져오려할때,
Private Player _player; 로 필드선언하고
public MainmenuScreen(Player player)
{
 _player = player;
}

로 객체를 할당해버릴 수 있음.

객체 생성시 생성자가 호출되는것은 알것이다. 그 클래스의 생성자를 만들어두고
객체들을 생성할때마다 인자로 받아오게하여 내부의 해당 인자 타입의 필드에 할당시키는 방식으로
초기화한다면 해당 클래스는 객체를 인자로 받아서 그때그때 쓸수있는 창구가 만들어지는것이고
내부 코드를 수정할 필요는없다.
참고로 객체 생성시 생성자는 호출되지만, 메서드는 인자를 받지않고 별도로 호출을 해줘야만한다.
헷갈리지말자.




확장성을 조금 희생하고, 간결하게 쓰려면
전역접근자로 사용해서 여기저기 쓸수도있긴하다. 다만 이러면 전역 static으로 만들어 
오직 하나만 있으므로 확장이 어렵다.
먼저 속성으로 만들고 그걸로 객체를 생성하면, 여기저기다가 해당 속성 변수를 할당해버리는 방식
으로 바로 쓸수도있다.

예를들면 클래스 하나를 만들고
Class GameContext
{
 public static Player CurrentPlayer { get; set;}

}

객체를 하나 생성하고
Player CurrentPlayer = new Player();

다른 클래스에서 이 타입을 이용하고싶을때

Player player = GameContext.CurrentPlayer; 로 바로 접근자를 도입해 할당해버릴수있음



MainMenuScreen에서 

    case 1:
        return new StatusScreen(_player);
    case 2:
        return new InventoryScreen(_player);
    case 3:
        return new ShopScreen(_player);
    case 0:
        return null;

이 구문을 보면 화면이동하는 HandleUserInput( string input) 안에 넣은 구문이다.
switch로 값을 받아 다른 스크린으로 이동할때 _player라고 사전에 객체를 생성해서
할당해놓은 변수를 넣어서 새롭게 인스턴스 생성시키고 있다.
물론 아예 만들어놓은 인스턴스를 이용해서 화면전환을 시킬수도있지만
해당방식이 큰 문제가안되는이유는 
1. 스크린들은 정보를 보여주고, 값을 컨트롤하는 가벼운 스크립트이기때문
2. 실제 데이터는 Player 스크립트 같은데서 저장되고있음
3. 가비지콜렉터기능이 런타임에 여유가있을때, 쓰지않는 참조 객체는 지워버림
따라서 다른 스크린으로 이동할때는 new로 Screen 타입 인스턴스가 반환되어서
CurrentScreen 변수에 다르게 할당 될것이기때문에 참조가 바뀐다. 
메모리 누수가 발생할 확률이 낮다.
참고로 저기서는 반환만 하는데 
program main에서 
while문 반복으로 하여 
재할당을 해주는
CurrentScreen = currentScreen.HandleUserInput(input)이 있었다.
반환값이 여기로 이동할것이다.

shopscreen에 Item 스크립트에서의 리스트 shopItems 항목들을 불러올때는
전역(static) 설정이 되어있으므로 
foreach(var item in Item.shopItems) 로도 리스트를 훑을수있지만

InventoryScreen에 띄울때 InventoryItems는 전역설정이 안되어있으므로 
객체를 통해 참조해서 불러와줘야함>
따라서
foreach(var item in _player.Inventory.InventoryItems) 해줘야한다.