코드카타 문제는 쉬웠는데 내가 스스로 원하는 시스템으로 세팅하는데 오래 걸림, C는 여전히 진도가 너무 느리다 (비개발자 기준으로 말하는 것), UE5 BP는 급 어렵다. 개념은 다 아는데 내가 생각하고 원하는 노드를 어디서 어떤 이름으로 생성하는지 찾는데 오래 걸린다.
Agenda: Start 코드카타, C언어 세션-가벼운 리뷰 & 혼자 공부, Unreal Blueprint 라이브 세션 - Line Trace, Spawn System, Effect, Sound, UI
Start 코드카타
코드카타 처음 해봤는데 초반이라 문제 자체는 매우 쉬웠다.
예전에 공부하고 알고리즘 해본다고 테스트할 때는 아무것도 모르겠어서 아예 손을 못 댔었는데 일단 시작을 쉬운 문제로 하니깐 아직은 맘이 편하다.
오늘 문제 정리: https://github.com/devcol-main/CodeKata/blob/main/Programmers/두 수의 차 구하기.md
코드카타 깃 링크: https://github.com/devcol-main/CodeKata
개인적으로 한 일
- 영어문제로 된 뱅크 사이들 찾고, 어디가 유용한지, 어떨 때 쓰는지 정리.
- 동기화 및 세팅: 옵시디언 - 구글 드라이드 - 깃허브
- 구글 드라이브 와 옵시디언 동기화 해서 백업해둠 (추후 노트북 반납해야 하니)
- 그 폴더 깃허브 repository 랑 연결
- 좀 찾아보니깐 n8n이나 zapier 같이 자동화해서 등록하는 사람도 있던데 우선 현재 세팅한 거 좀 익숙해지면 나도 추후 자동화 해버려야겠다.
힘들었던 것들
- 여러 가지 동기화해서 세팅하는 것 (처음에 생각을 잘 못해서 너무 복잡하게 생각함…)
- Mark Down 안 그래도 익숙하지 않은데, 너무 오랜만에 만져서 읽는데 오래 걸렸다. 특히 옵시디언 세팅 몇 개 때문에 원하는 데로 실행이 안돼서 그거 세팅하는데도 오래 걸렸다…
C언어 세션-가벼운 리뷰
인코딩(Encoding) Vs. 디코딩(Decoding)
- 형태 A에서 형태 B로 변환하는 것 vs 반대로 형태 B에서 형태 A로 변환하는 것
ASCII (American Standard Code for Information Interchange)
- 문자 형태의 데이터와 숫자 형태의 데이터 사이의 인코딩 규약 중 하나. 여러 인코딩 규약이 있으나, 그중 가장 쉽고 대표적인 규약.
- C++ ASCII Chart: ASCII Chart - cppreference.com
- 과거에는 ASCII, EUC-KR 등등 각 나라마다 다른 문자 인코딩들이 존재했지만 서로 호환되지 않아 지원에 문제가 생김. 그래서 전 세계 모든 문자를 표현 및 처리하기 위해 만들어진 문자 인코딩이 유니코드(Unicode)이다.
- 유니코드에는 UTF-8, UTF-16, UTF-32가 있다
- 유니코드(UTF-8, 16, 32)의 주된 차이는 문자를 표현하는 데 사용하는 비트(바이트) 수와 저장 공간 효율성
입력 기초
scanf( )
- 키보드로부터 데이터를 입력받을 수 있게끔 해주는 함수.
#define _CRT_SECURE_NO_WARNINGS // scanf() 함수를 쓸때는 이걸 정의해줘야 합니다. #include <stdio.h> // 다만 scanf() 함수는 stdio.h에 정의되어 있으므로, stdio.h 파일 인클루드 전에 정의해야 합니다. int main(void) { int Num; scanf("%d", &Num); // "Num에다가(&) %d 형식으로 입력받아라." printf("%d", Num); // "Num을 %d 형식으로 출력해라." return 0; }
연산자(Operator) Vs. 피연산자(Operand)
- 피연산자와 함께 사용되어서 계산 결과를 만들어 내는 기호. ex) 5 + 2에서 5와 2를 피연산자, +를 연산자.
연산자 우선순위(Operator Priority)와 결합법칙
- 좌에서 우로 계산하지만 그 안에서도 우선순위존
- ex: 5 +1 x 2 = 7 (곱셈 먼저, 그다음 덧셈)
- 연산자 우선순위: Precedence and order of evaluation | Microsoft Learn
산술 연산자의 종류
- 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지(%).
정수 피연산자와 실수 피연산자
- int 자료형끼리의 나눗셈은 그 결과도 int. float 자료형끼리의 나눗셈은 그 결과도 float임에 주의하셔야 합니다. 또, C언어에서는 float 자료형의 나머지 연산은 불가능합니다.
복합 대입 연산자
- 산술 연산과 대입 연산이 함께 계산되는 연산자.
- num = 3; // num = num 3과 동일
값(Value), 식(Expression), 문(Statement)
증감 연산자 Increment and Decrement Operators (++,—)
전치/후치 의미
- 전치는 지금 당장, 후치는 다음 줄에 연산됩니다.
- ex) ++Num이라면 지금 당장 Num이 1 증가. Num++이라면 다음 줄에 Num이 1 증가.
논리 연산자의 종류
- 논리 곱 연산자(&&), 논리 합 연산자(||), 논리 반전 연산자(!), 대등 연산자(==), 반대로 다르다는!=
if, if-else, if - else if - else, 중첩 if
- 조건문 꿀팁: 조건문에는 조건식이 나옵니다. 조건식은 보통 부등식으로 표현이 되는데, 머릿속에 수평선을 그려서 해석하면 쉽습니다.
- if (x >= 10 && x >= 15) // worst
- if (10 <= x && x <= 15) // best
switch-case문
“윤성우의 열혈 C 프로그래밍” 책 읽으면서 따로 리뷰한 것들
up to chapter 9
비트(Bit)와 바이트 (Byte)
- 비트 컴퓨터가 표현하는 데이터의 최소단위의 메모리 크기를 뜻 하는 단위
- 2진수 값 하나
비트를 8개 묶으면 ‘바이트’
- 0: 1비트
- 01010101 : 8비트 == 1바이트
따라서 00000000 00000000 00000000 00001111은 10진수로 15를 의미

