no image
C# - 박싱/언박싱과 박싱/언박싱&형변환 차이
✅ 박싱(Boxing) & 언박싱(Unboxing)🔸 박싱(Boxing)값 형식(Value Type) 데이터를 **참조 형식(Reference Type)**으로 변환하는 것값 타입(예: int, float)을 object 타입에 저장하면 박싱이 발생이 과정에서 값이 힙에 복사되고, 새로운 참조 객체로 할당됨int num = 10; object obj = num; // 박싱🔸 언박싱(Unboxing)박싱된 object를 다시 원래의 값 타입으로 꺼내오는 것힙에 있는 데이터를 스택에 복사하는 작업반드시 명시적 형변환이 필요하며, 잘못된 형변환 시 런타임 오류 발생int original = (int)obj; // 언박싱🔸 단점박싱/언박싱은 메모리 할당과 복사 비용이 발생 → 성능 저하특히 루프, 게임 로..
2025.07.01
C#
no image
C# Unity - 가비지 컬렉터(GC) 자동실행기준
✅ 가비지 컬렉터(GC)의 역할이란?더 이상 사용되지 않는 힙의 메모리를 자동으로 찾아서 정리해주는 시스템즉,메모리 누수 방지수동으로 메모리 해제하지 않아도 됨 (delete, free 필요 없음)✅ GC의 동작 기준 (언제 실행되나?)GC는 명확한 트리거 조건이 있어. 하지만 언제 실행될지 정확히 예측하긴 어려워.📌 주요 트리거 조건:힙에 여유 공간이 부족할 때새 객체를 new 하려는데 힙에 공간이 부족하면 → GC 실행너무 많은 객체가 생성되었을 때특정 임계치 이상 객체가 쌓이면 → 자동 실행시간이 일정 이상 지났을 때 (백그라운드 GC).NET 런타임이 비활성 시간에 GC를 실행하는 경우GC.Collect()를 명시적으로 호출했을 때가능하긴 하지만, 직접 호출은 성능상 좋지 않아서 권장하지 않음✅..
2025.07.01
C#
no image
TIL - 내일배움캠프 1일차 TIL [OT + 새로운 팀 + 팀 프로젝트(카드 뒤집기 게임)](25.06.30)
1. 오늘 하루 계획오전09:00 ~ 12:00 : OT12:00 ~ 13:00 : 12조 회의오늘 계획 (Task)[x] 팀원들 각자 역할 정하기[x] 필수 기능 기획 작성[x] 이미지 올리기오후13:00 ~ 14:00 : 점심시간14:00 ~ 15:30 : Git 사용법 특강15:30 ~ 18:00 : GitHub Desktop 실습 및 게임 프로젝트 협업[x] Card.cs, Board.cs 스크립트 구현[x] 팀원 GitHub 오류 수정[x] Unity 기초 설명 지원저녁18:00 ~ 19:00 : 저녁 식사19:00 ~ 20:00 : 팀 회의20:00 ~ 20:30 : TIL 작성20:30 ~ 21:00 : 팀원 회고 진행2. 오늘 학습 키워드Git / GitHub / GitHub Desktop..
2025.06.30
no image
사전캠프 7일차(주말) [게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발 5 주차 완강]
1. 오늘 학습 키워드5주차StartScene 구성 + 타이틀 UI 제작 (Text, Button, Image, 애니메이션)Splash 이미지 설정 (Project Settings > Player > Splash Image)카드 뒤집기 사운드, 정답 사운드 삽입 (AudioSource.PlayOneShot)배경음악 지속 재생 → AudioManager 싱글톤 + DontDestroyOnLoad()Android 빌드 설정 (IL2CPP, ARM64, Keystore, apk 생성)iOS 배포 개요 (expo build:ios, 트랜스포터, App Store Connect)Unity Ads 연동: AdInitialize.cs, RewardedButton.cs, 광고 보상 처리무료 에셋 스토어 탐색 및 사용법..
2025.06.30
no image
사전캠프 5일차 [게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발 4 주차 완강]
1. 오늘 학습 키워드시간 측정 + UI 표시 (Time.deltaTime, "N2" 포맷)카드 프리팹 반복 생성 + 격자 배치 (Instantiate, i % 4, i / 4)카드 이미지 랜덤 섞기 (OrderBy, Resources.Load)카드 클릭 시 뒤집기 애니메이션 (Animator.SetBool("isOpen", true))카드 클릭 → GameManager에 카드 등록 → 두 장 비교일치 시: DestroyCard() 호출 → 0.5초 후 카드 제거불일치 시: CloseCard() 호출 → 0.5초 후 다시 뒤집기남은 카드 수 cardCount로 추적 → 0되면 게임 종료 + Time.timeScale = 0Retry 버튼으로 재시작 (SceneManager.LoadScene, Time.t..
2025.06.27
no image
사전캠프 4일차 [게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발1,2,3 주차 완강]
1. 오늘 학습 키워드1주차캐릭터 이동 + flipX 반전마우스 클릭 시 방향 전환빗방울 프리팹 랜덤 생성 (Instantiate + Random.Range)충돌 처리 (OnCollisionEnter2D) → 점수 증가 / 오브젝트 제거GameManager 싱글톤 + 점수 관리 (AddScore)UI 텍스트 실시간 갱신 (Text.text)InvokeRepeating 사용해 빗방울 반복 생성시간 제한 + 게임 오버 패널 (Time.deltaTime, SetActive)Retry 버튼으로 씬 재시작 (SceneManager.LoadScene)2주차마우스 따라오게 하기 (Shield.cs → Camera.ScreenToWorldPoint)장애물 랜덤 생성 + 프리팹화 (Instantiate, Random.R..
2025.06.26
no image
사전캠프 3일차 [게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발], 오목 게임 팀플 기획(개인 작성)
1. 오늘 학습 키워드[게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발] 강의 학습, 오목 게임 팀플 기획2. 오늘 학습 한 내용을 나만의 언어로 정리하기void Start(){ Application.targetFrameRate = 60;}보통 Start() 안에 넣어서 게임 시작 시 프레임을 설정한다.프레임을 60프레임으로 제한함.3. 학습하며 겪었던 문제점 & 에러문제&에러에 대한 정의내가 한 시도해결 방법새롭게 알게 된 점이 문제&에러를 다시 만나게 되었다면4. 내일 학습 할 것게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발 1주차 이상5. 메모1. 오목의 기본 개념 정리(공통 작업)(개인 작성)[Step 1] 오목이란?오목이란?게임의 장르 : 보드 게임, 전략 게임기본적인 목표: ..
2025.06.26
no image
사전캠프 2일차 [기초 문법 복습 + 달리기반 Lv1, Lv2, Lv3]
1. 오늘 학습 키워드기초 문법 복습, 달리기반 Lv1, Lv2 풀기2. 오늘 학습 한 내용을 나만의 언어로 정리하기달리기반 Lv1, Lv2, Lv3using System;using System.Collections.Generic;using System.Linq;using System.Text;//------------------------------------------------------------------------------------------------------------------------////기본 문법 복습//팀원에게 스위치 케이스문 질문을 받았는데 나는 그냥 일반적인 숫자나 변수값이 들어가도 되는 줄 알았다//하지만 알아보니 리터럴 상수값이 들어간다고 한다 처음에는 리터럴 상수가..
2025.06.24
반응형

✅ 박싱(Boxing) & 언박싱(Unboxing)

🔸 박싱(Boxing)

  • 값 형식(Value Type) 데이터를 **참조 형식(Reference Type)**으로 변환하는 것
  • 값 타입(예: int, float)을 object 타입에 저장하면 박싱이 발생
  • 이 과정에서 값이 힙에 복사되고, 새로운 참조 객체로 할당
int num = 10; object obj = num; // 박싱

🔸 언박싱(Unboxing)

  • 박싱된 object를 다시 원래의 값 타입으로 꺼내오는 것
  • 힙에 있는 데이터를 스택에 복사하는 작업
  • 반드시 명시적 형변환이 필요하며, 잘못된 형변환 시 런타임 오류 발생
int original = (int)obj; // 언박싱

🔸 단점

  • 박싱/언박싱은 메모리 할당과 복사 비용이 발생 → 성능 저하
  • 특히 루프, 게임 로직에서 자주 발생하면 GC 부담으로 이어짐

 

그리고 궁금한게 생겼다 그럼 형변환과 무엇이 차이날까? 싶어서 GPT한테 물어보았다.

 

✅ 형변환(casting) vs 박싱/언박싱의 차이

🔹 형변환(casting)

  • 같은 형식 계열 내에서 타입만 바꾸는 것
  • 메모리 위치나 구조는 그대로
 
float f = 3.14f; int i = (int)f; // 형변환 (float → int)

스택 내에서 값 자체가 바뀌는 것이지, 힙에 복사되는 게 아님

 

✅ 꼭 object로 해야 박싱/언박싱이 일어날까?

🔥 박싱은 object뿐만 아니라 인터페이스로도 발생해!

예시:

interface IPrintable
{
    void Print();
}

struct MyStruct : IPrintable
{
    public void Print() { Console.WriteLine("Hello"); }
}

IPrintable p = new MyStruct(); // ✅ 박싱 발생
  • MyStruct는 값 타입이지만, IPrintable은 참조 타입이기 때문에 박싱이 발생함

 

일단 박싱/언박싱은 확실히 힙까지 사용되지만 형변환은 스택 내에서만 일어나는 일이라는걸 알게됐다!!

 

회사 면접볼때 박싱과 언박싱에 대해서 질문이 나왔던 적이 있다. 사실..여태까지는 잘 생각 안하고 사용했다..기초지식이 확실히 중요한거같다 ㅠㅜ 열심히 공부하자..이제 질문나오면 확실히 대답할 수 있다!!!

 

반응형

'C#' 카테고리의 다른 글

C# - .NET Runtime  (1) 2025.07.01
C# - 캡슐화  (1) 2025.07.01
C# Unity - 가비지 컬렉터(GC) 자동실행기준  (1) 2025.07.01
C# 주사위게임  (0) 2023.03.12
C# 칸 이동 게임  (0) 2023.03.12
반응형

✅ 가비지 컬렉터(GC)의 역할이란?

더 이상 사용되지 않는 힙의 메모리를 자동으로 찾아서 정리해주는 시스템

즉,

  • 메모리 누수 방지
  • 수동으로 메모리 해제하지 않아도 됨 (delete, free 필요 없음)

✅ GC의 동작 기준 (언제 실행되나?)

GC는 명확한 트리거 조건이 있어. 하지만 언제 실행될지 정확히 예측하긴 어려워.

📌 주요 트리거 조건:

  1. 힙에 여유 공간이 부족할 때
    • 새 객체를 new 하려는데 힙에 공간이 부족하면 → GC 실행
  2. 너무 많은 객체가 생성되었을 때
    • 특정 임계치 이상 객체가 쌓이면 → 자동 실행
  3. 시간이 일정 이상 지났을 때 (백그라운드 GC)
    • .NET 런타임이 비활성 시간에 GC를 실행하는 경우
  4. GC.Collect()를 명시적으로 호출했을 때
    • 가능하긴 하지만, 직접 호출은 성능상 좋지 않아서 권장하지 않음

✅ GC는 어떤 기준으로 “삭제할 대상을” 고르나?

GC는 **루트(Root)**에서부터 시작해서, 더 이상 접근할 수 없는 객체를 "가비지"라고 판단해.

🔸 Root란?

  • 스택의 지역 변수
  • 전역 변수 (static)
  • CPU 레지스터에 참조된 객체 등

👉 이 루트에서 참조되고 있지 않은 객체는 **"아무도 쓰고 있지 않다"**고 간주하고 수거함.


✅ GC는 세대를 나눠서 관리한다 (Generational GC)

GC는 성능 최적화를 위해 **객체의 생존 시간을 기준으로 세대(Generation)**를 나눠서 관리해.

세대설명
Gen 0 막 생성된 객체. 대부분 여기서 수거됨 (소멸률 높음)
Gen 1 Gen 0을 넘긴 객체들. 조금 더 오래된 객체
Gen 2 가장 오래 살아남은 객체. 수거 대상에서 가장 오래 남아 있음
 

🔥 대부분의 객체는 Gen 0에서 생기자마자 사라짐
→ 그래서 GC는 Gen 0만 자주 돌리고, Gen 2는 최소한으로만 돌리는 것이 성능에 좋아


✅ 예시 시나리오

void CreateGarbage() { for (int i = 0; i < 100000; i++) { var temp = new object(); // 힙에 생성됨 } }
  • 위 코드를 실행하면 object들이 계속 힙에 생성됨
  • 일정 수 이상이 되면 → GC가 자동으로 실행되어 참조되지 않는 object들을 회수함

 

흠...근데 주요 트리거 조건에서 궁금한게 생겼다.

1. 힙에 여유 공간이 부족한 기준

2. 너무 많은 객체가 생성된다는 기준이 어느정도인지

3. 시간이 일정 이상 지났을때의 기준

GPT에게 물어보니 친절하게 설명해줬다.

✅ 1. 힙에 여유 공간이 부족할 때 → GC 실행

🔸 그럼 “여유 공간 부족”의 기준은 뭘까?

정해진 “절대 크기”는 없음.
대신 세대(Generation)별 할당량과 동적 상황에 따라 달라짐.

📌 핵심 개념: Allocation Budget (할당 예산)

  • GC는 Gen 0/1/2 각각에 대해 힙 할당 예산을 갖고 있음
  • 이 예산을 초과하면 → GC가 실행됨
  • 예산은 GC가 이전에 수거한 양, 메모리 압력, CPU 상황 등을 고려해 동적으로 조절됨

📌 예시:

  • Gen 0 힙이 100KB 할당 예산을 갖고 있고, 지금까지 95KB 사용됨
  • 그런데 new로 10KB 객체를 만들려고 하면 → 예산 초과
    → ✅ GC가 Gen 0에서 먼저 동작

💡 즉, **"GC는 얼마나 썼냐"보다는 “할당하려는 크기 + 예산 초과 여부”**로 판단한다는 점이 중요!


✅ 2. 너무 많은 객체가 생성되었을 때 → GC 실행

🔸 기준은?

역시 정해진 개수 기준은 없음.
GC는 “많이 생성되었다”는 양적 기준보다, “할당 속도와 생존률”을 중요하게 본다.

📌 GC는 객체 생존률을 보고 판단

  • GC는 "이번에 생성된 객체들이 얼마나 빨리 죽는가?"를 본다
  • 생성만 많이 되고 죽지 않으면, 세대(Gen) 올라가며 압력 증가
  • 그럼 GC는 더 자주 실행됨

📌 예시 상황:

  • for 루프에서 수만 개의 new 연산이 빠르게 실행됨
  • 대부분은 Gen 0에서 할당되고, 금방 참조가 끊어짐
    → GC는 빠르게 Gen 0만 자주 실행

✅ 3. 시간이 일정 이상 지났을 때 (백그라운드 GC)

🔸 기준은?

⏱️ 이건 명확히 시간 초 단위로 정해져 있는 게 아님
대신 GC가 백그라운드 스레드에서 “유휴 시간”을 감지할 때 실행됨

📌 백그라운드 GC가 동작하는 상황:

  • 앱이 입력을 기다리거나, 유저가 아무것도 하지 않을 때
  • GC는 작업이 적은 타이밍에 자동 실행 → 앱이 바쁠 땐 일부러 안 함

✅ 보충 정리: GC의 실행 타이밍은 “예측 불가능하지만, 패턴은 있다”

트리거 상황설명
힙 공간 부족 할당 예산 초과 시
객체 생성량 급증 단기간에 많은 new → GC 주기 짧아짐
유휴 시간 감지 백그라운드에서 앱 부하 없을 때
명시적 호출 GC.Collect() → 강제 실행 (권장 ❌)
 

✅ 그럼 우리가 할 수 있는 건?

  • GC 타이밍을 완전히 제어할 수는 없지만,
  • 다음과 같은 습관을 통해 예측 가능하고 최소화된 GC 동작을 만들 수 있어:

🔹 GC 최적화 팁 (특히 Unity 기준)

  • Update()에서 new 피하기
  • List.Clear()로 컬렉션 재사용
  • Object Pooling 활용
  • string 연결 시 StringBuilder 사용
  • 큰 객체는 필요할 때만 생성 & 사용 후 null 처리

✅ 요약

질문정리
1. 힙 공간 부족 기준은? 할당 예산 초과가 기준 (세대별 동적 조절)
2. “많은 객체 생성” 기준은? 객체 생성 속도 + 생존률을 종합적으로 판단
3. “시간이 지나면 실행” 기준은? 앱이 유휴 상태일 때 백그라운드에서 감지하여 실행

 

그렇다고 한다! 1번은 정해진 절대적인 크기는 없다고하니 음.. 대신 세대별 할당량과 동적 상황에 달라지고 2번은 객체의 생존률을 보고 판단하고 3번은 유휴 시간을 감지하면 한다니

컴퓨터마다 다 성능도 다르고 코딩할때도 다 설정값이 다르니 계산된 값에 따라 컴퓨터에 따라 달라지지 않을까 싶다. 웬만하면 비슷할 지도?

 

예전에 회사에서 면접을 볼떄 가비지컬렉터가 작동할떄 언제 자동으로 작동되냐? 라고 질문을 받은적이 있었다. 근데 나도 생각해보니 자동으로 처리해주는것만 알았지 어떻게 자동으로 처리해주는지에 대한 내용은 잘 몰랐다. 스파르타 임예찬 튜터님께 물어보니 잘 설명해주셨고 나머지 더 자세한 부분은 GPT한테 물어보니 잘 대답해줬다. 궁금내용 해결!

반응형

'C#' 카테고리의 다른 글

C# - 캡슐화  (1) 2025.07.01
C# - 박싱/언박싱과 박싱/언박싱&형변환 차이  (0) 2025.07.01
C# 주사위게임  (0) 2023.03.12
C# 칸 이동 게임  (0) 2023.03.12
C# 구구단  (0) 2023.03.12
반응형

1. 오늘 하루 계획

  • 오전
    • 09:00 ~ 12:00 : OT
    • 12:00 ~ 13:00 : 12조 회의
      • 오늘 계획 (Task)
        • [x] 팀원들 각자 역할 정하기
        • [x] 필수 기능 기획 작성
        • [x] 이미지 올리기
  • 오후
    • 13:00 ~ 14:00 : 점심시간
    • 14:00 ~ 15:30 : Git 사용법 특강
    • 15:30 ~ 18:00 : GitHub Desktop 실습 및 게임 프로젝트 협업
      • [x] Card.cs, Board.cs 스크립트 구현
      • [x] 팀원 GitHub 오류 수정
      • [x] Unity 기초 설명 지원
  • 저녁
    • 18:00 ~ 19:00 : 저녁 식사
    • 19:00 ~ 20:00 : 팀 회의
    • 20:00 ~ 20:30 : TIL 작성
    • 20:30 ~ 21:00 : 팀원 회고 진행

2. 오늘 학습 키워드

  • Git / GitHub / GitHub Desktop
  • Unity Sprite 정렬
  • 협업 커밋 / 푸시 / 풀
  • SpriteRenderer 스케일 조정

3. 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 Git의 기본 개념부터 GitHub Desktop을 활용한 실습까지 경험하며, 협업 환경을 구축해보았다.

Git은 협업 시 필수인 버전 관리 시스템(VCS)이며, GitHub를 통해 원격 저장소에 코드를 공유하고 이력을 관리할 수 있다.

Desktop 앱을 사용해 Commit → Push → Pull 흐름을 실습하고, 실제 Unity 프로젝트에서 함께 작업했다.

Unity에서는 팀원들의 이미지 크기와 비율이 제각각인 상황에서 SpriteRenderer를 이용해 이미지 스케일을 계산하여 512x512 또는 100x100 픽셀 기준으로 통일하는 코드도 구현했다.

그 과정에서 sprite.bounds.size를 이용해 원본 크기를 구하고, transform.localScale을 조정하여 출력 크기를 정규화하는 법을 배웠다.

또한 팀원들과 협업하며 발생한 GitHub 오류나 Unity 이해 부족을 도와주며 내 지식을 정리하고, 팀워크도 함께 향상시킬 수 있는 좋은 기회였다.


4. 학습하며 겪었던 문제점 & 에러

🔹 문제&에러에 대한 정의

  • 팀원 이미지가 각기 다른 비율/크기로 들어와 카드 UI가 뒤틀림
  • GitHub Desktop 사용 중 Push/Pull 순서 혼동 및 충돌 우려
  • 팀원 GitHub 연동 시 커밋이 안 되거나 이미지 파일 누락

🔹 내가 한 시도

  • SpriteRenderer.bounds.size 값을 이용한 스케일 계산
  • localScale을 스크립트로 조정
  • Git 흐름 직접 시연하며 팀원들과 같이 실습
  • .gitignore 설정 확인 및 정리

🔹 해결 방법

  • 스크립트 내에서 크기 고정 기준값을 정하고 (100x100) 이미지 스케일을 맞춤
  • GitHub 커밋 순서: Pull → Commit → Push 순서 강조
  • 팀원에게 GitHub Desktop 사용법 설명 및 충돌 방지 팁 공유

🔹 새롭게 알게 된 점

  • SpriteRenderer는 실제 유닛 크기를 기준으로 스케일을 정할 수 있다
  • Unity는 이미지 크기보다 스케일과 Pixels Per Unit이 더 중요하다
  • GitHub Desktop은 시각적이고 간편하지만, 충돌 주의가 필요하다
  • 협업 중 작은 도움이라도 반복되면 팀 전체 이해도 향상에 크게 기여할 수 있다

🔹 이 문제&에러를 다시 만나게 된다면

  • 이미지 업로드 전 편집을 통해 사이즈 정규화 또는 자동화 도구 활용
  • Git 브랜치 전략 도입해서 충돌 가능성 최소화
  • 실습 중 생긴 실수를 문서화해서 팀원들과 공유하고 반복 방지

5. 내일 학습 할 것

  • Unity 내 카드 배치 및 정렬 개선
  • 팀 프로젝트 기본 기능 구현 시작 (카드 매칭 로직, UI 개선 등)
  • 팀원 간 역할 명확히 나누고 Git 활용 능력 향상시키기

6. 메모

이재은 팀장 ENFJ
김나경 팀원 ISTP
박상현 팀원  
진진원 팀원 INFJ
홍기정 팀원 INFJ

Git 특강1 (2시~3시30분)

  • Git이란?
    • VCS
    • V : Version
    • C : Control
    • S : System
    • 현상관리 시스템
  • VCS 를 사용하는 이유
    • 협업(공유)
  • 깃허브 사용법
    • 깃허브 안에서 Setting - Collaborators(팀원 초대)
  • 등등 깃 사용법 강의
    • commit -
    • Undo - 로컬에만 있는 (뒤로)
    • Amend - 제목만 바꾸는 것
    • Revert - 원격 저장소에 올라간거를 수정
    • Push - 올리기
    • Pull - 내려받기
    • CheckOut - 한 시점으로 다시 시작 (History)
    • Cherry_Pick -
  • 유니티 프로젝트 올리는 법
    • Git Ignore - Unity 해줘야함
  • 요약
    • git은 VCS 원격 공유 저장소

 

반응형
반응형

1. 오늘 학습 키워드

  • 5주차
    • StartScene 구성 + 타이틀 UI 제작 (Text, Button, Image, 애니메이션)
    • Splash 이미지 설정 (Project Settings > Player > Splash Image)
    • 카드 뒤집기 사운드, 정답 사운드 삽입 (AudioSource.PlayOneShot)
    • 배경음악 지속 재생 → AudioManager 싱글톤 + DontDestroyOnLoad()
    • Android 빌드 설정 (IL2CPP, ARM64, Keystore, apk 생성)
    • iOS 배포 개요 (expo build:ios, 트랜스포터, App Store Connect)
    • Unity Ads 연동: AdInitialize.cs, RewardedButton.cs, 광고 보상 처리
    • 무료 에셋 스토어 탐색 및 사용법 (OpenGameArt.org, Unity Asset Store)

🧠 2. 오늘 새롭게 알게 된 내용

✅ Unity 광고 시스템은 버전에 따라 다르게 동작함

  • Unity 2023.3.36f1에서는 Advertisement (Legacy) 패키지가 사라짐
  • 2023.3.17f1 이하 버전에서는 기존 방식의 광고 삽입 가능
  • 광고 삽입을 원할 경우, 버전에 맞는 SDK 방식 사용해야 함

✅ Unity Ads SDK 초기화 방법

  • Advertisement.Initialize(gameId, testMode, listener) 함수를 사용해 초기화
  • IUnityAdsInitializationListener 인터페이스를 구현해 성공/실패 콜백 처리
  • 에디터, iOS, Android 별로 Game ID 분기 처리 필요 (#if UNITY_IOS 등)
  • testMode = true일 경우 테스트 광고가 재생됨 (실제 출시 전 반드시 false로 설정)

✅ 광고 초기화 흐름

  1. 게임 시작 시 AdsInitializer 스크립트 실행
  2. 지원되는 플랫폼인지 확인 후 초기화
  3. 초기화 성공 시 광고 재생 가능 상태

🧪 3. 학습하며 겪은 문제 & 해결 과정

항목 내용

정의 최신 Unity 버전에서 Advertisement 패키지가 사라져 광고 삽입 불가
시도 Unity 2023.3.36f1 → 광고 코드 작성 중 오류
해결 Unity 2023.3.17f1로 다운그레이드 후 패키지 다시 등장
새로 알게 된 점 Advertisement (Legacy)는 더 이상 최신 Unity에서 기본 제공되지 않음

🔮 4. 내일 학습할 것

  • 보상형 광고(Rewarded Ad) 삽입 방식 학습
  • 광고 로드 상태 확인 및 사용자에게 광고 보여주는 방법 정리
  • 광고 로직과 게임 흐름의 자연스러운 연결

✏️ 5. 메모

  • 광고를 넣을 때는 테스트 모드 여부 꼭 확인!
  • Game ID는 Unity Dashboard에서 가져오는 실제 값으로 교체해야 정상 작동
  • Advertisement.IsReady()를 꼭 체크한 뒤 광고 실행할 것
반응형
반응형

1. 오늘 학습 키워드

  • 시간 측정 + UI 표시 (Time.deltaTime, "N2" 포맷)
  • 카드 프리팹 반복 생성 + 격자 배치 (Instantiate, i % 4, i / 4)
  • 카드 이미지 랜덤 섞기 (OrderBy, Resources.Load<Sprite>)
  • 카드 클릭 시 뒤집기 애니메이션 (Animator.SetBool("isOpen", true))
  • 카드 클릭 → GameManager에 카드 등록 → 두 장 비교
  • 일치 시: DestroyCard() 호출 → 0.5초 후 카드 제거
  • 불일치 시: CloseCard() 호출 → 0.5초 후 다시 뒤집기
  • 남은 카드 수 cardCount로 추적 → 0되면 게임 종료 + Time.timeScale = 0
  • Retry 버튼으로 재시작 (SceneManager.LoadScene, Time.timeScale = 1)

2. 오늘 학습 한 내용을 나만의 언어로 정리하기

1. Random 클래스 충돌 오류 (System.Random vs UnityEngine.Random)

📌 문제 코드

arr.OrderBy(x => Random.Range(0f, 7f)).ToArray();

⚠️ 오류 메시지

CS0104: 'Random' is an ambiguous reference between 'UnityEngine.Random' and 'System.Random'

🎯 원인

  • Random이라는 클래스가 System과 UnityEngine에 모두 존재해서 충돌 발생
  • 둘 다 using 되어 있는 경우 컴파일러가 어떤 Random인지 몰라서 오류 발생

✅ 해결 방법

  • 유니티에서 사용하는 Random.Range()를 명확히 지정:
rr.OrderBy(x => UnityEngine.Random.Range(0f, 7f)).ToArray();

2. Resources.Load<Sprite>()로 이미지 동적 로드

📌 새롭게 알게 된 코드

Resources.Load<Sprite>($"rtan{idx}");

✅ 동작 설명

  • Assets/Resources/ 폴더에 있는 "rtan{idx}" 이름의 스프라이트를 런타임에 불러옴
  • 문자열 보간을 사용하여 동적으로 파일명을 지정

✅ 주의할 점

  • 파일 경로에서 확장자 (.png)는 생략
  • 에셋은 반드시 Resources 폴더 하위에 있어야 함
  • Resources.Load는 자주 쓰면 퍼포먼스 저하 → 간단한 경우에만 사용 권장

4. 내일 학습 할 것

유니티 게임 개발 5주차


5. 메모


시간이 밀려서 그런지 5주차까지 완강하지 못했다..ㅠㅜ

주말에 나머지 5주차까지 완강해야지!

반응형
반응형

1. 오늘 학습 키워드

  • 1주차
    • 캐릭터 이동 + flipX 반전
    • 마우스 클릭 시 방향 전환
    • 빗방울 프리팹 랜덤 생성 (Instantiate + Random.Range)
    • 충돌 처리 (OnCollisionEnter2D) → 점수 증가 / 오브젝트 제거
    • GameManager 싱글톤 + 점수 관리 (AddScore)
    • UI 텍스트 실시간 갱신 (Text.text)
    • InvokeRepeating 사용해 빗방울 반복 생성
    • 시간 제한 + 게임 오버 패널 (Time.deltaTime, SetActive)
    • Retry 버튼으로 씬 재시작 (SceneManager.LoadScene)
  • 2주차
    • 마우스 따라오게 하기 (Shield.cs → Camera.ScreenToWorldPoint)
    • 장애물 랜덤 생성 + 프리팹화 (Instantiate, Random.Range, InvokeRepeating)
    • 시간 측정 및 표시 (Time.deltaTime, Text.text)
    • 풍선과 충돌 시 게임 종료 처리 (OnCollisionEnter2D, GameOver())
    • GameManager 싱글톤 처리 (static Instance, Awake)
    • 게임 오버 시 애니메이션 전환 (Animator.SetBool("isDie", true))
    • 0.5초 지연 후 시간 멈춤 처리 (Invoke("TimeStop", 0.5f))
    • 최고 점수 저장 및 불러오기 (PlayerPrefs.SetFloat, GetFloat, HasKey)
    • Retry 버튼으로 게임 재시작 (SceneManager.LoadScene)
    • UI 텍스트로 현재/최고 점수 표시
  • 3주차
    • StartScene → MainScene 씬 전환 (SceneManager.LoadScene)
    • 강아지가 일정 시간마다 밥 발사 (InvokeRepeating, Instantiate)
    • 밥이 일정 y값 넘으면 제거 (Destroy)
    • 마우스 따라 강아지 이동 + 이동 범위 제한
    • 고양이 프리팹 중력 이동 + Random.Range로 위치 지정
    • 고양이 HP 바 구현 (Transform.localScale)
    • 밥과 충돌 시 HP 증가 + 배부르면 이미지 전환 (SetActive)
    • 에너지 꽉 찬 고양이 옆으로 이동 후 제거 (Destroy(gameObject, 3.0f))
    • 지면 도달 시 게임 종료 (GameManager.Instance.GameOver())
    • 레벨 시스템 구현 (5마리마다 1레벨 증가)
    • 레벨에 따라 고양이 등장 확률 변경 + FatCat 등장
    • FatCat은 더 느리고 HP 더 많음
    • Retry 버튼 + Time.timeScale = 1.0f 재설정

2. 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 유니티 게임개발 1,2,3 주차 강의를 듣고 개발을 하였다. 딱히 어려운 점은 없었고 자주 사용하지 않던 부분들이 조금 있었다. 유니티 기능이 워낙 많아서 하나씩 천천히 잘 배워보자.


3. 학습하며 겪었던 문제점 & 에러

✅ 오늘 새롭게 배운 개념 요약

1. 🖼️ UI Image에 Shadow 컴포넌트 적용

  • Image 컴포넌트에도 Shadow(효과)를 추가할 수 있음
  • UI에 그림자 효과를 줘서 더 입체감 있는 디자인 가능
  • 추가 방법: Add Component > Effects > Shadow
  • Effect Color, Effect Distance, Use Graphic Alpha 등 속성 조절 가능

2. 📦 싱글톤(Singleton) 패턴

  • GameManager 같은 오브젝트를 전역에서 접근 가능하게 만드는 방식
  • 기본 구조:
csharp
복사편집
public static GameManager Instance;

void Awake()
{
    Instance = this;
}

  • 다른 스크립트에서 GameManager.Instance로 바로 접근 가능

3. 🎨 카메라 배경색 변경

  • Camera.main.backgroundColor = Color.blue; 처럼 코드로 설정 가능
  • 또는 에디터에서 Main Camera 선택 → Inspector > Background에서 직접 변경
  • Clear Flags가 Skybox일 경우 Solid Color로 바꿔야 색상이 보임

4. 💾 PlayerPrefs로 점수 저장

  • 앱을 껐다 켜도 데이터 유지 가능
  • 주요 함수:
PlayerPrefs.SetFloat("bestScore", 값); // 저장
PlayerPrefs.GetFloat("bestScore");     // 불러오기
PlayerPrefs.HasKey("bestScore");       // 존재 여부 확인
  • 최고 점수, 설정값, 튜토리얼 완료 여부 등에 자주 사용됨

4. 내일 학습 할 것

유니티 게임 개발 4,5주차 완강


 

반응형
반응형

1. 오늘 학습 키워드

[게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발] 강의 학습, 오목 게임 팀플 기획


2. 오늘 학습 한 내용을 나만의 언어로 정리하기

void Start()
{
    Application.targetFrameRate = 60;
}
  • 보통 Start() 안에 넣어서 게임 시작 시 프레임을 설정한다.
  • 프레임을 60프레임으로 제한함.

3. 학습하며 겪었던 문제점 & 에러

  • 문제&에러에 대한 정의
  • 내가 한 시도
  • 해결 방법
  • 새롭게 알게 된 점
  • 이 문제&에러를 다시 만나게 되었다면

4. 내일 학습 할 것

게임 개발이 처음이어도 쉽게 배우는 모바일 게임 개발 1주차 이상


5. 메모


1. 오목의 기본 개념 정리(공통 작업)(개인 작성)

[Step 1] 오목이란?

  1. 오목이란?
    • 게임의 장르 : 보드 게임, 전략 게임
    • 기본적인 목표: 자신의 돌을 가로, 세로, 대각선으로 연속 5개로 놓아 먼저 승리하는 것.
  2. 게임에 사용되는 요소
    • 15x15 또는 19x19 크기의 바둑판
    • 흑돌과 백돌 (두 명의 플레이어가 번갈아 가며 돌을 둠)
    • 선공은 일반적으로 흑돌
  3. 기본적인 진행 방식
    • 번갈아가며 한 수씩 돌을 놓음
    • 한 번 둔 돌은 다시 움직일 수 없음
    • 상대보다 먼저 5개의 돌을 연속으로 배열하면 승리
  4. 승리 조건 & 패배 조건
    • 승리 조건 : 같은 색의 돌을 5개 연속으로 두면 승리
    • 패배 조건 : 상대가 먼저 5개를 잇거나 금수 규칙 위반 시 패배

2. 게임의 룰과 상세 규칙 계획

[Step 2] 오목의 기본 규칙 정리

  1. 기본 규칙
    • 두 명의 플레이어가 번갈아 돌을 둠
    • 돌을 교차점에 둠 (격자 위)
    • 돌은 한 번 놓으면 이동 불가
  2. 승리 조건과 게임 종료 방식
    • 같은 색 돌을 가로/세로/대각선으로 5개 연속 놓으면 승리
    • 5개 이상이어도 무효가 아닌 일반 오목에서는 승리로 인정 (백 기준, 흑은 X)
  3. 특수 규칙 적용 여부
    • 금수 룰 적용 여부 (흑만 적용)
      • 33 금수: 한 수로 열린 세목(3개 연결) 2개 이상 만들면 무효
      • 44 금수: 한 수로 열린 네목(4개 연결) 2개 이상 만들면 무효
      • 6목 금지: 6개 이상 연결하면 무효 (5개까지만 허용)

3. 팀별 새로운 게임 요소 추가하기

[Step 3] 기존 오목에서 차별화된 요소 기획

  1. 기존 오목과 차별점을 만들 요소를 정의하세요.
    • 스킬 시스템 도입 : 게임 중 특정 횟수에 한해 사용할 수 있는 스킬
      • 상대 돌 하나 제거
      • 본인 돌 2개 연속 놓기
      • 상대 시간 절반으로 줄이기
  2. 게임의 핵심 재미를 한 문장으로 정의하세요.
    • “순간 판단력과 전략, 스킬 활용으로 반전을 만들어내는 오목”
  3. 추가적인 게임 규칙이 필요한가요?
    • 스킬은 게임당 3회 사용 가능
    • 스킬 종류는 게임 시작 전 선택

4. 최종 기획 문서 정리 & 팀 발표

[Step 4] 기획 문서 작성

🔷 게임 개요

  • 게임명: 스킬 오목 (Skill Gomoku)
  • 장르: 전략 보드 게임
  • 플레이 방식: 1:1 대전
  • 플랫폼: PC / 모바일

🔷 게임 진행 방식

  • 플레이어는 번갈아가며 돌을 놓는다
  • 각 플레이어는 고유 스킬 1개씩을 보유하며, 총 3회 사용 가능
  • 스킬 사용은 자신의 턴 시작 시 결정
  • 강화 타일 위에 돌을 놓으면, 다음 1턴 동안 해당 수는 금수 룰 무시

🔷 추가적인 게임 규칙

  • 금수 룰은 기본 적용 (33, 44, 6목)
  • 스킬 종류:
    • 🔥 "돌파" – 금수 룰 1턴 무시
    • ❌ "파괴" – 상대 돌 하나 제거
    • ⏱️ "재촉" – 상대 턴 시간 절반으로 제한

🔷 팀별 차별화 요소

  • 전통적인 오목의 사고력 + 스킬 기반의 전략성 강화

[선택 포함 내용]

  • 게임 시나리오 예시
  • 예상되는 사용자 경험



알까기 삼목

📌 1. 오목의 기본 개념 정리

✅ 오목이란?

  • 게임의 장르: 보드 전략 게임
  • 기본적인 목표: 가로, 세로, 대각선 방향으로 자신의 돌 5개를 연속으로 배치하여 승리

📌 2. 알까기 삼목 기본 규칙

✅ 게임에 사용되는 요소

  • 원형 보드(또는 격자형 바둑판)
  • 흑/백 알 (물리적으로 튕길 수 있음)
  • 마우스로 알을 튕기는 조작

✅ 기본적인 진행 방식

  • 플레이어는 번갈아가며 자신의 알을 튕겨서 보드에 놓음
  • 알은 바닥에서 굴러가며 다른 알에 부딪히거나, 보드 밖으로 나갈 수 있음
  • 정확한 위치 조준 및 세기 조절이 필요함
  • 알이 보드 밖으로 떨어지면 무효 처리, 다시 놓을 수 없음

📌 3. 승리 조건 및 특수 규칙

✅ 승리 조건

  • 보드 위에 남아 있는 자신의 알 중에서 연속 5개가 가로, 세로, 또는 대각선으로 연결되면 승리
  • 튕겨서 의도하지 않게 연결될 수도 있고, 상대의 알을 밀어내며 전략적으로 배치 가능

✅ 패배 조건

  • 상대가 먼저 연속 5개를 만들면 패배
  • 자신의 알을 너무 많이 보드 밖으로 날려서 불리해지면 패배 가능성 ↑

✅ 특수 규칙 (선택 적용 가능)

  • 튕기기 제한 시간: 한 턴당 10초
  • 알 수 제한: 각 플레이어는 10개의 알만 사용 가능
  • 자기 알로 자기 알 밀기 가능 / 상대 알 밀어내기도 가능
  • 한 번에 여러 개의 알이 밀리거나 튕겨나가도 허용

📌 4. 게임 차별점 및 재미 요소

✅ 기존 오목과의 차별점

항목 기존 오목 알까기 오목

방식 클릭/두기 튕기기 (물리 조작)
전략성 고정된 위치 계산 위치 + 물리 반응 예측
재미 포인트 정적인 수 싸움 예측 불가한 물리 반응, 반전 가능성
룰 완성도 정제된 룰 창의적, 신선한 룰 적용

✅ 게임의 핵심 재미 정의

“정확한 컨트롤과 전략으로 알을 튕겨 5목을 완성하는 역동적인 오목!”


📌 5. 최종 기획 문서 요약

🔷 게임 개요

  • 게임명: 알까기 오목
  • 장르: 보드 + 피직스 기반 전략 게임
  • 플레이 인원: 2명
  • 방식: 번갈아가며 알을 튕겨 보드에 배치

🔷 진행 방식 요약

  • 손 또는 마우스로 알을 튕겨 보드에 놓는다
  • 이미 놓인 알을 맞춰 이동시킬 수 있다 (전략적 충돌 가능)
  • 보드 밖으로 나가면 해당 알은 무효

🔷 추가 규칙

  • 튕기기 시간 제한 (10초)
  • 제한된 수의 알만 사용 가능
  • 5목이 먼저 완성되면 즉시 승리

📌 6. 예상 사용자 경험

  • 직관적인 재미: 누구나 쉽게 튕기기 시작
  • 실력 기반 경쟁: 손 조작의 정확성 + 전략적 사고
  • 웃음 유발: 예측 불가한 물리 반응으로 예상치 못한 전개
  • 빠른 템포: 턴 간 템포가 빠르고 실시간성 있음
반응형
반응형

1. 오늘 학습 키워드

기초 문법 복습, 달리기반 Lv1, Lv2 풀기


2. 오늘 학습 한 내용을 나만의 언어로 정리하기

달리기반 Lv1, Lv2, Lv3

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//------------------------------------------------------------------------------------------------------------------------//
//기본 문법 복습

//팀원에게 스위치 케이스문 질문을 받았는데 나는 그냥 일반적인 숫자나 변수값이 들어가도 되는 줄 알았다
//하지만 알아보니 리터럴 상수값이 들어간다고 한다 처음에는 리터럴 상수가 뭔지 제대로 이해하지 못했다
//리터럴 상수 == 코드에 직접 적은 값 이라고 한다. 결국 우리가 그냥 사용하는 숫자다.
//switch문의 case에 들어가는 값은 반드시 상수여야한다(예 : 리터럴, const, enum 등)

Console.Write("값을 입력해주세요 : ");

int number = int.Parse(Console.ReadLine());

Console.WriteLine("입력된 값 " + number);

switch (number)
{
    case 1: //이건 지금 리터럴 상수로 사용된 것
        Console.WriteLine("1번이 선택되었습니다.");
        break;
    case 2:
        Console.WriteLine("2번이 선택되었습니다.");
        break;
}

//case에는 변수값이 들어갈 수 없고 리터럴 상수와 같이 사용하면 된다.

//------------------------------------------------------------------------------------------------------------------------//
//Lv1. 홀수 출력
//1부터 100까지의 숫자 중에서 홀수만 출력하는 프로그램을 작성하세요.
//1. for문을 사용해 홀수를 출력하세요.

Console.WriteLine("for문 1~100사이 홀수 값 출력");
for(int i=1; i<=100; i++)
{
    if(i%2 != 0)
    {
        Console.Write(i + " ");
    } 
}
Console.WriteLine();
Console.WriteLine();

//2. while문을 사용해 홀수를 출력해 주세요.
Console.WriteLine("while문 1~100사이 홀수 값 출력");
int num = 1;
while(num <= 100)
{
    if (num % 2 != 0)
    {
        Console.Write(num + " ");
    }
    num++;
}
Console.WriteLine();
Console.WriteLine();

//3. do-while문을 사용해 홀수를 출력해주세요.
Console.WriteLine("do-while문 1~100사이 홀수 값 출력");
int k = 1;
do
{
    if (k % 2 != 0)
    {
        Console.Write(k + " ");
    }
    k++;
} while (k <= 100);

//------------------------------------------------------------------------------------------------------------------------//
//Lv1. 배열을 사용한 합계 및 평균 계산
int[] numbers = { 10, 20, 30, 40, 50 };
int sum = 0;

for(int i=0; i<numbers.Length; i++)
{
    sum += numbers[i];
}
int ave = sum / numbers.Length;

Console.WriteLine("합계 : " + sum);
Console.WriteLine("평균 : " + ave);

//------------------------------------------------------------------------------------------------------------------------//
//Lv2. 팩토리얼 계산

Console.WriteLine("팩터리얼 계산");
Console.Write("값 입력 : ");
int number = int.Parse(Console.ReadLine());
int sub = 1;

for(int i= number; i>=1; i--)
{
    sub *= i;
}

Console.WriteLine("값 : " + sub);

//------------------------------------------------------------------------------------------------------------------------//
//LV2. 숫자 맞추기 게임

Console.WriteLine("숫자 맞추기 게임");

Random random = new Random();
int randomNum = random.Next(1, 101);

while (true)
{
    Console.Write("번호 입력 : ");
    int sel = int.Parse(Console.ReadLine());
    if(randomNum == sel)
    {
        Console.WriteLine("정답!!");
        break;
    }
    else if(randomNum > sel)
    {
        Console.WriteLine("선택한 값보다 큽니다.");
    }
    else if(randomNum < sel)
    {
        Console.WriteLine("선택한 값보다 작습니다.");
    }
}

//------------------------------------------------------------------------------------------------------------------------//
//Lv2. 이중 반복문을 사용한 구구단 출력

//가로로 출력
for(int i=1; i<=9; i++)
{
    for(int j=2; j<=9; j++)
    {
        Console.Write(j + "x" + i +"=" + (i*j) + "  ");
    }
    Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine();

//세로로 출력
for (int i = 2; i <= 9; i++)
{
    for (int j = 1; j <= 9; j++)
    {
        Console.Write(i + "x" + j + "=" + (i * j) + "  ");
    }
    Console.WriteLine();
}

//------------------------------------------------------------------------------------------------------------------------//
//Lv2. 배열 요소의 최대값과 최소값 찾기

int[] numbers = { 10, 20, 30, 40, 50 };

int min = numbers[0];
int max = numbers[0];

for (int i = 0; i < numbers.Length; i++)
{
    for (int j = 0; j < numbers.Length; j++)
    {
        if (numbers[j] < min) { min = numbers[j]; }
        if (numbers[j] > max) { max = numbers[j]; }
    }
}

Console.WriteLine("최대값 : " + max);
Console.WriteLine("최소값 : " + min);

//------------------------------------------------------------------------------------------------------------------------//
//------------------------------------------------------------------------------------------------------------------------//
//Lv3. 행맨 게임
string secretWord = "hangman";
char[] guessWord = new char[secretWord.Length];
int maxAttempts = 6;
int attempts = 0;
bool wordGuessed = false;

for (int i=0; i<guessWord.Length; i++)
{
    guessWord[i] = '_';
}

while (attempts < maxAttempts && !wordGuessed)
{
    Console.WriteLine("현재 단어 : " + new string(guessWord));
    Console.Write("문자를 입력해주세요 : ");
    char input = Console.ReadKey().KeyChar; //char 입력받기 몰랐던 부분.
    Console.WriteLine();

    bool correctGuess = false;

    
    for(int i=0; i< secretWord.Length; i++)
    {
        if (secretWord[i] == input && guessWord[i] == '_')
        {
            guessWord[i] = input;
            correctGuess = true;
        }
    }

    if (!correctGuess)
    {
        attempts++;
        Console.WriteLine("틀렸습니다. 남은 기회 : " + (maxAttempts-attempts));
    }

    wordGuessed = true;
    for (int i = 0; i < secretWord.Length; i++)
    {
        if (guessWord[i] != secretWord[i])
        {
            wordGuessed = false;
            break;
        }
    }

}

if (wordGuessed)
{
    Console.WriteLine("단어를 맞췄습니다!" + secretWord);
}
else
{
    Console.WriteLine("기회를 모두 소진하였습니다. 정답은 :" + secretWord);
}

//------------------------------------------------------------------------------------------------------------------------//
//Lv3. 숫자 야구 게임

Random random = new Random();
int[] targetNumber = new int[3];

// 중복 없는 3자리 숫자 생성
int index = 0;
while (index < 3)
{
    int num = random.Next(1, 10);
    bool isDuple = false;

    for (int i = 0; i < index; i++)
    {
        if (targetNumber[i] == num)
        {
            isDuple = true;
            break;
        }
    }

    if (!isDuple)
    {
        targetNumber[index] = num;
        index++;
    }
}

bool isGuessUser = false;

while (!isGuessUser)
{
    int[] userGuess = new int[3];

    for (int i = 0; i < 3; i++)
    {
        Console.Write($"유저 번호 선택 {i + 1}번째 : ");
        userGuess[i] = int.Parse(Console.ReadLine());
    }

    Console.Write("선택한 번호 : ");
    for (int i = 0; i < 3; i++)
        Console.Write(userGuess[i] + " ");
    Console.WriteLine();

    int strikes = 0;
    int balls = 0;

    for (int i = 0; i < 3; i++)
    {
        if (userGuess[i] == targetNumber[i])
        {
            strikes++;
        }
        else if (Array.Exists(targetNumber, x => x == userGuess[i]))
        {
            balls++;
        }
    }

    Console.WriteLine($"{strikes} 스트라이크, {balls} 볼");
    Console.WriteLine();
    Console.WriteLine();

    if (strikes == 3)
    {
        Console.WriteLine("정답입니다!");
        isGuessUser = true;  // ← 게임 종료 플래그
    }
}


3. 학습하며 겪었던 문제점 & 에러 / 새롭게 알게 된 점 정리

✅ 1. switch문에서 변수 사용이 안 되는 이유

  • switch문의 case에는 반드시 컴파일 타임 상수 값만 들어가야 한다.
    • 사용 가능한 값: 리터럴(literal), const로 정의된 상수, enum 값 등
  • 평소에 숫자를 그냥 넣어서 사용했기 때문에 변수도 되겠지라고 착각했지만, 실제론 case에서 변수 사용 시 컴파일 에러 발생
  • ❌ 예시 (에러):
  • int a = 1; switch(x) { case a: // ❌ 오류! a는 런타임 변수 }
  • ✅ 예시 (정상):
  • const int a = 1; switch(x) { case a: // ✅ 컴파일 타임 상수 사용 가능 }

✅ 2. 리터럴 상수(Literal Constant)의 개념

  • 리터럴 상수란 코드에 직접 작성한 값
    • 예: 1, 'A', "Hello", true
  • case 1:, case 'A':처럼 우리가 자주 쓰는 숫자나 문자는 리터럴이기 때문에 사용 가능
  • 반면, 일반 변수는 값이 바뀔 수 있으므로 case에서 사용할 수 없음

✅ 3. Console.ReadKey().KeyChar – char 한 글자 입력받기

  • 기존에 Console.ReadLine()만 사용했기 때문에 문자 단위 입력 처리 방법을 몰랐음
  • Console.ReadKey().KeyChar를 사용하면 한 글자를 즉시 입력받을 수 있음
  • 유용한 경우: 메뉴 선택, 키 입력 처리, 게임 입력 등
  • Console.Write("입력: "); char input = Console.ReadKey().KeyChar; Console.WriteLine("\\n입력한 문자: " + input);

✅ 4. Array.Exists() – 배열 안에 값이 있는지 확인

  • Array.Exists(array, x => x == 값) 형태로 사용
  • for문을 쓰지 않고도 배열에 값이 존재하는지 간단히 확인 가능
  • 숫자 야구 게임에서 볼(Ball) 판별 시 사용했음
  • if (Array.Exists(targetNumber, x => x == userGuess[i])) { balls++; }

✅ 느낀 점 요약

  • switch-case 문법에서 컴파일 타임 상수의 중요성을 명확히 알게 됨
  • ReadKey()를 통해 빠른 문자 입력 방식을 익히고 활용 가능성을 느낌
  • Array.Exists()처럼 람다식을 활용한 배열 검색 방법이 코드 간결화에 효과적임을 깨달음

4. 내일 학습 할 것

  • 유니티 강의수강

5. 메모

새로운 팀원 추가!!

홍기정 - 93년생 원래 C#을 사용했었고 유니티도 조금 공부했었다.

김혜수 - 91년생 UI,UX를 하다가 유니티를 배워보려고 왔다.

원래 달리기반 Lv1, Lv2만 풀려고 했지만 시간이 남아서 Lv3 까지 풀어봤다. 하지만 쉽지 않았다 모르는 문법도 있었고 아직 갈 길이 먼거같다. 역시 개발자는 겸손할 수 밖에 없는 직업.. 하나씩 차근차근히 잘 배워보자!!!


반응형