-
유니티 개인공부 1 기본 게임 구조 & C# 기초 문법,개념유니티 개인공부 2026. 7. 4. 11:45

연극으로 비유를 하자면, 다음과 같은 요소들로 이루어져 있습니다.
막(Act): 이야기가 진행되는 하나의 장면, 막이 바뀌면 무대 배경도, 등장인물도 통째로 바뀜
인물&소품:무대 위에 등장하는 배우와 소품들, 각자 자기 위치에서 자기 역할을 완수함
특기(능력):배우 한 명이 가진 개별 능력. 검술, 노래, 즉흥 대사 같은 것들이 모여서 하나의 배역이 완성
대본:배우가 그대로 따라야 하는 행동 지침, 정해진 대로 말하고 움직임
이 구조를 게임에 그대로 옮기면 유니티의 핵심 개념이 됩니다
연극게임(유니티)
막 (Act) 씬 (Scene) 인물 & 소품 게임 오브젝트 (GameObject) 특기(능력) 컴포넌트 (Component) 대본 스크립트 (Script) 씬(Scene) - 막에 해당
씬은 게임의 한 장면입니다 메인 메뉴, 1 스테이지, 보스전, 엔딩화면 같은 것들이 각각 하나의 씬이 되어있으며
씬이 전환되면 화면에 보이는 모든 게임 오브젝트가 통째로 바뀜
게임 오브젝트 (GameObject) - 인물&소품에 해당
씬 안에 존재하는 모든 것의 기본 단위, 플레이어 캐릭터, 적, 카메라, UI요소 등 전부 게임 오브젝트로 볼 수 있음
다만 오브젝트 자체로는 아무 기능이 없음
컴포넌트(Component) - 특기(능력)에 해당
게임 오브젝트에 붙는 기능조각, Transform(위치·회전·크기),sprite Renderer(화면에 보이는 모습),
Rigidbody(물리, 중력) 같은 컴포넌트들이 조합되어야 게임 오브젝트가 실제로 움직이고 보이고 부딪히는
캐릭터가 됨
스크립트 (Script) - 대본에 해당
스크립트는 컴포넌트의 한 종류로 직접 작성한 C#코드가 게임 오브젝트에 붙으면,
그게 바로 "이 배우는 이렇게 행동하라"는 대본 역할을 수행함
예: WASD를 누르면 앞 뒤, 좌우로 움직여라, 마우스 좌클릭을 누르면 공격을 해라 등.
C#기본 문법
스크립트 (Script) - 대본에 해당되는 컴포넌트를
작성, 제어할 때 사용하는 언어
1. 변수( 기본 자료형들)
자료형 예시 코드설명
int int level = 1; 정수형 변수 · 소수점 없는 숫자를 담습니다 float float power = 15.2f; 실수형 변수 · 소수점이 있는 값에는 반드시 뒤에 f를 붙입니다. 단, 값이 정수로 떨어질 때(예: float power = 15;)는 f 없이도 됩니다 (암시적 변환) string string name = "홍길동"; 문자열 변수 · 큰따옴표로 감싼 텍스트를 담습니다 bool bool isAlive = true; 논리형 변수 · true 또는 false 값만 가질 수 있습니다 암시적 변환(Implicit Conversion), 명시적 변환(Explicit Conversion)
float의 경우 데이터 손실이 없을 때 자동으로 일어나는 변환으로 캐스팅 문법 없이 그냥 대입하면 되는
암시적 변환(implitict Conversion)이 일어남. (정수의 경우 뒤에 f를 안 붙여도 되는)
더 작은 범위/정밀도 > 더 큰 범위 정밀도로 갈 때만 자동으로 됨
int > float > double 순서로 자동 변환
int a = 15;float b = a; // OK, int → float 암시적 변환double c = b; // OK, float → double 암시적 변환반대로 명시적 변환(Explicit Conversion / 캐스팅)도 존재함
암시적 변환은 손실이 없는 방향으로만 자동으로 일어나는 반면 반대로
정밀도나 범위가 줄어드는 방향의 변환은 데이터가 깨질 위험이 존재, C# 컴파일러가
개발자에게 강제로 할 거냐고 물어보는 셈.
그 대답이 바로 (타입) 형태의 캐스팅 문법.
예:
double d = 15.99;
float f = (float) d; // double → float, 명시적 변환 필요(float) d 괄호 안에 원하는 타입을 적어 double 값인 d를 float으로 바꿔줘라고 명시적으로 지시하는 문법
float damage = 15.9f;
int intDamage = (int) damage; // 결과: 15 (소수점 버림, 반올림 아님!)(int)로 캐스팅하면 소수점 이하는 반올림 없이 잘려나가며 15.9도 15.2도 등이 단순히 15가 됨
큰 범위 > 작은 범위 정수(오버플로우 위험)
(4바이트 형 변수) int bigNumber = 300;
(1바이트 형 변수) byte smallNumber = (byte) bigNumber; // 결과: 44 (300 - 256 = 44, 오버플로우로 값이 깨짐)byte 자료형의 경우 0~255까지 표현 가능한 반면 300을 억지로 넣으면 오버플로우가 발생해 엉뚱한 숫자가 나옴
유니티에서 자주 사용하는 상황:
// Time.deltaTime은 float인데, 정수 계산과 섞일 때
int score = 100;
float scaledScore = score * Time.deltaTime; // int → float은 암시적 변환 OK
// 반대로 계산 결과를 다시 int로 되돌릴 때
float rawResult = 15.7f;
int finalScore = (int) rawResult; // 명시적 변환 필요, 결과는 15방향변환 종류예시