!!! 정수의 가장 왼쪽에 존재하는 비트는 ‘부호비트’이다
비트 연산자
- & : 비트 단위로 AND 연산 (예: num1 & num2)
- 0 & 0 // 0 0 & 1 // 0 1 & 0 // 0 1 & 1 // 1 int num1 = 15 // 00000000 00000000 00000000 00001111 int num2 = 20 // 00000000 00000000 00000000 00010100 int ans = num1 & num2; // ans = 4 00001111 & 00010100 결과: 00000100
- | : 비트 단위로 OR 연산 (예: num1 | num2)
- 0 | 0 // 0 0 | 1 // 1 1 | 0 // 1 1 | 1 // 1 int num1 = 15 // 00000000 00000000 00000000 00001111 int num2 = 20 // 00000000 00000000 00000000 00010100 int ans = num1 | num2; // ans = 00001111 | 00010100 결과: 00011111 //31
- ^ : XOR
0 ^ 0 // 0
0 ^ 1 // 1
1 ^ 0 // 1
1 ^ 1 // 0
int num1 = 15 // 00000000 00000000 00000000 00001111
int num2 = 20 // 00000000 00000000 00000000 00010100
int ans = num1 | num2; // ans =
00001111
^ 00010100
결과: 00011011 //27
- ~ : 단항 연산자로서 피연산자의 모든 비트를 반전
~ 0 // 1
~ 1 // 0
int num1 = 15 // 00000000 00000000 00000000 00001111
int ~num2 = num1
int num2 // -16
~num1 // 11111111 11111111 11111111 11110000
- << : 피연산자의 비트 열을 왼쪽으로 이동
- “비트의 열을 왼쪽으로 1칸씩 이동시킬 때마다 정수의 값은 두 배가 된다”
- “비트의 열을 오른쪽으로 1칸씩 이동시킬 때마다 정수의 값은 2로 나누어진다”
- 이걸 잘 기억하면 상황에 따라서 곱셈과 나눗셈 연산은 비트 이동으로 대체가능
- CPU 입장에서는 곱셈과 나눗셈이 비트의 이동보다 부담스러운 연산이기 때문에
int num = 15 // 00000000 00000000 00000000 00001111
int result1 = num<<1;
int result2 = num<<2;
int result3 = num<<3;
result1 // 30 // 00011110
result2 // 60 // 00111100
result3 //120 // 01111000
- : 피연산자의 비트 열을 오른쪽으로 이동
- 연산자와 << 연산자의 가장 큰 차이점은 비트의 열을 이동시키는 방향에 있다.
- 음수는 조금 다르게 계산해야 함!!! CPU 따라서 다르다…
- 11111111 11111111 11111111 11110000 // -16
- 2칸 >> 이동할 때 (아래의 두 가지 경우가 생김
- 00111111 11111111 11111111 11111100
- 11111111 11111111 11111111 11111100
- 2칸 >> 이동할 때 (아래의 두 가지 경우가 생김
게임에서 바이트로 비트 연산해서 상태머신 (State Machine) 표현 가능.
자료형
C언어 주요 자료형 크기 및 범위 (32/64비트 표준 환경)
| 정수형 | char | 1바이트 | -128 ~ 128 |
| short | 2바이트 | -32,768이상 32,767이하 | |
| int | 4바이트 | -2,147,483,648 이상 2,147,483,648이하 | |
| long | 4바이트 | -2,147,483,648 이상 2,147,483,648이하 | |
| long long | 8바이트 | -9,223,372,036,854,775,808 이상 | |
| 9,223,372,036,854,775,808 이하 | |||
| 실수형 | float | 4바이트 | ± 3.4 x 10−37이상 |
| ± 3.4 x 1038이하 | |||
| double | 8바이트 | ± 1.7 x 10−307이상 | |
| ±1.7 x 10+308이상 | |||
| long double | 8바이트 이상 | double이상의 크기 |
자료형 크기 값의 표현 범위
연산자 sizeof를 사용해서 자료형의 크기 파악가능
- ex: int num = 10; int sz1 = sizeof(num); // 결과 4
unsigend를 붙여서 0과 양의 정수만 표현하게 할 수 있다 그러면 표현할 수 있는 값이 0 이상의 범위로 두 배가 된다.
정수형 상수 접미사
정수 뒤에 붙여 int 대신 long, unsigned 등으로 자료형을 지정합니다.
- U / u: unsigned int (예: 15U)
- L / l: long (예: 123456789L)
- UL / ul: unsigned long (예: 100000 UL)
- LL / ll: long long (예: 123456789012345 LL)
- ULL / ull: unsigned long long
실수형 상수 접미사
실수는 기본이 double이므로, float나 long double을 표현하기 위해 사용합니다.
- F / f: float (예: 3.14f)
- L / l: long double (예: 3.141592L)
#include <stdio.h>
int main() {
float f = 3.14f; // float형 (접미사 f 필수)
long l = 1000000L; // long형
unsigned long ul = 100UL; // unsigned long형
long long ll = 10000000000LL; // long long형
printf("%f, %ld, %lu, %lld\\n", f, l, ul, ll);
return 0;
}
이름을 지니는 심볼릭(Symbolic) 상수: const 상수
- Naming 시 “상수의 이름은 모두 대문자로 표시하고, 둘 이상의 단어로 연결할 때에는 MY_AGE와 같이 언더바를 이용해서 두 단어를 구분하는 것이 관례이다”
- 선언 시 꼭 초기화 같이 해야 함
자료형의 변환
- double num1 = 245 // int형 정수 245를 double 형으로 자동 형 변환
- int num2=3.1414 // double 형 실수 3.1414를 int 형으로 자동 형 변환
- 실수형 데이터를 정수형 데이터로 변환하는 과정에서는 ‘소수부의 손실’이 발생한다
- 정수를 실수로 형 변환하는 경우: 실수로 표현, 실수의 표현범위가 정수에 비해 넓기 때문에 데이터의 손실은 일어나지 않는다. 다만, 실수의 표현이기 때문에 오차는 존재
- 실수를 정수로 형 변환하는 경우: 정수는 소수점 이하의 값을 표현하지 못하기 때문에, 소수점 이하의 값은 버려진다.
- 바이트 크기가 큰 정수를 바이트 크기가 작은 정수로 형 변환하는 경우: 변환하고자 하는 정수의 바이트 크기에 맞춰서 상위 바이트를 단순히 소멸시킨다. 그리고 이로 인해서 부호가 바뀔 수도 있으니 주의 필요.
- 정리: “데이터의 표현범위가 보다 넓은 자료형으로의 형 변환은, 그 과정에서 데이터의 손실이 발생하지 않지만, 데이터의 표현범위가 좁은 자료형으로의 형 변환은, 그 과정에서 데이터의 손실이 발생할 수 있다”
정수의 승격(Integral Promotion)
- “일반적으로 CPU가 처리하기에 가장 적합한 크기의 정수 자료형을 int로 정의한다. 따라서 int형 연산의 속도가 다른 자료형의 연산속도에 비해서 동일하거나 더 빠르다”
- int형 연산이 short형 연산보다 빠르다
피연산자의 자료형 불일치로 발생하는 자동 형 변환
- 피연산자의 자료형이 일치하지 않아서 발생하는 자동 형 변환은 데이터의 손실을 최소화하는 방향으로 진행된다.
- int → long → long long → float → double → long doublen cx
명시적 형 변환: 강제로 일으키는 형 변환 (형 변환 연산자 type casting operator)
int num1;
double num2;
divResult = (double)num1 / num2;
특수문자의 종류
C언어 주요 이스케이프 시퀀스 목록
- \\n (Newline): 줄 바꿈. 가장 많이 사용되는 특수문자.
- \\t (Horizontal Tab): 탭만큼 간격을 띄움.
- \\\\ (Backslash): 백슬래시(\\) 기호 자체를 출력.
- \\" (Double Quote): 큰따옴표(")를 문자열 내에서 출력.
- \\' (Single Quote): 작은따옴표(')를 출력.
- \\b (Backspace): 한 칸 백스페이스.
- \\r (Carriage Return): 줄의 처음으로 커서를 이동.
- \\a (Alert): 시스템 경고음 발생.
- \\? (Question Mark): 물음표(?)를 출력
서식 지정자 (Format Specifiers)
- %d: 10진수 정수
- %f: 실수
- %c: 문자 하나
- %s: 문자열
- %x: 16진수
- %o: 8진수
- %u: 부호 없는 10진수
반복문 (while, do~while, for)
반복문의 생략과 탈출 (continue & break)
- continue: 조건 검사로 이동
- break: 반복문 탈출
조건에 따른 흐름의 분기 (if, else if, else)
switch
- switch에서 break는 case의 다음 영역으로 이동
goto
- 프로그램의 흐름을 원하는 위치로 이동시킬 때 사용하는 키워드
- 편하지만 큰 단점은 ‘프로그램의 자연스러운 흐름을 방해한다’, 그렇기 때문에 극히 제한하는 추세
Unreal Blueprint 라이브 세션 - Line Trace, Spawn System, Effect, Sound, UI
Line Trace & 데미지 시스템
- 캐릭터 눈(카메라)에서 앞으로 쭉 직선을 하나 쏴요. 그 직선이 적에게 닿으면 맞았다!, 벽에 닿으면 벽이다!, 아무것도 안 닿으면 허공이다! — 이걸 알려주는 기능입니다.
- 시작점 — 어디서 쏠 건지 (예: 카메라 위치)
- 끝점 — 어디까지 쏠 건지 (예: 카메라 앞 10000cm → 100m),
- 결과 — 뭔가에 맞았는지, 맞았다면 뭐에 맞았는지
총으로 쏠 경우 임에서 흔히 표현하는 hit-scan 이란 개념
- Camera Location + (Forward Vector * 6000) 그럼 이러한 공식이 나오고 시작 위치로부터 앞 방향으로 6000cm(60m) 전진하게 됩니다.
- Line Trace By Channel detail패널을 열어서 Draw Debug Type을 For Duration으로 변경해서 5초 동안 보이게 합니다.
- Draw Debug Type을 지정하는 것은 라인이 그어지는 것을 눈으로 보기 위함입니다.
- spare line trace (multi vs single)
- 멀티는 중첩되는 거 다 검사
- 싱글은 하나
Muzzle Flash, Impact Effect:
- Muzzle Flash (머즐 플래시) — 총을 쏘는 순간 총구에서 빵! 하고 나오는 불꽃 이펙트!
- Impact Effect (임팩트 이펙트) — 총알이 벽이나 바닥에 탁! 하고 부딪힐 때 나오는 먼지/파편 이펙트!
나이아가라 vs 캐스케이드
- 소환 방식이 다름
- Cascade Particle System은 나이아가라(Niagara)가 나오기 전에 쓰던 이펙트 시스템입니다.
- P_가 붙은 에셋들이 캐스케이드 방식입니다.
Spawn System Attached
- Muzzle Flash 타입이 나이아가라기 때문에 이 이팩트를 불러오기 위해서 Spawn System Attached노드를 사용합니다.
이펙트 계속 나오는 문제 해결
- 이제 NS_MuzzleFlash로
- Flash_01 이런 식으로 되어 있는 노드가 Emitter(이미터).
- 이제 이미터 하나하나 누르면서 Loop Behavior를 Once로 변경.
Effect 사이즈 줄이기
- Location Type에 Snap to Target, Including Scale을 선택합니다.
- Keep Relative Offset → 붙인 컴포넌트 기준으로 위치 차이(오프셋)를 유지한 채 따라감
- Keep World Position → 스폰된 월드 위치 그대로 고정, 따라가지 않음
- Snap to Target, Keep World Scale → 타깃에 딱 붙되, 크기는 월드 기준 유지 (부모 스케일 무시)
- Snap to Target, Including Scale → 타깃에 딱 붙고, 부모의 크기까지 따라감 (지금 선택한 것)
- 해당 나이아가라 VFX가 메모리에 쌓이지 않도록 메모리에서 자동 정리하기 위해 Auto Destroy
총기반동
- Add Controller Pitch Input노드 & Add Controller Yaw Input노드
- Random Float in Range노드
Sound
- Audio에 박스를 쳤는데 Audio 말고 그 오른쪽 Cue에 있는 Sound Cue를 사용
- Sound Cue는 여러 소리를 섞거나, 랜덤 재생하거나, 볼륨/피치를 조절할 수 있게 가공하는 사운드 편집 도구
- Play Sound 2D노드를 배치하고 Sound에 FirstPersonTemplateWeaponFire02_Cue를 선택
- 총사운드가 조금 크기 때문에 줄인다 Volume Multiplier → 0.3으로 조정해서 30%만 들리게
연발 사격
- Is Firing을 Started, Completed에 놓고 Started에는 Is Firing을 true
- 결국 왼쪽 마우스 버튼을 누른 상태면 IsFiring은 계속 true
- 이때 Fire함수가 호출되고 사운드, 이펙트, 라인트레이스가 일어난 후 FireInterval만큼 잠시 대기하고 지금 계속 마우스 좌클릭을 하고 있다면 IsFiring이 true기 때문에 다시 Fire함수를 호출합니다.
- 만약 좌클릭 후 손을 떼면 Fire 함수가 한 번 호출되지만, 그 후에 IsFiring은 손을 떼는 순간 Completed 실행 핀이 실행되면서 false가 저장되어서 Fire 함수가 다시 호출되지 않습니다.
함수:
- 함수는 자주 쓰는 기능을 하나로 묶어서 이름 붙인 것. 매번 같은 노드를 반복해서 연결하는 대신, 한 번 묶어두고 이름만 불러서 실행할 수 있다.
- 코드가 깔끔해지고 관리가 편해.
크로스헤어 & 탄약 표시 UI
User Widget:
- User Widget은 화면에 표시되는 UI 한 장
- 크로스헤어, 탄약 텍스트, 체력바 같은 걸 이 위젯 안에 배치해서 화면에 띄움. Widget Blueprint를 만들면 이 User Widget을 시각적으로 편집 가능
- UI폴더 안에서 우클릭하고 User Interface → Widget Blueprints 선택.
- 보통 UI는 Widget Blueprints를 많이 사용.
- 팔레트에서 canvas 검색 후 드래그 앤 드롭해서 배치합니다. (canvas는 그냥 도화지)
- progress bar
- 오른쪽 디테일에서 HP라고 이름 변경, Is Variable선택 → 이것을 해야 다른 캐릭터나 외부에서 HP값을 변경할 수 있다.
- Progress 밑에 Percent는 1로 변경. 1 == 100%
- 이제 text검색 후 2개 canvas안으로 배치.
- text 2개 모두 선택 후 Anchors를 선택하고 ctrl + shift 누르고 왼쪽 아래 위치를 클릭.
- ctrl + shift를 눌러야지 이제 원하는 위치에 정확하게 배치.
- text 2개 모두 선택 후 Anchors를 선택하고 ctrl + shift 누르고 왼쪽 아래 위치를 클릭.
- 젯 만들고 이 위젯을 화면(View port)에 붙여야 함
- create widget return value → add to view port target과 연결
크로스바
- image, Anchors에서 ctrl + shift 누르고 중앙
- Detail → Appearance → Image 선택하고 Anchor 이미지
- 이미지가 없으면 레벨로 나가서 → 콘텐츠 브라우저 → Setting Show Engine Content버튼이 체크가 되어 있어야 우리가 사용하는 이미지 보임
Fire 로직 수정
- Fire함수로 오면 총기 반동 로직이 보인다.
- Line Trace함수보다 앞에 있어서 쏘는 순간 원하는 위치에 안 맞아서 이 총기 반동 로직을 라인트레이스 뒤에 두자.
오늘의 핵심 정리
| Line Trace By Channel | 카메라에서 보이지 않는 레이저를 쏴서 뭔가에 맞았는지 확인. Start(카메라 위치) + End(앞 방향 × 거리) |
| Break Hit Result | 맞은 결과를 분해. Impact Point(맞은 위치), Impact Normal(표면 방향), Hit Actor(맞은 물체) 등 |
| Niagara vs Cascade | 나이아가라(NS_) = Spawn System, 캐스케이드(P_) = Spawn Emitter. 에셋 타입에 맞는 노드 사용 |
| Auto Destroy | 스폰된 이펙트가 끝나면 메모리에서 자동 삭제. 체크 안 하면 메모리에 계속 쌓임 |
| Sound Cue | 여러 소리를 섞거나 랜덤 재생, 볼륨/피치 조절할 수 있는 사운드 편집 도구 |
| 함수 (Function) | 자주 쓰는 노드를 하나로 묶어서 이름 붙인 것. 선택 후 우클릭 → Collapse to Function |
| 연발 사격 | IsFiring + Started/Completed + Delay(FireInterval)로 구현. 누르고 있으면 반복 발사 |
| User Widget | 화면에 표시되는 UI 한 장. Create Widget → Add to Viewport로 화면에 붙임 |
| Is Variable | 위젯 안의 요소를 외부에서 접근/변경하려면 반드시 체크 |
개념 배운 것
개인적으로 찾아본 것
BP에서 Variable들 정
- BP에서 Variable 들 너무 정리 안돼서 방법 찾아보니 Category 설정하면 자동으로 폴더가 만들어짐
- 단점은 여러 개를 한 번에 선택이 안됨.. 그나마 drag and drop 이 돼서 다
- supfolder는 | 를 이용하면 됨, mainfoldername|supfoldername
현재 총알이 안 줄어듬
총 쐈을때 사물이 맞지 않았을 경우 총알 이 줄지 않는 버그가 있음
내 생각에 현재 BP 로직은 Break Hit Result 노드 -> Impact point 로나와서 Spawn Emitter at Location 노드로 나오기에 충돌을 해야 Emitter 가 sapwn 되면서 총알이 줄어드는 거 아닌가? 그래서 현재 충돌 안 하면 Emitter 가 안 나오고 총알도 안 줄어드는 거 같은데 내가 잘못 짠 건가? (충돌 안 한 경우의 예외 처리가 안되어있는 거 같음)

