본 캠프 TIL

26.04.23 TIL / C언어 3-1 ~ 4-1 / UE5 Day4

jh009 2026. 4. 23. 21:49

C언어 세션 4일차

3-1 : 들어가기 전에

소스코드를 정독하는 방법을 익히기

섣부른 암산은 폐사의 지름길

  • 프로그램의 시작점은 main() 함수. main() 함수의 첫 줄부터 읽음
  • 위에서 아래로, 좌에서 우로 읽음
  • 단위는 하나의 문. 명령어 단위로 읽음

★ 처음에는 답답하고 힘들겠지만, 정독 횟수가 누적되어야 정확한 속독이 가능 ★

 

[좋은습관] 조건문의 스코프 { } 속 명령어가 한 줄이어도 스코프 { } 는 꼭 적기

  • 중괄호를 생략하는 사람이 정말 많음
  • 초보자에겐 너무나도 안좋은 습관 
  • 무조건 적어서 명시적으로 표현하기
if (x < 10)
{
	printf("x < 10"); 
}

// if (x < 10) printf("x < 10"); worst.

3-2 : 단순 if문

조건문

단순 if문

if () 뒤에 ; 를 붙이면 잘림 

if (조건식)
{
	명령어1;
	명령어2;
	...
}

 

Ex030201) 단순 if문 [중요 샘플 코드]


3-3. if-else문

  • 그 밖에 모든 것 이라는 뜻
  • 간단한 if-else문은 삼항 연산자로 대체가 가능 (나중에 자연스럽게 배움)
  • If문 있어야 가능

Ex030301) if-else문 [중요 샘플 코드]


3-4. if-else if-else문

같은 1개

if (조건식1)
{
	명령어1; // 조건식1이 참이라면 명령어1부터 수행.
	...
}
else if (조건식2) // 조건식1이 거짓이라면 조건식2 검사.
{
	명령어2; // 조건식2가 참이라면 명령어2부터 수행.
	...
}
else
{
	명령어3; // 조건식1도 거짓이고, 조건식2도 거짓이라면 명령어3 수행.
	...
}

 

if-else if-else문 vs. 단순 if문

서로 다른 3가지

if문 조건식1이 참이든 거짓이든 if문 조건식2, 조건식3은 따로 실행됨

if (조건식1)
{
    명령어1
    ...
}
if (조건식2)
{
    명령어2
    ...
}
if (조건식3)
{
    명령어3
    ...
}

 

 

Ex030401) if-else if-else문 [중요 샘플 코드]


 

Ex030402) if ifelse문

// Main.c

#include <stdio.h>

int main(void)
{
	int Num = 102;

	if (Num < 105)
	{
		printf("Num < 105\n");
	}
	if (Num < 110)
	{
		printf("Num < 110");
	}
	else
	{
		printf("110 <= Num");
	}

	return 0;
}

 


3-5. 중첩 if문(Nested-if statement)

  • 조건식1 이 True 면 조건식1 안에 있는 조건식2 가 실행
  • 조건식1 이 False 면 조건식2 는 실행 X
if (조건식1)
{
    명령어1;
    ...

    if (조건식2)
    {
        명령어2;
        ...
    }
    else
    {
        명령어3;
        ...
    }
}

 

 

값의 범위를 조건식에 적을때 아래와 같이 적어보기.

  • 확실히 x가 10과 15 사이에 있음을 알 수 있음
  • 가독성과 빠른 이해를 위해 아래와 같이 적는게 좋음
// if (x >= 10 && x >= 15) worst
if (10 <= x && x <= 15) // best.

그럼 이 조건식의 역은 어떻게 적으면 될까요?

if (x < 10 || 15 < x)
X는 10보다 작"거나" 15보다 크다 >> || 를 쓰는거임

 

 

Ex030501) 중첩 if문 [중요 샘플 코드]


3-6. switch-case문

switch-case문은 if-else if-else문으로 치환 가능

switch-case문을 사용하는 이유? → 가독성 때문

  • 반대로 if-else if-else문은 switch-case문으로 치환 불가능할 때가 있음
  • 특히 if-else if-else문의 조건식이 범위를 다루는 경우 불가능
switch (Num)
{
case 값1:
	명령어1; // "Num == 값1"인 경우엔 명령어1
	...
	break;

case 값2:
	명령어2; // "Num == 값2"인 경우엔 명령어2
	...
	break;

default:
	명령어3; // "Num이 값1도 값2도 아닌 경우"(Num이 어떤 케이스에도 속하지 않는 경우)엔 명령어3
	...
	break;
}

