Unity를 위한 C# 기초 핵심 강의 보며 정리하기

0. 출력

 

Debug.Log()

 

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

public class NewBehaviourScript : MonoBehaviour
{
    void Start()
    {
        Debug.Log("Hello Unity!");
    }

}

 

 

1. 변수

 

데이터를 메모리에 저장하는 장소

 

원하는 값을 기억하고 나중에 재사용할 수 있다.

 

가장 많이 쓰이는 4가지 int, float, string, bool

 

int는 정수형 데이터

 

float는 소수도 포함한 숫자형 데이터, 사용할 때는 뒤에 f를 붙여줘야함

 

float strength = 15.5f;

 

string은 문자열 데이터, 양 끝에 큰 따옴표 사용

 

string name = "윤대혁";

 

bool은 논리형 데이터, true나 false를 저장

 

변수 이름을 만드는 것은 변수 선언, 변수에 값을 넣으면 초기화

 

변수명은 숫자로 시작할 수 없다

 

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

public class NewBehaviourScript : MonoBehaviour
{
    void Start()
    {
        Debug.Log("Hello Unity!");

        int level = 5;
        float strength = 15.5f;
        string playerName = "윤대혁";
        bool isFullLevel = false;

        Debug.Log("용사의 이름은?");
        Debug.Log(playerName);
        Debug.Log("용사의 레벨은?");
        Debug.Log(level);
        Debug.Log("용사의 힘은?");
        Debug.Log(strength);
        Debug.Log("용사는 만렙인가?");
        Debug.Log(isFullLevel);
    }

}

 

 

 

 

 

2. 주석

 

//을 앞에 붙이면 한줄 주석

 

코드가 실행되지 않는 메모

 

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

public class NewBehaviourScript : MonoBehaviour
{
    void Start()
    {
        Debug.Log("Hello Unity!");

        //1.변수 (주석)
        int level = 5;
        float strength = 15.5f;
        string playerName = "윤대혁";
        bool isFullLevel = false;
    }

}

 

 

3. 배열

 

변수들을 묶은 하나의 장소

 

변수 하나에는 여러가지 값을 넣을 수 없지만 

 

배열에는 여러가지 값을 넣어서 하나의 변수처럼 다룰 수 있음

 

{} 안에 값을 넣어서 하나의 string 배열 선언

 

//2. 그룹형 변수
string[] monsters = { "슬라임", "사막뱀", "악마" };

 

 

각각의 값을 가지고 올때는 인덱스를 넣는데 0번부터 시작

 

Debug.Log("맵에 존재하는 몬스터");
Debug.Log(monsters[0]);
Debug.Log(monsters[1]);
Debug.Log(monsters[2]);

 

 

 

 

 

배열의 크기를 선언한 다음 각 인덱스 공간에 값을 직접 넣는 방식으로 선언할 수 있음

 

당연히 선언한 배열의 자료형에 맞는 값을 넣어야함

 

int[] monsterLevel = new int[3];
monsterLevel[0] = 1;
monsterLevel[1] = 6;
monsterLevel[2] = 20;

 

 

배열의 원소 길이는 (배열).Length

 

Debug.Log("배열의 길이: " + monsters.Length);

 

 

 

 

4. List

 

기능이 추가된 가변형 배열?

 

List<(타입)> items = new List<(타입)>();

 

타입에는 List가 담을 자료형 명시, 이걸 generic이라고 한다?

 

List<string> items = new List<string>();

 

 

값을 넣을때는 Add() 사용

 

List<string> items = new List<string>();
items.Add("생명물약30");
items.Add("미니물약30");

 

 

인덱스로 넣을려하면 items[0] = "생명물약30";하면 0번에는 아이템이 없다며 에러나는

 

items.Add("생명물약30");으로 0번 아이템을 만들고 나서, 

 

items[0] = "생명"; 이런식으로 수정도 가능함

 

+ 어쨌든 접근할때는 배열과 마찬가지로 인덱스로 접근가능

 

List<string> items = new List<string>();
items.Add("생명물약30");
items.Add("미니물약30");

Debug.Log(items[0]);

items[0] = "생명";

Debug.Log(items[0]);
Debug.Log(items[1]);

 

 

 

 

 

RemoveAt(index)로 해당하는 index의 아이템 삭제 가능

 

이때 삭제하면 이후 인덱스를 한칸씩 앞으로 땡겨옴

 

