변수 : 메모리에 할당(적재)
ex) 숫자, 문자, 문자열, bool, 텍스처, 게임오브젝트(class)
변수이름 xx ~만큼(size)
사이즈 명시 = 자료형
ex) (int) (hp) = (1);
(자료형) (변수명) = (값);
자료형 : 어떤 식으로 적재 할거다(크기 포함)
1바이트 = 8비트
1비트는 (0과1) 2개 표현
1바이트는 2의 8승 256개 표현 가능
signed(음수까지 표현)
u~ unsigned(0부터 양수 표현)
리터럴 – 따로 선언 안 하고 그냥 숫자 사용 ex) a = 15; (여기서 a가 상수 15가 리터럴)
게임프로그래밍에서..
변수 -> 명사
함수 -> 동사
ex) FPS 게임
총을 쏴서 적군을 맞춘다.
명사 – 총, 적군
동사 – 쏴서 맞춘다.
숫자 – 정수형, 실수형
int와 long
ex) 귀찮아서 long으로 쓰면 하나 당 8바이트가 1000개 있으면 FPS가 30이라고 쳤으면 8000*30 = 240000 너무 커짐 ** 주의
nint
nuint
32bit os 64bit os
runtime(운영체제에 따라 달라짐) word
게임 만들 때 자료형보다 큰 숫자로 넘어간다면 overflow로 다시 최소값부터 시작
underflow는 자료형보다 작은 숫자가 될 때 => 웬만하면 int
cf) 네트워크를 들어갈 때 opcode일 때 byte 사용할 때가 있음
값 참조 vs 주소 참조
값을 참조할 때는 값만 복사해서 대상과 독립적으로 사용하는 경우고
주소를 참조할 때는 같은 대상의 주소를 담아서 직접 사용하는 경우다.
부동소수점 / 고정소수점
부동 – float(부유하다, 떠다니다) => 지수를 안 정함
- 부호비트 +-
- 32비트 1비트에서 최상위 비트 - 부호비트
- 가수에서 쓸 만큼만 쓰고 나머지를 소숫점을 표현하는 데 씀 => 경계가 떠다님
오차가 생길 수 있음
고정 – fixed => 지수를 정하고 감
가수x밑수(지수 – 제곱표현)
특징)
가수가 커지면 지수가 작아짐(정확도 내려감)
지수가 커지면 가수로 표현할 부분이 줄어듬(정확도 올라감)
용량이 큼(메모리 잡아먹음)
ex) 10진수 4.123
가수 4123
밑수 10
지수 –3
4123x10(-3)
float(4바이트) vs double(8바이트)
지수를 표현하는 부분이 float과 double이 다름
비트를 사용하는 부분이 다르기 때문
소수를 비교할 때 a == b 등 등치 비교는 잘 안 함
=> 오차 범위를 지정하거나 문자열화 시켜서 비교(얼추 맞을 수 있음)
소수점 어떻게 표현?
- IEEE 754 표준
암시적 자료형 var
var 쓰는 이유
- 변수를 선언하는데 숏코딩을 위해 사용
특징
- 지역변수로만 사용 가능
- 숫자 타입은 var 지양(형변환 문제 때문에)
- 가독성 문제
ex)
int a = 3; // var a = 3;
float b = 1.23f; // var b = 1.23f;
char c = ‘h’; // var c = ‘h’;
문자형 / 문자열
char / string
‘’ / “”
string은 char의 배열
string은 내장 클래스도 있음
bool형 : 참과 거짓을 위한 자료형
c#에서 true와 false 아니면 값 안 받음
ex) bool isTrue = true;
배열
– 같은 자료형 + 이름 + 메모리 상에 순차 저장
ex) int[5] arrayHp = new int[5];
0번부터 시작 int라면 4바이트 크기만큼 담기고 그 다음으로
c# .NET Framework Array라는 클래스 사용 – 내장함수 포함
List
Collection
IEnumerable – 순회
c#
int[ ][ ] 가변길이 배열
int[ , ] 다차원 배열
연산자
산술연산자
+, -, *, /, %
복합대입 연산자
+=, -=, *=, /=, %= 등등
증감연산자
++, --
전위 연산자
ex) ++i, --i
후위 연산자
ex) i++,i--
비교 연산자
==, >=, >, <=, <
논리연산자
&&, &, ||, |, !, ^
ex) Instanciate(“Enemy”) == null
중요! 많이 나오는 실수
&&를 쓰면 앞에서 false일시 뒤의 나머지 부분을 스킵하는데
&를 쓰면 조건문에서 앞에가 false여도 조건 부분은 실행됨
||를 쓰면 조건문에서 앞에가 true일시 나머지 부분을 스킵하는데
|를 쓰면 조건문에서 앞에가 true여도 조건 부분을 다 실행함
ex) bool a = true;
a &= false;
a = false && a;
a |= false
연산자 우선순위(Microsoft Docs)
형변환(캐스트 : 형태에 맞춰서 본을 뜸)
암시적 형변환
- 담을 형태 변수 = 담길 변수;
- int를 float에 담는 것은 가능
- float -> double 괜찮음
명시적 형변환
- 담을 형태 변수 = (담을 형태와 같은 바꿀 형태)담길 변수;
- float을 int에 담는 것은 불가능(상실되는 부분이 많으면 명시적)
- double(8바이트) -> float(4바이트)은 X
- 명시적으로 = 뒤 부분에 (double)을 붙여줘야 됨
ex)
float a = 5f;
a = 5; // 암시적 형변환
float b = (int)a; // 명시적 형변환
예약어
사용자 변수를 선언할 때 예약어는 쓰면 안 됨
C#예약어(Microsoft Docs)
코드 표기법
파스칼 케이스 : 단어들이 연속적으로 이어질 때 각 단어의 첫글자를 대문자로 사용
ex) PlayerName
카멜 케이스 : 단어들이 연속적으로 이어질 때 첫 단어를 제외하고 각 단어의 첫글자를 대문자로 사용
ex) playerName
- 회사마다 가이드가 다름(미리 숙지를 하면 좋음)
코딩 컨벤션(표준)
- 변수이름 설정하는 게 중요
조건문
if (조건)
{
// 실행문
}
반복문
for문
for (var i = 0; i < 5; i++)
{
Debug.Log(i);
}
Coroutine
yield return
변수 => 데이터형을 메모리에 올리는 것
배열 – int[] student = new int[5];
배열만으로 다루기 어려움
=> 클래스를 만들자
클래스 : 어떤 문제를 해결하기 위한 데이터를 만들기 위해 추상화(쓰고자 하는 내용)
ex) 챔피언의 hp mp status를 필요한 것만 빼놓은 것
캐릭터 A(name)가 공격(Attack)을 하면 메소드 {데미지(명사) 10이 박힌다(동사)} .
이런 개념이 합쳐지면 클래스가 됨
메서드
형식
public void Move () {}
접근한정자 반환형(리턴형) 메서드이름 매개변수 {뭐할지}
ex)
public int Add(int a, int b)
{
return a + b;
}
int a = 1;
int b = 3;
int result = a + b;
debug.Log(result);
int newResult = Add(1, 3);
debug.Log(newResult);
- 반환형 void – 반환 값이 없음 (return 안 써줘도 됨)
- 반환형 나머지(int, string , , ,) 맞는 형이 return에 나와야 됨
- 매개변수 – 받을 땐 형식 명시 줄 땐 그냥 형식에 맞춰서 보내면 됨
- 함수를 래핑도 가능 Debug.Log(string str);를 시간을 찍히게 MyLog(string str);로 만들 수 있음
클래스
Champion champ = new Champion();
클래스 변수명 = new한정자 클래스 생성자 ;
ex)
class Champion
{
int hp;
int mp;
int Add(int a, int b)
{
return a + b;
}
}
ex) int[] arr = new int[]4;
- new는 클래스 new 한정자이다. 자료형과는 다르게 참조형 자료형이다.
- int, string 등등은 값형 자료형
오버로딩
함수 이름은 같은데 매개변수의 타입이 다름
- 오버로딩으로 구현하면 같은 함수를 작성했을 때(Add를 썼을 때 위아래 방향키를 눌러서 다른 함수를 선택할 수 있음 => 개발 편의성)
ex)
public float Add(float a, float b)
{
return a + b;
}
// 매개변수가 같고 반환 값이 다른 경우는 에러 뜸
한정자
ex)
class System
{
int hp;
int lv;
public int GetHp()
{
return hp;
}
private void SetLvUp()
{
lv++;
}
}
class Program
{
static void Main(string[] args)
{
System system = new System();
int hp_ = system.GetHp();
// system.SetLvUp(); 에러 – private라서
}
}
유니티에서 inspector에서 접근하고 싶을 때 코드 상으로는 private여야 한다면 무지성 public말고
[SerializedField]
private int hp = 0; 이런 식으로 선언해야 한다.
생성자
ex)
Champion champ = new Champion();
champ.hp = 500;
Champion champ = new Champion();
champ.hp = 600;
Champion champ = new Champion();
champ.hp = 700; 일 때 항상 넣기 힘드니까
class Champion
{
int _hp;
int _mp;
// 외부에서 접근하니까 public
public Champion(int hp, int mp)
{
_hp = hp;
_mp = mp;
}
}
소멸자
ex)
~Champion()
{
Debug.Log(“Free”);
_hp = 0;
_mp = 0;
}
프로퍼티(property)
ex)
public int HP
{
// champ.HP => get을 호출
// 무조건 return을 써줘야됨
get
{
return _hp;
}
// champ.HP = -100; => set을 호출
// 무조건 value라는 값을 써줘야됨
set
{
if (value < 0)
{
value = 0;
}
_hp = value;
}
}
// 다른 클래스에서
int A = champ.HP; => get
champ.HP = -100; => set
// HP 값 자체에는 접근 가능, 받아올 수 있음
public int HP { get; set; }
// 가져오는 건 가능한데 넣는 건 작업을 막을 수 있음
public int MP { get; private set; }
값 자료형, 참조 자료형, 클래스 자료형
값 자료형
ex)
int a = 20;
TestValue(a);
Debug.Log(a); // 출력 값 20
void TestValue(int a)
{
a = 10;
}
참조 자료형
ex)
int[] a = new int[1]{ 20 };
TestValue(a);
Debug.Log(a[0]); // 10 출력
void TestValue(int[] a)
{
a[0] = 10;
}
클래스 자료형
ex)
class TestValueClass
{
public int value = 0;
}
void TestValue(TestValueClass t)
{
t.value = 10;
}
// 다른 클래스에서
TestValueClass tvClass1 = new TestValueClass();
tvClass1.value = 20;
TestValue(tvClass1);
Debug.Log(tvClass1.value);
string a = “Test”;
Debug.Log(a);
TestValue(a);
Debug.Log(a);
TestValue(string a)
{
a = “Test2”;
}
상속
부모로부터 자식이 속성이나 특성을 물려받음
// 챔피언 아칼리 아리 아무무
// 속력 2 3 4
// Move(); SkillQ,W,E,R 챔피언마다 조건이 다름
public class Champion
{
public int _lv = 1;
public int _hp = 650;
public int _mp = 0;
public void Move()
{
Debug.Log(“Move”);
}
public virtual void SkillQ()
{
Debug.Log(“SkillQ”);
}
public virtual void SkillW()
{
Debug.Log(“SkillW”);
}
public virtual void SkillE()
{
Debug.Log(“SkillE”);
}
public virtual void SkillR()
{
Debug.Log(“SkillR”);
}
}
// 다른 클래스
public void new Move()
{
Debug.Log(“Move”);
}
가상 함수
virtual – 부모 객체의 함수를 자식들을 통해서 변화를 줄 수 있음
한정자
base 한정자 - 부모
new 한정자 – 덮어씀
접근 한정자
public – 외부 접근 가능
protected – 자식(파생 클래스)에서 접근 가능
private - 같은 클래스 내에서 접근 가능
외의 개념들
모듈화 : 기능적인 기본 사양을 공유하는 그룹핑을 지은 unit
상속 : 이미 부모에서 구현된 거에서 갖다 쓰는 것
라이브러리 : using을 통하여 갖다 씀
[Serializable] - 클래스 위에 쓰여서 인스펙터에 정보가 뜨게 함