Intentional-Fallthrough

 

/*Intentional-Fallthrough*/ → 나 일부러 브레이크 안썼다 → 안 적어도 실행은 되지만 남이 봤을 때 헷갈릴 수 있음

 

고의적으로 case 내부에 break 구문을 적지 않은 경우,

아래와 같이 코드를 작성한다면 Num이 값1과 같으면, case 값2 부분까지도 수행하게 됨

switch (Num)
{
case 값1:
    명령어1;
		/*Intentional-Fallthrough*/
case 값2:
    명령어2; // Num == 값1인 경우엔 명령어1과 명령어2 모두 실행
    ...
    break;

default:
    명령어3;
    ...
    break;    
}

 

 

만약 case 내에서 변수를 선언하려면 아래와 같이 중괄호를 쳐주면 됨

switch (Num)
{
case 값1:
    명령어1;
    ...      
    break;

case 값2:
    {
        int Var = 10;
        printf("%d", Var);
    }
    break;

default:
    작은 명령어3
    ...
    break;
}

 

Ex030601) switch-case문 [중요 샘플 코드]


 

4-1. while문

 

Ture 면 다시 위로 가서 명령어 실행, False 면 아래로 감

while (조건식)
{
	명령어1;
	...
}

 

 

Ex040101) while문 [중요 샘플 코드]


Ex040102) 누적합

문제. 5개의 int 자료형 값을 입력 받고 이 값들의 누적합을 구해봅시다. 그리고 출력해서 확인해봅시다.

 

문제를 쪼개서 이해해보기

  • 5개의 int 자료형
  • 값을 입력 받고
  • 이 값들의 누적합을 구해봅시다.
  • 그리고 출력해서 확인해봅시다.
//입력1
10
10
10
10
10

Ex040104) 최대값

  • 최대값을 얻고 싶다면 (max) 초기값을 엄청 작은 값을 대입해야 함
  • 반복문의 순회 변수로는 i를 자주 씀
  • iterate의 약자이기도 하지만, 이후에 배울 배열 + 반복문에서 index의 약자이기도 함
  • 되도록이면 i를 사용하는 것이 국룰
예습 4-2 ~ 6단원

 


Blueprint FPS 슈팅 게임 개발 4일차

 

적 AI 구현 & 체력 시스템

전 시간에 만들었던 Fire 함수 수정 → 맨 뒤에 있던 노드를 앞으로 수정 → 하늘을 보고 쏴도 총알이 깎이게 끔 설정 

 

AI 폴더 생성 후 Fab에서 몬스터 에셋 다운

 

  • Mesh 파일에서 스켈레탈메시, 스켈레톤, 피직스 에셋 확인
  • Animation폴더 들어가서 애니메이션 확인

 

  • 캡슐 높이, 반지름 설정 (캡슐 아래에 위치 시켜야 공중에 뜨지 않음 ★★★)  
  • mesh도 위치, 방향 잘 설정

 

Sphere Collision

 

Sphere Collision 생성 → Radius 600 (6m) 설정

ㄴ 플레이어가 개미 6m 안으로 들어가면 개미가 플레이어를 추격

 

Hidden in Game 체크 해제

ㄴ PIE로 게임시작해도 게임 안에서 개미의 탐지 범위를 볼 수 있음

 

 

블루프린트 에서 Add OnComponentBeginOverlap 빨리 꺼내는 방법

 

범위 안으로 들어갔을 때 Hello 가 뜨는지 테스트 (잘 뜸)

 

Linetrace 에서 Visibility Channel 을 사용해서 캡슐의 Visibility 설정을 Block으로 했었음

 

Collision Preset → Custom 으로 변경

Visibility → Block 으로 변경

 

 

개미 움직이게 하기 

1. 노드 설정

 

2. Navmesh 배치

P 누르면 네비게이션이 보임 (초록색)

Nav Mesh BoundVolume → AI가 이동할 수 있는 공간을 만들어줌 

 

Brush Settings XYZ 값을 맵 전체에 덮게 설정

 

XYZ 좌클릭 후 좌우로 움직이면 자동으로 줄어들고 늘어남 (편함)

 

 

Outliner → Recast → RecastNavmesh-Default 선택

 

Default

  • Cell size → 네비 영역의 크기를 얼마나 디테일하게 할지 
  • Cell Height → 네비 영역 높이 값 (계단 끊어진 것도 수정 가능)
  • Agent Max Step Height 35.0으로 설정 → AI들이 얼마나 높은 곳을 올라갈 수 있는지 정함