0번 아이템 삭제시 1번 아이템을 0번으로 옮겨옴

 

List<string> items = new List<string>();
items.Add("생명물약30");
items.Add("마니물약30");

items.RemoveAt(0);

Debug.Log(items[0]);
Debug.Log(items[1]);

 

 

 

 

 

생명물약30 삭제하니 0번에 마나물약30이 오고 마나물약30이 출력

 

items에는 0번 아이템만 있어서 items[1]은 인덱스를 벗어나서 인덱스 에러

 

리스트 내 원소의 수는 (리스트).Count

 

Debug.Log("리스트의 길이: " + items.Count);

 

 

 

 

 

 

5. 연산자

 

상수나 변수와 연산해주는 기호

 

+, -, / , *

 

//3.연산자
int exp = 1500;

exp = 1500 + 320;
exp = exp - 10;
level = exp / 300;
strength = level * 3.1f;

Debug.Log("용사의 총 경험치는?");
Debug.Log(exp);
Debug.Log("용사의 레벨은?");
Debug.Log(level);
Debug.Log("용사의 힘은?");
Debug.Log(strength);

 

 

 

 

 

나눗셈 보면 알겠지만 1810/300 = 6이 나온 것으로 보아 /은 몫을 구해줌

 

%는 나머지를 구해줌

 

        int nextExp = 300 - (exp % 300);

        Debug.Log("다음 레벨까지 남은 경험치는?");
        Debug.Log(nextExp);

 

 

 

 

 

문자열끼리도 연산이 가능한데 문자열 + 문자열을 하면 두 문자열을 이어 붙임

 

        string title = "전설의";
        string playerName = "윤대혁";
        Debug.Log("용사의 이름은?");
        Debug.Log(title + " " + playerName);

 

 

 

 

 

6. 비교연산자

 

서로 같은지 비교하는 연산자 ==

 

int level = 5;
int fullLevel = 99;
isFullLevel = level == fullLevel;
Debug.Log("용사는 만렙입니까? " + isFullLevel);

 

 

 

 

 

부등호는  > , < , >=, <= 4가지 다른 언어에서 쓰는 그대로

 

bool isEndTutorial = level > 10;
Debug.Log("튜토리얼이 끝난 용사입니까? " + isEndTutorial);

 

 

 

 

7. 논리연산자

 

&&는 and로 A && B는 A,B가 모두 true일때 true

 

int health = 30;
int mana = 25;
bool isBadCondition = health <= 50 && mana <= 20;
Debug.Log("용사의 상태가 나쁩니까? " + isBadCondition);

 

 

 

 

|| 는 or로 A || B는 A와 B중 적어도 하나가 True이면 True

 

int health = 30;
int mana = 15;
bool isBadCondition = health <= 50 || mana <= 20;
Debug.Log("용사의 상태가 나쁩니까? " + isBadCondition);

 

 

 

 

 

8. 삼항연산자

 

(조건) ? (조건이 참일때) : (조건이 거짓일때)

 

string condition = isBadCondition ? "나쁨" : "좋음";

 

isBadCondition이 true이면 condition = "나쁨"

 

isBadCondition이 false이면 condtion = "좋음"

 

string condition = isBadCondition ? "나쁨" : "좋음";
Debug.Log("용사의 상태가 나쁩니까? " + condition);

 

 

 

 

 

9. 키워드(keyword)

 

프로그래밍 언어를 구성하는 특별한 의미를 가지는 단어들

 

int, bool, string, new, float, .... 등등등

 

변수 이름으로 사용 불가(int float = 1;은 불가능)

 

값으로 대입할 수 없음(string name = List;는 불가능)

 

 

10. 조건문

 

조건에 만족하면 해당 로직을 실행하는 제어문

 

1) if문

 

if (조건) {

조건이 참이면 실행할 문장

}

 

        if (condition == "나쁨")
        {
            Debug.Log("플레이어의 상태가 나쁘니 아이템을 사용하세요.");
        }

 

 

당연히 조건이 참이 아니면 실행되지 않고 그냥 다음 단계로 넘어감

 

 

 

2) if else문

 

if (조건) {

조건이 참이면 실행

}

else {조건이 거짓이면 실행}

 

int health = 30;
int mana = 15;
bool isBadCondition = health > 50 && mana > 20;
string condition = isBadCondition ? "나쁨" : "좋음";