2. 그룹형 변수
그룹형 변수 종류:
그룹형 변수 (배열, 리스트)
종류문법 형태설명배열 선언 자료형[] 변수명 크기가 고정된 그룹형 변수 · 선언 시 크기를 정해야 하며 이후 변경 불가 배열 요소 접근/대입 변수명[인덱스] 인덱스로 각 칸에 값을 넣거나 꺼냄 (0부터 시작) 배열 크기 확인 변수명.Length 배열의 전체 칸 수를 확인하는 속성 리스트 선언 List<자료형> 변수명 크기가 가변적인 그룹형 변수 · 클래스이므로 new 필수 리스트 값 추가 변수명.Add(값) 리스트 맨 뒤에 요소를 추가, 자동으로 크기가 늘어남 리스트 값 제거 변수명.RemoveAt(인덱스) 지정한 인덱스의 요소를 제거, 뒤 요소들이 앞으로 당겨짐 리스트 개수 확인 변수명.Count 현재 리스트에 담긴 요소 개수를 확인하는 속성 리스트 포함 여부 확인 변수명.Contains(값) 특정 값이 리스트에 있는지 true/false로 확인 그룹형 변수 / 메서드예시 코드설명
string 배열 string[] monster = { "슬라임", "고블린", "드래곤" }; 문자열 배열 · 값을 아는 즉시 new 없이 중괄호로 바로 초기화 int 배열 (크기만 지정) int[] monsterlevel = new int[3]; 정수형 배열 · new int[3]으로 크기 3인 배열을 먼저 생성 (초기값은 전부 0) 배열 요소 값 할당 monsterlevel[0] = 1;
monsterlevel[1] = 5;
monsterlevel[2] = 10;인덱스는 0부터 시작 · 각 칸에 값을 하나씩 나중에 대입 string 리스트 생성 List<string> item = new List<string>(); 문자열 리스트 · 클래스이므로 new 필수, 크기가 고정되지 않고 늘어날 수 있음 리스트에 값 추가 item.Add("포션");
item.Add("엘릭서");Add()로 리스트 맨 뒤에 요소를 하나씩 추가 (배열의 [i] = 대입과 달리 인덱스를 직접 안 정해줘도 됨) 리스트에서 값 제거 item.RemoveAt(1); 인덱스 1번 요소("엘릭서")를 제거 · 제거 후 뒤에 있던 요소들이 앞으로 한 칸씩 당겨짐 그룹형 변수를 사용한 예시:

값 타입 (Value Type) 참조 타입 (Reference Type)
저장 위치 스택 (변수 자체에 값 직접 저장) 스택엔 주소만, 실제 데이터는 힙 대표 예시 int, float, bool, double, struct class, 배열, string, List<T>, Dictionary 등 new 필요 불필요 필요 (거의 항상) 기본값 (초기화 안 했을 때) 0, false 등 null (아무것도 안 가리킴) 참조 타입이 new가 필요한 이유:
C#의 타입은 두 종류로 나뉘는데
값타임(value type): int, float, bool, struct 등 변수 자체에 값이 직접 들어가는 타입
참조타입( reference type): 배열, class(List, string 제외하면 대부분), List <> 등 변수에는 값이 아니라 힙에 있는
객체의 주소만 들어감
배열, List <> 모두 참조 타입이라 실제 데이터가 들어갈 공간을 힙에 만드는 과정, 즉 new가 반드시 필요함
new의 경우 힙(heap)에 실제 객체를 만들고 그 객체가 있는 메모리 주소를 참조하여 돌려줌
예: int []scores = new int[5];
이 코드가 실행되면
1. 힙에 int 5칸짜리 공간이 실제로 생성
2. new int [5]는 그 공간의 주소값을 돌려줌
3 scores라는 변수(스택에 있는)에는 그 주소값만 저장
배열은 int [] arr = {1,2,3};처럼 new를 생략하여 선언과 동시에 초기값을 주는 문법이 허용되는 반면
( 이는 컴파일러가 배열에 한 한해서 컬렉션 이니셜라이저 문법을 특별 취급 해주기 때문,
내부적으로는 컴파일러가 자동으로 new int []를 붙여 사용, 생략되어 있는 것처럼 보이지만 실제로는 new가 사용됨)
List <>는 일반 클래스 이기 때문에 클래스는 이런 취급을 받지 못해 컴파일러가 어떤 생성자를 호출해서 객체를 만들지 자동으로
유추해주지 않아 항상 명시적으로 new를 써서 이 생성자를 호출해서 힙에 객체를 만들거라 지시해야 함