※ Cell size / Cell Height

천천히 낮추면서 확인할 것 / 절대로 낮은 값으로 설정하지 말 것. (팅겨버림) ★ ★ ★ ★ ★

 

전 후 비교

 

이 공간안에 캐릭터가 overlap 되면 개미가 폭발하게 만들기

 

Sphere 추가 

Radius값 적절하게 변경

 

Cascade 타입이라 Spawn Emitter at Location노드로 파티클??

Destroy Actor → 마지막에 개미 액터 삭제

 

소리 추가

  • Inner Radius 400: 이 거리 안에서는 최대 볼륨
  • Falloff Distance 1800: 이 거리 밖에서는 안 들림

 

BP_Ant

  • Apply Damage는 액터(Actor)에게 데미지를 입히는 Blueprint 함수
  • 대상 액터, 데미지 양, 가해자, 무기 정보를 전달하면 언리얼의 데미지 시스템이 자동으로 처리
  • 데미지 25로 설정

 

BP_FPSCharacter

 

텍스트가 뜨는지 확인 

 

AnyDamage 이벤트에서는 아래와 같이 현재 체력에서 들어온 데미지를 빼고 최대 체력이랑 나눠서 ProgressBar에 퍼센트를 설정

 

BP_Ant 랜덤으로 이동하는 기능

 

BP: 함수 vs 이벤트

함수 = 값을 돌려받을 수 있고 즉시 실행됨 (Delay 없음)

이벤트 = 반환값 없고 Delay 쓸 수 있음

 

Random 이동도 있고 Chase 도 있는데 둘 다 AI Move To 함수를 사용하다 보니 실행이 꼬일 수 있음

해결방안으로 IsChasing 변수 생성 → 추격하지 않을 때만 랜덤 이동

 

IsChasing 으로 분기를 나눠서 IsChasing 이 False 일 때만 랜덤하게 이동

 

캐릭터BP → Fire 함수에 추가

Break Hit Result 노드에서 Hit Actor를 BP_Ant로 변환 하고 개미에게 데미지 주는 로직을 작성

 

아래 그림처럼 연결해야 개미가 아닌 다른곳을 쏴도 총알 이펙트가 나옴

 

 

BP_Ant 

Explode로직에서 폭발 이펙트 및 사운드, 액터 삭제 로직을 함수로 변경

 


개미 애니메이션 만들기

 

AI 폴더 → ABP_Ant , BS_Ant 생성

 

 

BS_Ant 설정

 

ABP_Ant 에서 연결 →  캐릭터 ABP에서 그대로 노드를 복사해서 ABP_Ant 복붙

Set Speed 노드 우클릭 → Create variable ‘Speed’선택해서 변수

 

핀 연결

 

BP_Ant로 가서 Mesh → Detail → Animation Mode

 

Blueprint / ABP_Ant 체크

 

_C: 블루프린트 클래스 라는 뜻


Target을 추격하는 이벤트

 

BP_Ant 에 추가

 

Chase 로직에서도 길었던 로직을 StartChase이벤트로 교체

 

사진에는 As BP FPSCharacter - Target 에 연결 안되어있음. 연결하기

 

이제 개미가 공격을 받았을 때 추격 중이 아니라면 플레이어를 추격하도록 만들

 

Start Chase 이벤트도 실패 시 다시 랜덤하게 이동하게 만들기


픽업 아이템(힐 포션) & 레벨 배치

Blueprint 파일에 Items 파일 만들고 Actor 로 생성 

 

Sphere → 드래그앤 드랍 → DefaultSceneRoot → Make New Root 선택

 

Collision 을 루트로 설정하는 이유: 액터의 물리적인 ‘중심점’과 ‘기준’을 일치시켜 예기치 못한 물리 오류를 방지하기 위해서

 

크기 조절

Sphere → Radius 

Radius와 맞춰서 스태틱 메시 Location 까지

 

충돌 판정 설정

Sphere  → Hidden in Game 선택해제 (False)

 

다른 물체와 만났을 때, 통과시킬지 아니면 부딪힐지 설정

Sphere  → Collision → Collision Presets에 Custom → Visibility를 Block


BP_Item_Health 블루프린트

 

HealAmount 변수 → Float 타입 , 기본값 20.0

 

BP_Charcrter 에서 함수 추가

 

MIN노드: 체력이 100 일 때, 포션을 먹으면 120이 되는것을 방지