if (condition == "나쁨")
{
    Debug.Log("플레이어의 상태가 나쁘니 아이템을 사용하세요.");
}
else
{
    Debug.Log("플레이어의 상태가 좋습니다.");
}

 

 

 

 

 

3) else if문

 

if (조건1) {

조건 1이 참이면 실행

}

else if (조건2) {조건2가 참이면 실행}

 

        if (isBadCondition && items[0] == "생명물약30")
        {
            items.RemoveAt(0);
            health += 30;
            Debug.Log("생명포션30을 사용하였습니다.");
        }
        else if (isBadCondition && items[0] == "마나물약30")
        {
            items.RemoveAt(0);
            mana += 30;
            Debug.Log("마나포션30을 사용하였습니다.");
        }

 

 

 

 

 

4) switch case문

 

변수의 값에 따라 실행하는 제어문

 

switch (변수) {

case 값1:

break;

case 값2:

break;

case 값3:

break;

}

 

break를 쓰지 않으면, 해당 case문이 실행되더라도 switch문을 빠져나가지 않아서

 

그 다음에 만족하는 case문도 실행하게 됨

 

C#은 case 다음에 break;를 반드시 써야함

 

안쓰면 컴파일 에러나더라

 

string[] monsters = { "슬라임", "사막뱀", "악마" };
        
switch (monsters[0])
{
    case "슬라임":
        Debug.Log("소형 몬스터가 출현!");
        break;

    case "악마":
        Debug.Log("중형 몬스터가 출현!");
        break;

    case "골렘":
        Debug.Log("대형 몬스터가 출현!");
        break;
}

 

 

 

 

 

응용해서 서로 다른 case문이 동일한 로직을 실행해야한다면?

 

"슬라임", "사막뱀"인 경우 소형 몬스터가 출현!을 출력하려면

 

case 슬라임:

case 사막뱀:

Debug.Log("소형 몬스터가 출현!");

break;

 

        switch (monsters[1])
        {
            case "슬라임":
            case "사막뱀":
                Debug.Log("소형 몬스터가 출현!");
                break;

            case "악마":
                Debug.Log("중형 몬스터가 출현!");
                break;

            case "골렘":
                Debug.Log("대형 몬스터가 출현!");
                break;

            default:
                Debug.Log("??? 몬스터가 출현!");
                break;
        }

 

 

 

 

 

 

5) default

 

모든 case문을 통과하고나서 변수 값에 상관없이 실행하는 부분

 

monsters[1] = 사막뱀인데 슬라임, 악마, 골렘도 아니라서 default문이 실행

 

        switch (monsters[1])
        {
            case "슬라임":
                Debug.Log("소형 몬스터가 출현!");
                break;

            case "악마":
                Debug.Log("중형 몬스터가 출현!");
                break;

            case "골렘":
                Debug.Log("대형 몬스터가 출현!");
                break;

            default:
                Debug.Log("??? 몬스터가 출현!");
                break;
        }

 

 

 

 

 

11. 반복문

 

조건을 만족하면 특정 로직을 반복하는 제어문

 

1) while문

 

while (조건) {

조건이 참이면 반복

}

 

while (health > 0)
{
    health--;
    if (health > 0)
    {
        Debug.Log("독 데미지를 입었습니다. " + health);
    }
    else
    {
        Debug.Log("사망하였습니다.");
    }
}

 

 

 

 

2) break

 

반복문 중간에 break를 만나면 반복문을 그만두고 탈출한다

 

        while (health > 0)
        {
            health--;
            if (health > 0)
            {
                Debug.Log("독 데미지를 입었습니다. " + health);
            }
            else
            {
                Debug.Log("사망하였습니다.");
            }

            if (health == 10)
            {
                Debug.Log("해독제를 사용합니다.");
                break;
            }
        }

 

 

 

 

 

3) for

 

연산을 하면서 해당 조건을 만족하는 동안 반복문을 수행

 

for (변수; 조건; 연산) {

조건을 만족하는 동안 반복

}

 

        for (int count = 0; count < 10; count++)
        {
            health++;
            Debug.Log("붕대로 치료 중..." + health);
        }

 

 

 

 

 

        for (int index = 0; index < monsters.Length; index++)
        {
            Debug.Log("이 지역에 있는 몬스터: " + monsters[index]);
        }

 

 

 

 

 

4) foreach

 

배열의 원소를 직접 꺼내서 반복할수 있는 반복문

 

        foreach (string monster in monsters)
        {
            Debug.Log("이 지역에 있는 몬스터: " + monster);
        }

 

 

 

 

 