3. 연산자
연산자의 종류들
산술 연산자
연산자의미예시+ 더하기 5 + 3 → 8 - 빼기 5 - 3 → 2 * 곱하기 5 * 3 → 15 / 나누기 (몫) 7 / 2 → 3 (int끼리는 소수점 버림) % 나머지 7 % 2 → 1 대입 연산자
연산자의미동일한 표현= 값 대입 - += 더한 값 재대입 a = a + 5; -= 뺀 값 재대입 a = a - 5; *= 곱한 값 재대입 a = a * 5; /= 나눈 값 재대입 a = a / 5; ++ 1 증가 a = a + 1; -- 1 감소 a = a - 1; 비교 연산자 (결과는 항상 bool)
연산자의미== 같다 != 다르다 > 크다 < 작다 >= 크거나 같다 <= 작거나 같다 논리 연산자
연산자의미참이 되는 조건&& AND (그리고) 둘 다 true일 때 || OR (또는) 둘 중 하나라도 true일 때 ! NOT (반대로) 원래 값이 false일 때 true 삼항 연산자
연산자의미예시? : 조건에 따라 값 하나 선택 조건 ? 참일 때 값 : 거짓일 때 값 사칙연산 연산자를 사용한 예시:

4. 조건문
조건문 종류들:
종류설명if 조건이 true일 때만 실행 if-else 조건이 false일 때 실행할 코드도 함께 지정 else if 여러 조건을 순서대로 검사 switch 하나의 값에 대해 여러 경우의 수를 분기 · break 필수 조건문과 bool변수를 사용한 예시
위 그룹형 변수에서 초기값을 준 몬스터 배열을 활용한 Switch~case 문 예시:
5. 반복문
종류설명for 반복 횟수를 알 때 사용 (초기식, 조건식, 증감식 구조) while 조건이 true인 동안 반복 · 조건을 맨 앞에서 검사 do-while 일단 한 번 실행하고 나서 조건 검사 · 최소 1번은 무조건 실행 foreach 배열/리스트의 모든 요소를 처음부터 끝까지 순회 · 인덱스 관리 불필요 break 반복문을 즉시 강제 종료 continue 현재 반복만 건너뛰고 다음 반복으로 넘어감 bool 형과 if, else 조건문을 활용한 while 반복문

for문을 사용한 몬스터의 종류 구하기

foreach 문을 사용한 몬스터 종류 구하기

6. 함수 (메서드)
함수(메서드) 관련 개념
종류문법 형태설명메서드 선언 반환타입 메서드명(매개변수) { } 특정 동작을 수행하는 코드 묶음을 정의 매개변수 (Parameter) (자료형 변수명) 메서드를 호출할 때 외부에서 전달받는 값을 담는 변수 인자 (Argument) 메서드명(전달할 값) 메서드를 호출할 때 실제로 넘겨주는 값 반환타입 int, float, string, bool 등 메서드가 실행을 마치고 돌려주는 값의 자료형 void void 메서드명() { } 반환값이 없는 메서드 · 아무것도 return하지 않음 return return 값; 메서드를 즉시 종료하고 지정한 값을 호출한 쪽으로 돌려줌 메서드 호출 메서드명(인자); 정의해둔 메서드를 실제로 실행시킴 메서드 오버로딩 같은 이름, 다른 매개변수 구성 이름은 같지만 매개변수의 개수나 타입이 다른 메서드를 여러 개 정의 가능 접근 제한자 public, private 메서드를 다른 클래스에서 호출할 수 있는지(public) 없는지(private) 결정 static 메서드 static 반환타입 메서드명() 객체를 생성하지 않고 클래스 이름으로 바로 호출 가능한 메서드 유니티에서 자주 보는 특수 메서드
메서드호출 시점Start() 오브젝트가 처음 활성화될 때 딱 한 번 실행 Update() 매 프레임마다반복 실행 Awake() Start()보다 먼저, 오브젝트가 생성되자마자 실행 FixedUpdate() 물리 연산 주기(고정된 시간 간격)마다 실행 매개변수를 선언하고 리턴값을 돌려받는 heal 함수:

heal 함수를 호출(사용) 하여 hp라는 전역 변숫값을 직접 바꾸는 함수:

여기서 나오는 전역변수&지역변수 개념
전역변수 (필드) 클래스 내부, 메서드 바깥 public int hp = 100; 클래스 전체(모든 메서드)에서 접근 가능 · 객체가 살아있는 동안 값 유지 지역변수 메서드(또는 함수) 내부 int level = 1; 선언된 메서드 안에서만 접근 가능 · 메서드 실행이 끝나면 사라짐 for문과 매개변수를 이용한 함수 호출로 전투 메커니즘 예시 코드

7. 클래스
클래스 기본 개념
개념문법 형태설명클래스 선언 public class 클래스명 : MonoBehaviour 데이터(필드)와 기능(메서드)을 하나로 묶은 설계도 · : MonoBehaviour를 붙이면 유니티 게임 오브젝트에 붙일 수 있는 스크립트가 됨 필드 (멤버 변수) int hp = 100; 클래스 안에 선언하는 전역변수 · 이 클래스로 만든 객체가 가지는 데이터 메서드 (멤버 함수) void Attack() { } 클래스 안에 선언하는 함수 · 이 클래스로 만든 객체가 할 수 있는 행동 생성자 public 클래스명() { } 객체(new로 생성)가 만들어지는 순간 자동으로 실행되는 특수 메서드 · 초기값 설정에 사용 객체(인스턴스) 생성 클래스명 변수명 = new 클래스명(); 설계도(클래스)를 바탕으로 실제 데이터를 힙에 만드는 것 접근 제한자
제한자의미public 다른 클래스/스크립트에서도 접근 가능 private 선언된 클래스 내부에서만 접근 가능 (기본값) protected 선언된 클래스와 이를 상속받은 자식 클래스에서만 접근 가능 상속
개념문법 형태설명상속 class Dog : Animal { } 부모 클래스(Animal)의 필드/메서드를 자식 클래스(Dog)가 그대로 물려받음 오버라이드 protected override void Update() { } 부모 클래스의 메서드를 자식 클래스에서 재정의(다시 구현) base 키워드 base.Update(); 자식 클래스 안에서 부모 클래스의 원래 메서드를 호출 유니티에서 자주 쓰는 특수 클래스/개념
개념설명MonoBehaviour 유니티가 제공하는 기본 클래스 · 이걸 상속해야 스크립트를 게임 오브젝트에 컴포넌트로 붙일 수 있음 Start() 게임 오브젝트가 생성된 후 딱 한 번 자동 실행되는 메서드 (MonoBehaviour가 제공) Update() 매 프레임마다 자동으로 반복 실행되는 메서드 (MonoBehaviour가 제공) this 클래스 자기 자신(현재 객체)을 가리키는 키워드 클래스 vs 구조체(struct) 비교
classstruct타입 종류 참조 타입 값 타입 저장 위치 힙 스택 new 필요 여부 필요 선택 (없어도 됨) 상속 가능 불가능 유니티 대표 예시 MonoBehaviour, ScriptableObject Vector3, Quaternion, Color 클래스&상속성을 활용한 예:
Actor 클래스 Cs을 하나 생성 후
각 플레이어의 기초가 되는 변수들을 하나씩 생성(Actor 클래스에
플레이어(또는 몬스터 등 캐릭터)의 기초가 되는 변수들을 필드로 미리 정의해 두면,
new Actor()로 인스턴스를 만드는 것만으로 그 변수들을 전부 갖춘 객체가 만들어진다.
그래서 본 파일에서 id, name, weapon 같은 변수를 하나하나 따로 선언할 필요 없이,
player.id, player.name처럼 바로 접근해서 쓸 수 있다.)
본 파일에서 접근하기 위해 변수들 앞에 public 적용

이를 다시 처음 스크립트 (유니티 엔진 오브젝트 클래스를 상속한)에서 new를 사용해 객체 인스턴스로 선언 후 사용
인스턴스의 변수의 값을 할당하고 호출 및 사용이 가능

Player라는 새로운 클래스 파일을 만들어 Actor를 상속받음

상속받은 클래스를 인스턴스로 선언해
자식 클래스인 Player의 메서드도 사용 가능하고
부모 클래스인 Actor 또한 메서드로 사용이 가능함.
NewMonoBehaviourScript.cs0.01MBPlayer.cs0.00MBActor.cs0.00MB본 내용에서 사용한 소스들을 첨부합니다