(현) 캐나다 AAA 게임 스튜디오 U사 게임 프로그래머
- PC/콘솔 AAA 액션 어드벤처 게임 프로젝트 참여
(전) 국내 게임사 N사 서버 프로그래머
- 언리얼 MMORPG 게임 프로젝트 참여
(전) 국내 게임사 N사 클라이언트 프로그래머
- 언리얼 MMORPG 게임 프로젝트 참여
(전) 국내 게임사 N사 클라이언트 프로그래머
- 유니티 캐주얼/미드코어 게임 프로젝트 참여
(전) 국내 대기업 S그룹 소프트웨어 엔지니어
- S그룹 계열사 전산 시스템 프로젝트 참여
안녕하세요. 게임 개발자 BurningCarrot 버닝캐럿 입니다.
게임을 개발하는 사람이 되고 싶다는 마음으로
대기업을 퇴사한 후 국내 게임 회사를 거쳐
현재는 해외 게임 스튜디오에서 일하고 있습니다.
현재 업계에 몸담고 있는 만큼, 현업에서 사용하는
실전 노하우와 기법을 최대한 공유 드리고자 합니다.
여러분과 같이 게임을 좋아하고 만드는 한 사람으로서,
제 강의를 수강 하시는 모든 분들이 각자의 목표에
한걸음 더 다가갈 수 있는 유익한 시간이 되었으면 좋겠습니다.
📩 문의 : burningcarrotstudio@gmail.com
💡블로그 : https://blog.naver.com/burningcarrot
💡브런치 : https://brunch.co.kr/@burningcarrot#works
💡스레드 : https://www.threads.com/@burning.carrot
💡X(구 트위터) : https://x.com/burningcarrot10
강의
수강평
- 취업완성 C++: 10년 간의 게임사 면접 기출 & 실전 사례 수록 (기본편)
- 취업완성 C++: 10년 간의 게임사 면접 기출 & 실전 사례 수록 (기본편)
- 유니티 시스템 프로그래밍 Pt.2 - 상용 게임 구현을 위한 핵심 시스템 올인원 패키지
- 유니티 시스템 프로그래밍 Pt.2 - 상용 게임 구현을 위한 핵심 시스템 올인원 패키지
게시글
질문&답변
파이어베이스 이벤트 로그 수집관련 질문입니다.
안녕하세요! BurningCarrot입니다. 문의해 주신 내용에 답변 드립니다.앱 삭제시 삭제하는 유저의 마지막 스테이지 값을 함께 받아보고 싶은데 어떻게 구현해야 하는지 궁금합니다.앱 삭제 시 유니티에서 별도로 호출되는 콜백이 없기 때문에 이 부분은 구현이 어려울 것 같습니다.동일한 유저가 앱을 설치하고 삭제한 뒤 다시 재설치하고 또 삭제한 다면 설치한 유저는 총 2명, 삭제한 유저는 총 2명으로 기록되는지 궁금합니다.네 파이어베이스에 앱 삭제 시 다시 설치하면 새로운 유저로 인식한다고 알려져 있습니다. 다만 유저 로그인 시 기존에 사용했던 아이디를 이용하면 기존에 저장되었던 유저 데이터를 불러올 수 있어 유저가 기존에 보유했던 재화, 플레이 이력 그대로 다시 플레이할 수 있습니다.
- 0
- 1
- 26
질문&답변
파이어베이스 관련 질문입니다.
안녕하세요! BurningCarrot입니다.웬일로 인프런 AI 인턴이 정확한 답변을 해줬네요.👀제가 따로 답변을 드릴 필요는 없을 것 같습니다. 아래 내용 참고하시면 되겠습니다.감사합니다.
- 0
- 2
- 32
질문&답변
업적/미션 Pt.3에서 OnClickClaimBtn 호출 시 Sort 부분 호출 동작
안녕하세요! BurningCarrot입니다. 문의해 주신 내용에 답변 드립니다.혹시 AchievementUI 스크립트에 아래 코드가 포함되어 있을까요? 해당 코드가 있어야 OnAchievementProgressed 함수가 작동합니다.public class AchievementUI : BaseUI { //... private void OnEnable() { Messenger.Default.Subscribe(OnAchievementProgressed); } private void OnDisable() { Messenger.Default.Unsubscribe(OnAchievementProgressed); } //... }
- 0
- 1
- 60
질문&답변
구글 플레이 콘솔 사전 예약 등록에 대해.
안녕하세요! BurningCarrot입니다.모든 설정을 다 완료하셨음에도 "사전 등록 시작" 버튼도 활성화되지 않는게 맞을까요?사전 등록 테스트 탭에서도 두 개 항목 중 하나는 선택한 상태이실까요?(사진)
- 0
- 2
- 59
질문&답변
우편 기능에 대해 궁금합니다.
안녕하세요! BurningCarrot입니다. 문의해 주신 내용에 답변 드립니다.저의 경우 Firestore DB에 UserMailData라는 컬렉션을 만들고, 그 데이터를 불러와서 UI에 표시해주는 방식으로 우편함 시스템을 구현했었습니다. 특정 플레이어에게 보상을 우편으로 전달해야 한다면, Firestore DB 콘솔에서 해당 플레이어의 UserMailData에 보상에 대한 데이터를 추가해 줍니다. 그럼 플레이어는 그 우편을 열어 '받기'를 클릭하면 보상이 지급됩니다.물론 이럴 경우 수강생분이 각 플레이어를 식별할 수 있는 계정 정보(ex. 이메일)를 추가적으로 Firestore DB에 수집해 두셔야 합니다. 그리고 그런 개인정보를 저장할 때는 개인정보 처리방침 등에 잊지말고 잘 명시해야 하고, 구글/애플 개발자 콘솔의 유저 개인정보 수집 설정 페이지도 각 항목들이 올바르게 선택되어 있는지 잘 확인해 주셔야 합니다.이해가 되지 않는 부분이 있으시다면 편하게 다시 질문해 주시길 바랍니다.
- 0
- 2
- 39
질문&답변
41-원격 리소스 다운로드 강의의 후반에 실습할 텍스쳐가 없습니다.
안녕하세요! BurningCarrot입니다. 문의해 주신 내용에 답변 드립니다.이미지 리소스 첨부해 드립니다. 사실 해당 강의는 원격 리소스를 교체해서 재업로드하면, 교체된 이미지로 새로 다운로드 되어 적용된다는 것을 보여드리는 내용이므로 다른 이미지로 아무거나 교체하셔서 테스트 하셔도 됩니다.감사합니다.(확인해 봤는데 여기 이미지를 첨부하면 다운로드가 되지 않네요. 41-원격 리소스 다운로드 강의 첨부파일에 넣어 다시 업로드해 드리겠습니다. 해당 강의 첨부파일 다시 확인 부탁 드립니다)(사진)
- 0
- 2
- 35
질문&답변
로컬 알림과 다국어 지원에 대해 궁금합니다.
안녕하세요! BurningCarrot입니다. 문의해 주신 내용에 답변 드립니다.로컬 알림제가 이전에 사용하던 코드를 공유 드리겠습니다.로컬 알림 sdk 다운로드Package Manager에서 Mobile Notifications로 검색해서 설치아래 코드를 싱글턴 게임 오브젝트로 적용LocalNotifyType은 수강생분이 새로운 로컬 알림을 추가하실 때마다 타입을 추가하시면 되겠습니다. 하트(자원) 충전, 가챠(뽑기) 박스 충전 등 알림의 종류를 의미하는 값입니다. 각 타입마다 적용해 주실 ID값을 적절하게 설정해 주세요. 저는 예시로 TypeA, TypeB, TypeC 이런식으로 표기해 두었습니다. 게임이 중단되거나 종료될 때 디바이스 플랫폼에 따라 알림이 실행되어야 할 시간을 계산해서 SetAOSNotification, SetIOSNotification 함수를 호출하시면 될 것입니다. 유니티 매뉴얼 링크도 같이 첨부 드립니다. https://docs.unity3d.com/Packages/com.unity.mobile.notifications@1.0/manual/index.html#if UNITY_ANDROID using Unity.Notifications.Android; #elif UNITY_IOS using Unity.Notifications.iOS; #endif using System.Collections; using System; public enum LocalNotifyType { TYPE_A, TYPE_B, TYPE_C } public class LocalNotificationManager : SingletonBehaviour { private string m_IOSTypeAID = string.Empty; private string m_IOSTypeBID = string.Empty; private string m_IOSTypeCID = string.Empty; protected override void Init() { base.Init(); #if UNITY_ANDROID InitAOS(); #elif UNITY_IOS InitIOS(); #endif } public void SetNotification(LocalNotifyType notifyType, string notiTitle, string notiText, int days, int hours, int minutes, int seconds) { #if UNITY_ANDROID SetAOSNotification(notifyType, notiTitle, notiText, days, hours, minutes, seconds); #elif UNITY_IOS SetIOSNotification(notifyType, notiTitle, notiText, days, hours, minutes, seconds); #endif } public void CancelAllNotification() { #if UNITY_ANDROID CancelAllAOSNotification(); #elif UNITY_IOS CancelAllIOSNotification(); #endif } #region AOS private void InitAOS() { #if UNITY_ANDROID AndroidNotificationCenter.Initialize(); var typeAChannel = new AndroidNotificationChannel() { Id = "AOS_TypeA_Id", Name = "AOS_TypeA_Channel", Importance = Importance.Default, Description = "AOS_TypeA_Notification", }; AndroidNotificationCenter.RegisterNotificationChannel(typeAChannel); var typeBChannel = new AndroidNotificationChannel() { Id = "AOS_TypeB_Id", Name = "AOS_TypeB_Channel", Importance = Importance.Default, Description = "AOS_TypeB_Notification", }; AndroidNotificationCenter.RegisterNotificationChannel(typeBChannel); var typeCChannel = new AndroidNotificationChannel() { Id = "AOS_TypeC_Id", Name = "AOS_TypeC_Channel", Importance = Importance.Default, Description = "AOS_TypeC_Notification", }; AndroidNotificationCenter.RegisterNotificationChannel(typeCChannel); #endif } private void SetAOSNotification(LocalNotifyType notifyType, string notiTitle, string notiText, int days, int hours, int minutes, int seconds) { #if UNITY_ANDROID var notification = new AndroidNotification(); notification.SmallIcon = "small_icon"; notification.LargeIcon = "large_icon"; notification.Title = notiTitle; notification.Text = notiText; notification.FireTime = DateTime.Now.AddDays(days).AddHours(hours).AddMinutes(minutes).AddSeconds(seconds); switch (notifyType) { case LocalNotifyType.TYPE_A: AndroidNotificationCenter.SendNotification(notification, "AOS_TypeA_Id"); break; case LocalNotifyType.TYPE_B: AndroidNotificationCenter.SendNotification(notification, "AOS_TypeB_Id"); break; case LocalNotifyType.TYPE_C: AndroidNotificationCenter.SendNotification(notification, "AOS_TypeC_Id"); break; default: break; } #endif } private void CancelAllAOSNotification() { #if UNITY_ANDROID AndroidNotificationCenter.CancelAllNotifications(); #endif } #endregion #region IOS private void InitIOS() { StartCoroutine(RequestAuthorization()); } private IEnumerator RequestAuthorization() { #if UNITY_IOS using (var req = new AuthorizationRequest(AuthorizationOption.Alert | AuthorizationOption.Badge, true)) { while (!req.IsFinished) { yield return null; }; string res = "\n RequestAuthorization: \n"; res += "\n finished: " + req.IsFinished; res += "\n granted : " + req.Granted; res += "\n error: " + req.Error; res += "\n deviceToken: " + req.DeviceToken; Logger.Log(res); } #endif yield return null; } private void SetIOSNotification(LocalNotifyType notifyType, string notiTitle, string notiText, int days, int hours, int minutes, int seconds) { #if UNITY_IOS var timeTrigger = new iOSNotificationTimeIntervalTrigger() { TimeInterval = new TimeSpan(days, hours, minutes, seconds), Repeats = false }; var identifier = string.Empty; var categoryIdentifier = string.Empty; var threadIdentifier = string.Empty; switch (notifyType) { case LocalNotifyType.TYPE_A: identifier = "IOS_TypeA_Id"; categoryIdentifier = "Category_TypeA"; threadIdentifier = "Thread_TypeA"; m_IOSTypeAID = identifier; break; case LocalNotifyType.TYPE_B: identifier = "IOS_TypeB_Id"; categoryIdentifier = "Category_TypeB"; threadIdentifier = "Thread_TypeB"; m_IOSTypeBID = identifier; break; case LocalNotifyType.TYPE_C: identifier = "IOS_TypeC_Id"; categoryIdentifier = "Category_TypeC"; threadIdentifier = "Thread_TypeC"; m_IOSTypeCID = identifier; break; default: break; } var notification = new iOSNotification() { Identifier = identifier, Title = notiTitle, Body = notiText, ShowInForeground = true, ForegroundPresentationOption = (PresentationOption.Alert | PresentationOption.Sound), CategoryIdentifier = categoryIdentifier, ThreadIdentifier = threadIdentifier, Trigger = timeTrigger, }; iOSNotificationCenter.ScheduleNotification(notification); #endif } private void CancelIOSNotification(LocalNotifyType notifyType) { #if UNITY_IOS var notifyID = string.Empty; switch (notifyType) { case LocalNotifyType.TYPE_A: notifyID = m_IOSTypeAID; break; case LocalNotifyType.TYPE_B: notifyID = m_IOSTypeBID; break; case LocalNotifyType.TYPE_C: notifyID = m_IOSTypeCID; break; default: break; } iOSNotificationCenter.RemoveScheduledNotification(notifyID); #endif } private void CancelAllIOSNotification() { #if UNITY_IOS iOSNotificationCenter.RemoveAllScheduledNotifications(); iOSNotificationCenter.RemoveAllDeliveredNotifications(); #endif } #endregion }CSV 파일 내 문자열에서 ,CSV파일에서 그냥 전체 문자열을 ""로 감싸주시면 됩니다. "안녕하세요, BurningCarrot입니다." 이렇게 해주시면 됩니다.
- 0
- 2
- 45
질문&답변
통합 에셋
안녕하세요! BurningCarrot입니다. 문의해 주신 내용에 답변 드립니다.Pt.2의 통합 어셋을 제공해 드리려면 Pt.1의 어셋도 제공해 드려야 하고(Pt.1&2 모두, Pt.2만 들으시는 분 사이의 형평성 문제), 수강생 분들마다 각종 외부 SDK 버전의 상이함으로 인해 빌드 에러 문제가 생길 수 있기 때문에 제공해 드리지 않고 있습니다. 양해 부탁 드립니다.🙏감사합니다.
- 0
- 2
- 37
질문&답변
구글 AD 미디에이션
안녕하세요! BurningCarrot입니다. 문의해 주신 내용에 답변 드립니다.Admob 미디에이션에 대한 문서는 해당 링크를 참고하시면 됩니다.https://developers.google.com/admob/unity/mediation?hl=ko기본 구현 원리는내가 포함시키고자 하는 광고 네트워크 미디에이션 SDK 추가 설치https://developers.google.com/admob/unity/choose-networks?hl=ko광고매니저 초기화 코드에 미디에이션 어댑터 초기화 코드 추가 MobileAds.Initialize((InitializationStatus initializationStatus) => { Dictionary map = initializationStatus.getAdapterStatusMap(); foreach (KeyValuePair keyValuePair in map) { string className = keyValuePair.Key; AdapterStatus status = keyValuePair.Value; switch (status.InitializationState) { case AdapterState.NotReady: // The adapter initialization did not complete. Logger.Log($"Adapter: {className} is not ready."); break; case AdapterState.Ready: // The adapter was successfully initialized. Logger.Log($"Adapter: {className} is initialized."); break; } } });
- 0
- 2
- 51
질문&답변
구글로그인 인증 에러 문제 살려주세요 ㅠㅠ
안녕하세요! BurningCarrot입니다. 문의해 주신 내용에 답변 드립니다.크래시는 Firebase SDK 버전 문제로 추측됩니다. 현재 사용하시는 유니티 버전과 Firebase SDK 버전이 어떻게 되시는지 공유 부탁 드립니다.
- 0
- 2
- 70