5) 무한 반복문

 

유니티에서는 무한반복문을 특히 조심해야하는데

 

무한반복문에 걸려버리면 유니티 에디터가 멈춰서 강제로 꺼야하는 상황이 생길 수 있어서

 

지금까지 만든 것을 날릴 수 있기 때문에 조심해야함

 

while (true) {
health++;
}

 

 

 

12. 함수

 

미리 지정된 동작을 수행하는 코드 묶음

 

같은 동작을 수행하는 코드를 여러번 작성할 필요가 없어짐

 

일부만 수정하거나 원하는 기능을 추가하기만 해도 되는 편리함

 

(함수 반환값의 타입) (함수이름)(함수가 받을 변수들)

{

함수 내용
}

 

int Heal(int health)

{

내용

}

 

Heal이라는 함수는 health를 변수로 받아 int값을 return함

 

    int Heal(int health)
    {
        health += 10;
        Debug.Log("힐을 받았습니다." + health);

        return health;

    }

 

 

return은 함숫값을 반환할 때 사용하는 키워드

 

Heal이라는 함수가 받는 변수 int health를 매개변수라고 부름

 

당연히 매개변수 이름은 원하는대로 설정가능

 

또한 함수가 받는 매개변수는 여러개도 가능하다

 

void Start(){

health = Heal(health);

}

 

 

health값을 Heal함수에 넣어서 반환값을 다시 health에 저장

 

 

 

모든 함수는 return이 있어야하며, return으로 전달할 데이터 타입을 함수명 앞에 명시해야함

 

예외적으로 void는 반환값이 없는 함수라는 뜻으로 return을 생략해도 된다

 

health 변수를 Heal()함수 안에서 사용해서 변환시키고자할때

 

 

 

 

health에 빨간줄이 그어져있는

 

health는 void Start() 함수 안에 정의된 지역변수

 

지역변수는 다른 함수에서는 접근할 수 없다

 

함수 바깥에서 선언한 전역변수는 모든 함수에서 접근 가능

 

 

 

 

 

 

꼭 필요한 변수들을 전역변수로 다시 설정하고 몬스터 레벨과 용사 레벨을 비교하여 결과를 알려주는

 

Battle()함수 생성

 

for문을 이용하여 결과를 출력

 

    string title = "전설의";
    string playerName = "윤대혁";
    int level = 5;
    float strength = 15.5f;
    int exp = 1500;
    int health = 30;
    int mana = 25;
    bool isFullLevel = false;

    void Start()
    {
    ....
    
    for (int index = 0; index < monsters.Length; index++)
        {
            Debug.Log("용사는 " + monsters[index] + "에게 " +
                Battle(monsterLevel[index]));
        }
    }

    //7. 함수(메소드)

    void Heal()
    {
        health += 10;
        Debug.Log("힐을 받았습니다." + health);

    }
    
    string Battle(int monsterLevel)
    {
        string result;
        if (level >= monsterLevel)
        {
            result = "이겼습니다.";
        }
        else
        {
            result = "졌습니다.";
        }
        return result;
    }

 

 

 

 

 

13. 클래스

 

하나의 오브젝트와 그에 대응하는 로직들

 

public class NewBehaviourScript : MonoBehaviour

 

class 키워드는 클래스를 만들때 사용하는 키워드

 

 

 

 

 

 

unity에서는 보통 하나의 class는 하나의 파일에 대응

 

assets에서 오른쪽 클릭 - create - c# script로 파일 생성

 

 

 

 

actor 파일 생성

 

 

 

 

 

public class Actor만 남기고 모두 지우고

 

 

 

 

 

public class Actor
{
    int id;
    string name;
    string title;
    string weapon;
    float strength;
    int level;

    string Talk()
    {
        return "대화를 걸었습니다.";
    }

    string HasWeapon()
    {
        return weapon;
    }

    void LevelUp()
    {
        level = level + 1;
    }

}

 

 

 

만들고 나서 public class NewBehaviourScript : MonoBehaviour 안의 void Start() 함수 안에

 

(class명) (변수명) = new (class명)();

 

        Actor player = new Actor();

 

 

정의된 class를 변수 초기화로 실체화 시키는 것을 인스턴스라고 부름

 

player에 . 붙이면 가지고 있는 멤버변수나 메소드에 접근할 수 있는데

 

보호 수준때문에 접근할 수 없다고 나옴

 

 

 

당장 Actor에 접근할 수 있는 이유도 public이라는 접근자 때문인데

 

다른 변수나 함수는 접근자가 없는데 private가 기본형으로 설정되어 있다

 

private는 외부 클래스에서 접근할 수 없도록 하는 접근자

 

 

 

 

id변수를 public으로 바꾸면

 

 

 

 

이제 접근할 수 있게됨

 

 

 

 

 //8.클래스
        Actor player = new Actor();

        player.id = 0;
        player.name = "윤대혁";
        player.title = "현명한";
        player.strength = 2.4f;
        player.weapon = "나무 지팡이";
        Debug.Log(player.Talk());
        Debug.Log(player.HasWeapon());

        player.LevelUp();
        Debug.Log(player.name + "의 레벨은 " + player.level + " 입니다.");

 

 

 

 

 

13. 클래스 상속

 

Actor는 용사이거나 슬라임이거나 악마이거나 몬스터이거나 다양하게 될 수 있는데

 

Actor를 이용해서 용사, 슬라임, 몬스터 등 다양한 클래스를 또 만들 수 있음

 

public class Player : Actor
{
    public string move()
    {
        return "플레이어는 움직입니다.";
    }
}

 

 

이후 Actor를 Player로 바꿔도 아무 문제가 없음

 

Player class가 Actor class의 모든 멤버변수 메소드를 사용할 수 있게 됨

 

 

 

 

public class Player : Actor

 

Actor는 부모 클래스 Player는 자식 클래스

 

자식 클래스는 부모 클래스의 모든 멤버변수, 메소드를 사용할 수 있으면서도,

 

추가로 자기 자신의 멤버변수, 메소드를 정의할 수 있다

 

여기서는 move()가 정의되어있음

 

public class Player : Actor
{
    public string move()
    {
        return "플레이어는 움직입니다.";
    }
}

 

 

public class NewBehaviourScript : MonoBehaviour

 

MonoBehaviour는 유니티 게임 오브젝트들의 클래스

 

참고로 MonoBehaviour은 유니티 독특한 구조상 인스턴스로 생성할 수 없다

 

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

14. 형 변환

 

자료형이 다른 다수 변수가 연산을 하면, 알아서 문장을 파악해서 변수 타입을 자동으로 바꿔줌

 

좌측 변수 자료형 기준으로 string enemy에서 3을 문자열로 바꿔줌

 

이를 암시적 형변환이라고 부른다

 

그런데 int health = 50 + 4.8f;는 암시적 형변환을 할 수 없다고 에러나는데?

 

float랑 int 사이 암시적 형변환을 할 수 없다는데.. int랑 float 더하면 float인데 int health로 받아서 안된다나봐

 

int health = 50 + (int)4.8f;로 하면 에러가 안난다

 

이걸 명시적 형변환이라고 부른다

 

int health = 50 + (int)4.8f;
string enemy = 3 + "번 고블린";

 

 

 

 

 

15. 단항 연산자

 

level++;는 level + 1과 같고

 

exp--;는 exp - 1과 같음

 

++를 앞에 붙이거나 뒤에 붙일 수 있는데

 

        int level2 = 4;

        Debug.Log(level2++);
        Debug.Log(++level2);
        Debug.Log(level2);

 

 

 

Debug.Log(level2++)는 level2 = 4를 먼저 출력하고 level2에 1을 증가시킴

 

Debug.Log(++level2)는 level2 = 5에 1을 증가시켜 6을 만들고 level2를 출력

 

Debug.Log(level2)는 최종적으로 6을 출력

 

 

16. 생성자

 

클래스는 기본 생성자를 가지고 있음

 

생성자를 따로 만들지 않더라도 기본 생성자가 암시적으로 생성된다.

 

직접 구현하고 싶으면 클래스 이름과 동일하게 구현해야함

 

public class Player()
{
string name;
int level;
string weapon;

public Player(string pName, int pLevel, string pWeapon){
name = pName;
level = pLevel;
weapon = pWeapon;
}
}

public class Start()
{
Player P1 = new Player("윤대혁", 12, "타격완드");
}

 

 

Player 클래스가 public Player라는 생성자를 보유하고 있음

 

그래서 Player의 인스턴스를 만들 때 해당 생성자를 사용하여 pName, pLevel, pWeapon값을 넣어서 멤버변수를 초기화할 수 있음

 

python의 init같은 역할임

TAGS.

Comments