전체 글 (204)

  • 2024.02.18
  • 2024.02.15
  • 2024.02.14
  • 2024.02.13
  • 2024.02.08
  • 2024.02.07
  • 2024.02.07
  • 2024.02.05
  • 2024.02.02
  • 2024.02.02
  • 2024.02.02
  • 2024.02.02
  • 02
    18

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 37일차

    부분진행도 : Chapter4.2 - 5일차

    작성일자 : 2024.02.16(금)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    팀 과제 마지막날, 발표를 무사히 끝냈다. (확인해보니 포스트 내용이 날아가 있어 간단하게나마 수정중)

    2. 오늘 학습에 대해

    • 게임 개발에 있어 느낀 점
      • 이번엔 UI 구조화를 나름 도전 해 보았는데, 기반이 갖춰지는 만큼 이후 스퍼트에서 좋은 효율을 보였다.
        • 일단 구축 역량이 제일 중요하다
        • 구조 구축에 긴 시간이 필요하거나 개발 기간이 극도로 짧다면 분배를 정말 잘 하여야겠다.
      • Manager들의 구성에 대해 소통을 잘 해야 한다.
        • 전체 매니저를 관리하거나, 게임 전체를 총괄하는 매니저의 부재로, 개인적으로 TempManagers라는 매니저를 사용하였는데, 소통의 부재로 개인용 매니저가 되어버렸다. 사실 그래도 상관은 없었지만 나중에 본다면 구조적으로 아쉬운 부분이 될 것은 확실하다.
    • 발표 준비에 있어 느낀 점
      • 밤을 새며 준비한 것 치고는 볼륨을 많이 낼 수가 없었다. 발표라는 걸 해본 경험이 거의 없었기 때문이라고는 생각하지만 상상 이상으로 시간을 소요했다.
      • 전체적인 흐름은 나쁘지 않았다고 생각하지만, 확 와닿는 핀트를 잡지 못했다고 생각했다.
        • 게임 소개는 좋은 흐름이었다고 생각한다.
        • 기술적인 부분은 기존 안내된 대로 팀원이 각자 1분 30초가량의 영상을 준비하여 넣어 괜찮았는데, 이렇게 하지 않았다면 내가 직접 기술적인 내용을 많이 넣지는 못했을 것이라고 생각한다. 앞으로 발표 자료를 준비할 일이 있다면 더 신경써야 할 것.
        • 팀원 역할에 대해서는 넣었지만 각자의 개성을 보여주는 것은 포기했다. 발표를 듣는 사람의 관점에 따라 해당 내용은 호불호가 크게 갈리지 않을까 싶다.
        • 마지막 슬라이드에 '-終-' 이라는 문구 괜히 넣은 것 같다.
      • 시연 영상의 촬영
        • 무척 시간이 오래 걸리지는 않았고, 편집 중 나레이션이 비는 부분이 많아 자연스럽게 영상과 엮기가 어려웠다.
        • 그래도 미리 어떤 내용과 흐름으로 할 지 설계를 해 두고, 그에 맞게 의식하며 게임 시연 영상을 찍고 나레이션을 녹화하는 것은 좋은 선택이었던 것 같다. 문제가 되었던 건 그저 경험이 부족해서 전체적인 그림이 잘 그려지지 않았던 것.
      • 그 외
        • 발표에 어울리는 잔잔한 목소리들이 부럽다. 이에 관한 연습도 하면 되는걸까.

    3. 과제에 대해

    • 팀 리포지토리 포크 하여 정돈해두기
    • 챌린지반 세션 델리게이트 내용 이후 다시 보며 익히기
    • 오는 주차 제공 강의 학습하고 익숙해지기
    • 루키스 강의도 시간 내서 보고 싶은데, 과연.
    반응형
    COMMENT
     
    02
    15

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 36일차

    부분진행도 : Chapter4.2 - 4일차

    작성일자 : 2024.02.15(목)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    유니티 게임개발 숙련주차의 팀 프로젝트 4/5일째 진행중이다.

    3D 플랫폼 퍼즐게임을 개발중이고, UI전반을 맡아 진행중에 있다.

    UI를 구성할 뼈대를 갖추는 데 시간이 많이 걸렸고, 스퍼트가 붙기 시작할 때 즈음 마감일이 다가와서 아쉬운 기분이다.

    아직 해야 할 작업이 많이 남았는데, 룰렛을 돌려 발표담당까지 맡게 되었다. 앞으로 14시간 뒤가 과제 제출 마감시간이고, 16시간 뒤 발표 세션을 시작한다. 밤샘각이지만 14시간이나 있으니 어떻게든 되겠지라는 생각중이다.

    2. 오늘 학습에 대해

    팀 리포지토리 커밋 그래프

    이전 프로젝트와는 다르게, 오브젝트들을 모두 제대로 프리팹화 하여 작업들을 했기 때문에, 브렌치들이 머지 될 때 충돌이 아얘 없었다. 하나 보였던 충돌은, 빌드세팅에서 설정 차이가 조금 있었다는 점 1회.

    각자 만든 이벤트에 모두 구독 시스템을 잘 넣어두었기 때문에, 머지 이후에도 나름 쉽게 서로 연동이 잘 되었다.

    3. 과제에 대해

    - UI 작업 마치기, 발표 자료 만들고 제출 준비하기

    반응형
    COMMENT
     
    02
    14

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 35일차

    부분진행도 : Chapter4.2 - 3일차

    작성일자 : 2024.02.14(수)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    팀 프로젝트 3/5(발표날 포함)일째이다. 3D플랫폼 퍼즐 게임을 진행중이고, UI 및 씬 관리 전반을 하고있다.

    굉장히 시간이 모자라다. 스크립트와 UI의 기본적인 프리팹은 모두 준비되었는데, 메인 브런치에 Merge를 해가며 진행할 요소가 너무 많아 시간에 맞출 수 없을 것 같은 기분이 들고, UI가 아니더라도 퍼즐 쪽도 어떻게 진행이 될지, 내일 하루만에 완성을 해야할텐데 정말 모르겠다.

    Todo 리스트를 열심히 지워가며 진행중인데도 아직 할 게 많이 남았고 많이 또 생길 것 같다.

    Todo

    • 현재 Data에 따라 Stage 해금되도록 하기, 스테이지 선택 할 수 있도록 하기
    • 애니메이션이나 Fade in out 효과 넣기
    • 전체적인 디자인 손보기

    Merge 후 손보기

    • ESC키로 UI_Pause 띄우게 하기 : 제대로 메서드 써서 씌워야 Popup 오더 관리 됨
    • Player가 상호작용 가능 할 때, 어떻게 UI를 보여줄지 생각
    • Player의 상태를 보여줄 때, 어떻게 UI를 보여줄지 생각
    • 위 두 가지 사항에 대해, 화면 내 어느 위치에 UI를 배치하고 구현할지 생각
    • Player가 분신을 만들었을 때, 어떻게 UI를 보여줄지 생각
    • 게임을 클리어 했을 때, 어떻게 UI를 보여줄지 생각
    • 결과 데이터 저장

    일단 생각나는 것만 해도 이 정도. 에셋 찾아와서 UI를 꾸미는 게 정말 시간이 오래 걸릴 것 같은데 다른 것도 만만치 않다.

    2. 오늘 학습에 대해

    Unity의 생명주기때문에 코드가 꼬이는 일이 종종 있다. 매번 난감해서 생소한 코딩을 하며 해결을 하였는데, 오늘은 여러 스크립트가 꼬여 그렇게도 할 수가 없어, UI의 Start() 메서드에 사용하던 모든 코드를 통째로 다른곳으로 옮겨 작업을 해야만했다. 오브젝트를 만들고 컴포넌트를 붙여주는 작업이 그 오브젝트의 Start 메서드보다 빨리 실행되어 Null을 갖게 된 게 이유이다. 조금 더 경험이 쌓여있었다면 더 나은 방법으로 해결 할 수 있었을까 생각한다.

    3. 과제에 대해

    • 팀 프로젝트 되는 데까지 하기
    반응형
    COMMENT
     
    02
    13

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 34일차

    부분진행도 : Chapter4.2 - 2일차

    작성일자 : 2024.02.13(화)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    심화주차 팀 과제 2/5일차(발표날 포함)이다. 3D 플랫폼 퍼즐 게임을 만들고 있고, UI 전반 관리의 역할을 맡았다.

    1일차에 준비 해 둔 UI요소들

    1일차에 UI 요소들을 만들었는데, UI를 관리할 능력이 없어 관련 강의를 듣고 스크립트를 짜는 법을 대강이나마 배워왔다.

    어설프지만 그렇게 만들어진 오늘의 스크립트들의 목록은 위와 같다. 아직 매끄럽지 못한 부분이 많아 계속 손보아야 하지만 시간이 부족하다. 뼈대는 어찌저찌 마련하였으니 이젠 원래 스타일대로 깡코딩으로 밀어붙일 차례인 듯 하다.

    2. 오늘 학습에 대해

    오늘은 코테준비 없이 UI작업을 계속하였다. 메모 해 둘 정도의 트러블슈팅은 없었고, 간단하게 배운 내용을 조금 정리.

    게임이 로드 될 때 실행되는 특별한 메서드(유니티에서 지원)

    Monobehaviour을 상속받는 Managers.cs에서 사용한 방법이다.

    씬 위에 오브젝트와 컴포넌트를 배치하지 않더라고 게임이 로드 될 때 함께 메서드를 실행시켜주는 방법이 있었다.

    // 게임이 로드될 때 자동으로 실행
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void OnBeforeSceneLoadRuntimeMethod() 
    {
        Init();
    }

    게임 시작 시, Awake 실행 이전에 한번만 호출되는 함수이며, 나는 이 메서드에 Init()메서드를 두고, Init 메서드에서 @Managers 오브젝트의 생성과 그 안에 여러가지 Manager류 컴포넌트를 추가하는 방식을 사용하였다.

    팝업의 배경에 IPointerClickHandler를 상속

    팝업의 외부에 화면을 덮는 이미지를 만들어준 후(투명도는 자유, Raycast Target 옵션을 켜주어야 한다) 사용하면 좋고, 이 배경의 클릭 이벤트에 대응할 메서드를 버튼 컴포넌트 없이 쉽게 작성 할 수 있다.

    public class BlockBG : MonoBehaviour, IPointerClickHandler
    {
        public void OnPointerClick(PointerEventData eventData)
        {
            // BG 클릭 시, 가장 최근의 팝업을 지우기
            TempManagers.UI.ClosePopupUI();
        }
    }

    본인의 경우는 UIManager에서 팝업 관리 메서드 중 하나(닫기)를 사용했지만, 다른 방법으로도 쉽게 팝업을 닫던가 다른 행동을 할 수도 있다.

    3. 과제에 대해

    • UI 빡세게 구현 진행하기... 당장 공부하기도 구현하기도 시간이 너무 부족하다.
    반응형
    COMMENT
     
    02
    08

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 33일차

    부분진행도 : Chapter4.2 - 1일차

    작성일자 : 2024.02.08(목)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    숙련주차 팀 과제의 시작이다. 설 연휴 제외 오늘 포함 4일간 개발을 하고, 다음날 발표를 한다.

    이번 주제 역시 쉽지 않았다. 주어진 네개의 토픽 중 하나를 선택하여 기능구현을 한다. 우리 조는 긴 회의 끝에 3D 플랫폼 퍼즐 게임을 선택했다. 다른 세개의 주제도 쉽지 않아보였지만, 우리조도 만만치 않다.

    2. 오늘 학습에 대해

    저작권 특강 세션

    저작권과 관련하여 간단한 특강 세션을 진행했다.

    나는 저작권에 대해 자세한 내용은 거의 찾아본 적이 없었기 때문에 무척 도움이 되는 내용들이었다.

    일단 자주 보였지만 자세히 알아보지는 않았던 CC 라이선스에 대한 내용이다.

    크리에이티브 커먼즈 라이선스

    이용 허락 조건 네 종류(생각보다 적었다) 기호의 뜻만 알고 있어도 큰 불편함이 없을 것으로 보였다.

    • 사람 모양은, 출처를 표기하기.
    • 달러 모양은, 영리목적 금지
    • 이퀄 모양은, 변경 금지
    • 재사용같은 화살표 모양은, 변경 가능이지만 이후 창작물에 동일한 라이선스를 붙이기

    그리고, 어떻게 사용해도 상관없는 CC0 퍼블릭도메인 저작권이다.(땡큐를 외치며 사용하면 된다고)

    실제 예시도 다양하게 들을 수 있었는데, 저작권의 라이센스를 준수하며 사용한다고 하여도 문제가 발생할 수 있는 경우가 있다.

    • 판매자A의 저작물을 구매하여 사용하였다.
    • 나중에 알고보니, 판매자A는 판매자B의 저작물을 무단으로 판매하였다.

    이러한 경우 B로부터의 법적인 소송을 대비하기 위해, 나는 해당 저작물을 사용하기 시작하면서 판매자 A에게 이 저작물을 어떠한 용도로 사용한다는 이메일을 보내두는 방법을 사용할 수 있다.(A로부터의 답장이 없을 시, 한 달 정도 단위로 계속 연락을 시도한다.)

    이러한 기록을 확실히 쌓아두어 나는 A에게 저작물을 구매하여 억울하다는 입장이었다는 것을 보여줄 수 있다.

    프로젝트 진행

    앞서 적은 것처럼, 팀의 프로젝트로 '3D 플랫폼 퍼즐게임'을 선정했다.

    역할 분담으로는 UI 전반과 씬 전환 관리를 맡았다.

    회의 내용이 무척 많았고 길었기 때문에, 오늘의 개발 시간은 많지 않았다.

    나는 일단 UI 관련한 오브젝트들을 마련하였다. 스크립트 등은 내일부터 구상하거나 더 배우고 손대려고 한다.

    구현할 UI들 구상
    타이틀 씬에서 사용할 UI 패널들
    게임 씬에서 사용할 UI 패널들

    슬라이드바는 관련한 내용을 알아보고 넣을 예정이고, 이러한 UI 관련 강의들을 설 연휴(내일부터)에 찾아보며 공부해야겠다.

    개발기간이 4일밖에 되지 않아 퍼즐게임이 잘 만들어질지 모르겠다. 일단 아이디어가 부족해보이는 상황이다.

    적어도 UI만은 어디서든 접근하기 쉽도록 설계해야겠다.

    3. 과제에 대해

    • UI 관련 내용 많이 학습해서 팀 프로젝트에 기여하기

    4. 참고자료

    반응형
    COMMENT
     
    02
    07

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 32일차

    부분진행도 : Chapter4.1 - 5일차

    작성일자 : 2024.02.07(수)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    11시간에 걸친 밤샘 개인 과제 작성을 마쳤다. 오전 10시까지 제출이었는데 기능구현을 마치고 마지막까지 README와 혹시 있을 버그를 열심히 손보았다.

    내일부터는 약 일주일간 숙련주차의 팀 과제를 시작한다. 어떤 주제로 하게 될지는 아직 미지수.

    어제 캠프내 새로 사귀게 된 분들과 얘기를 하며 구조화에 대한 시야도 넓히고, 강의를 추천받았는데 굉장히 듣고 싶은 내용이었다.

    지금까지 내가 소화할 지 미지수인 것도 있고 유료라는 허들이 커서 유료강의는 거의 듣지 않았는데, 이번에 추천받은 Rookiss씨의 강의는 가격이 좀 나가도 내용이 무척 깊어 보여 엄청 듣고싶다고 생각하였다. 로드맵 강의를 따라가면 572,000원.

    아, 그리고 이전 입문 주차에 소화하지 못한 강의와, 이번 숙련주차에 소화하지 못한 13/13강 마지막 강의가 있다. 이것도 공부해야 할 듯.

    2. 오늘 학습에 대해

    과제 도중 이슈

    InputField의 값이 갱신되지 않는 버그

    발단

    public class Withdraw : MonoBehaviour
    {
        [SerializeField] private int amount;
    
        public InputField amountInput;
    
        public GameObject[] goSuccess;
        public GameObject popupObject;
        public Text AlertText;
    
        public DisplayText displayTextManager;
        public void OnClickButton()
        {
            if (amount < 1)
                amount = int.Parse(amountInput.text);
    
            if (DataManager.Instance.Withdraw(amount))
            {
                displayTextManager.RenewDisplay();
                foreach (GameObject go in goSuccess)
                    go.SetActive(!go.activeSelf);
                return;
            }
    
            AlertText.text = "계좌 잔금이 부족합니다.";
            popupObject.SetActive(!popupObject.activeSelf);
        }
    }

    값을 필드에 입력하고 출금 버튼을 클릭 시(OnClickButton()), 일정 금액이 출금된다.

    다른 금액을 다시 넣어 시도 시, 처음에 넣었던 금액만큼의 처리가 계속되는 현상이 있다.

    당장 코드만 보면 크게 문제가 없어 보였으나, 원인을 발견하였다.

    코드와 원인에 대해

    해당 메서드는, '10000원 버튼', '30000원 버튼', '50000원 버튼'을 누를 경우에도 대응되도록, 미리 설정된 amount가 1만, 3만, 5만이 아닐 경우(amount<1) InputField로부터 유저로부터 입력받은 값을 가져오도록 했다.

    그래서, amount가 새로 설정되는 시점부터 그 이후는 amount값이 1보다 크기 때문에 갱신을 하지 않은 것이었다.

    해결

    조건 분기를 위해 새로운 변수를 추가했다. [SerializeField] private bool useAmountInput;

    해당 변수는 에디터에서 체크를 할 수 있으며, InputField를 사용하여 유저가 직접 값을 입력하는 케이스에 체크 해 두도록 한다.

    수정된 코드는 아래와 같다.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class Withdraw : MonoBehaviour
    {
        [SerializeField] private int amount;
        [SerializeField] private bool useAmountInput; // 추가된 부분
        public InputField amountInput;
    
        public GameObject[] goSuccess;
        public GameObject popupObject;
        public Text AlertText;
    
        public DisplayText displayTextManager;
        public void OnClickButton()
        {
            if (useAmountInput) // 수정된 부분
                amount = int.Parse(amountInput.text);
    
            if (DataManager.Instance.Withdraw(amount))
            {
                displayTextManager.RenewDisplay();
                foreach (GameObject go in goSuccess)
                    go.SetActive(!go.activeSelf);
                return;
            }
    
            AlertText.text = "계좌 잔금이 부족합니다.";
            popupObject.SetActive(!popupObject.activeSelf);
        }
    }

    출금에서 발견했지만, 입금도 같은 구조이기 때문에 같이 수정 해 주었다.

    유니티의 json 등 파일 쓰기에 대해

    실시간으로 세이브 및 로드를 하는 경우, 파일 쓰기를 할 수 있는 경로가 극히 제한된다는 것을 알았다.

    Application.persistentDataPath을 데이터 저장 경로로 사용하는 케이스를 종종 볼 수 있다.

    나는 프로젝트 파일 근처에서 json파일을 열심히 찾아보다 보이지 않아 구체적인 경로를 검색 해 보았는데,

    C:\Users\[user name]\AppData\LocalLow\[company name]\[product name]

    위와 같은 복잡한 경로에 존재한다고 한다. 이게 어째서인고 하니..

    위 경로가 운영체제에서 앱이 사용할 수 있도록 허용한 경로라고 하여 유니티 실행 중 자유롭게 파일을 쓸 수 있는 경로인 것이다.

    그 외 아래와 같은 경로도 있는데,

    Application.dataPath
    Application.streamingAssetsPath

    각각 프로젝트 폴더 내부(Asset, StreamingAsset)를 반환하는데, 이러한 경로들은 파일을 수정하거나 작성 할 수 없다고 한다.

    3. 과제에 대해

    • 내일부터 팀 과제 수행, 과연 무슨 내용이 주어질지
    • 입문주차 및 숙련주차 주어졌던 강의 학습 및 복습

    4. 참고자료

    5. 듣고싶은 강의

    반응형
    COMMENT
     
    02
    07

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 31일차

    부분진행도 : Chapter4.1 - 4일차

    작성일자 : 2024.02.06(화)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    내일 정오까지 개인과제를 제출해야 한다.

    시간이 얼마 없지만, 그래도 강의의 '이해'는 해야 된다고 생각하기 때문에 최대한 들으며 이해를 하고, 몇몇 포인트마다(슬슬 필요할 때마다) 자체 코드리뷰 시간을 가지기로 했다.

    이렇게 하여 강의를 모두 끝내지 못했을 경우, 저녁을 먹은 후 오후 7시에 과제에 진입한다.

    세부 시간 계획 및 실천사항은 아래에 작성.

    오늘은 시간에 쫓기는 상황이니만큼 Today I Learned 이라기보다 계획 및 실천사항에 중점을 두었다.

    2. 오늘 학습에 대해

    • 01시 ~ 03시 단기 목표, 7/13 인벤토리 강의를 마치고, 모든 스크립트에 대해 코드리뷰를 한다.
      • 02:45 7강 수강 완료, 현재 Damagable 관련 스크립트 세 개만 확인하면 일단 전체적인 구성은 파악한 것 같다.
      • DamageIndicator는 코루틴을 사용한다는 점 빼고는 어려운 점이 없다. 완료.
      • Campfire와 InteractionManager 을 확인하자.
      • private List<IDamagable> thingsToDamage = new List<IDamagable>(); IDamagable 인터페이스를 구현한 모든 객체를 포함
      • 03:05 1차 코드리뷰 완료.
    • 03시 ~ 05시 단기 목표, 8/13 아이템 장착 및 모션 강의를 마치고, 코드리뷰가 필요한지 결정한다. 분량이 많다.
      • 5시정도에 딱 맞추어 끝냈다. 흐름은 어떻게 알 것 같아서 코드리뷰는 추가로 하지 않았다.
    • 오전 5:40, 11/13강을 시작했다. 플레이어 인벤토리 이후는 난이도가 무척 할만해지고 내용도 매우 흥미로워 열심히 따라 배우는 중이다. 다시 한 강에 50분짜리로 분량이 꽤 되는 '적 생성과 로직' 파트이다. 지금까지의 흐름으로 보면 최소 두시간은 걸릴 것 같다.
    • 오전 8:00까지 취침 후, 오전 10시까지 11강 완주 목표. 달성한다면 오전 11시까지 13강 완주를 할 수 있을 것 같다.
    • 위 내용을 지키지 못하고 많이 쉼. 저녁 6:55, 12/13까지 완료하였다.
    • 짧고 효과 좋은 가성비 최강 포스트 프로세싱. Bloom 효과를 적용하였다.

    Bloom 효과를 적용한 카메라

    • 8:40 자료구조 관련 세션이 있었다.
      • 여러 상황에 맞게 Stack과 Queue, 배열과 리스트와 딕셔너리를 사용하면 좋다는 내용이었다.
      • 여러 장면이나 패널을 순차적으로 열고 닫아야 할 때는 Stack을 사용하면 좋을지도 모르고
      • 오브젝트 풀에는 Queue를 사용할 수도 있다.
      • 인벤토리 내 아이템을 표시하는 경우는 경우에 따라 다르지만 상황이 괜찮다면 딕셔너리를 사용하는 것이 계산복잡도 측면에서 좋다.
    • 마지막 13/13강인 오디오 파트는 잠시 내려두고 과제 제출 이후에 이어서 하기로 했다.

    Random 사용 시 오류(빨간 밑줄)가 나는 경우

    Random을 사용하려고 보니 에러 발생

    원인 : using System과 using UnityEngine 양 쪽에서 Random 클래스를 가지고 있기 때문에 충돌
    해결1. using System; 을 지운다.
    해결2. (채택) Random 대신 UnityEngine.Random 이라고 표기한다.

    3. 과제에 대해

    • 밤샘작업으로 아침 10시까지 개인과제 제출하기

    4. 참고자료

    5. GPT4 문답

    반응형
    COMMENT
     
    02
    05

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 30일차

    부분진행도 : Chapter4.1 - 3일차

    작성일자 : 2024.02.05(월)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    강의지급 및 개인과제 3/5일차, 서바이벌 3D게임 강의를 학습중이고, 개인과제는 UI구성까지만 마치고 스크립트 작성을 보류중이다. 슬슬 밤샘각이 보인다. 강의가 어렵지만 굉장히 멋진 구조의 디자인을 하고 있어 보이기 때문에 확실히 학습하면 굉장히 도움이 될 것이다.

    + 오후에 핫식스 도핑하면서 버티던 도중에 눈이 번득 뜨이는 이벤트가 발생했다.

    갑자기 분위기 우수 TIL(Today I Learned)

    일단 개발일지 목록이 업데이트가 덜 되어 있어서 호다닥 작성했지만 나머지는...

    더보기
    막 3일전 질러놓은 게임글
    NSFW 프로젝트
    유익하지만 음원소스가 서브컬쳐
    가장 최근 글이 방주 관리 프로젝트
    최고 인기글 제목도 부끄러움
    도메인도 부끄러움

    이쯤 되면 그냥 당당해지기로 했다

    2. 오늘 학습에 대해

    아침 CodeSolve

    바쁘더라도 한 문제 정도는 30분정도 써서 풀어도 괜찮은 것 같다.

    다른 날과 마찬가지로 주석으로 상세 내용을 정리한다.

    전엔 하지 않았던, 솔루션을 미리 작성해두고 과정을 따라가는 방식을 해 보니 괜찮은 것 같다.

    코딩테스트 연습 > 2022 KAKAO BLIND RECRUITMENT > 신고 결과 받기

    using System;
    using System.Collections.Generic;
    
    public class Solution {
        public int[] solution(string[] id_list, string[] report, int k) {
            int[] answer = new int[id_list.Length];
    
            // 솔루션
            // Dict1 : {"{ID}":{받을 메시지 수}}
            // Dict2 : {"{ID}":{List<string> ID를 신고한사람 목록}}
            // 1. Dict1과 Dict2를 초기화
            // 2. foreach문으로 report 순회하며 Dict2를 채운다
            // 3. Dict2를 순회하며 List의 길이가 k 이상일 경우,
            //    해당 리스트를 키로 갖는 Dict1의 값을 모두 1 더한다
    
            // 1. Dict1과 Dict2를 초기화
            // (Dictionary 안의 자료형으로 List<> 그냥 써 봤는데 왜 되는거야...)
            Dictionary<string, int> dict1 = new Dictionary<string, int>();
            Dictionary<string, List<string>> dict2 = new Dictionary<string, List<string>>();
            foreach(string id in id_list){
                dict1[id] = 0;
                dict2[id] = new List<string>(){};
                // Console.WriteLine(dict2[id].Count);
            }
    
            // 2. foreach문으로 report 순회하며 Dict2를 채운다
            foreach(string msg in report){
                string[] parts = msg.Split(' ');
                string userA = parts[0];
                string userB = parts[1];
                if(!dict2[userB].Contains(userA))
                    dict2[userB].Add(userA);
            }
    
            // 3. Dict2를 순회하며 List의 길이가 k 이상일 경우,
            //    해당 리스트를 키로 갖는 Dict1의 값을 모두 1 더한다
            // 찾아보기: 사전형의 순회
            foreach(var item in dict2){
                if(item.Value.Count>=k){
                    foreach(string user in item.Value){
                        dict1[user] += 1;
                    }
                }
            }
    
            // 4. answer 배열에 dict1의 내용 옮기기
            for(int i=0;i<id_list.Length;i++){
                answer[i] = dict1[id_list[i]];
            }
    
            return answer;
        }
    }
    • Dictionary 안의 자료형으로 제네릭 (예:List<>) 을 사용 해 보았다.
      • Dictionary<string, List<string>> dict2 = new Dictionary<string, List<string>>();
    • 사전형의 순회법
      • foreach(var item in dict2){ //Item.Key나 Item.Value로 접근 }

    3. 과제에 대해

    - 주어진 강의 흡수(남은 게 많다. 큰일. 오늘은 밤샘이다. 그래도 방향성은 잡힌 것 같다.)

    - 개인과제 스크립트 부분 이어서 착수

    반응형
    COMMENT
     
    02
    02

    FileFlattener-and-Restorer 깃허브 리포지토리

    방주 파일을 다루는데, 복잡한 디렉터리 구조에 퍼져있는 모든 파일을 하나의 앨범에 모으기 위해 작성한 스크립트이다.

    • flatten_and_move.py

    역으로, 모았던 파일을 다시 원래 위치로 복원하기 위한 스크립트도 마련하였다.

    • restore_files.py

    현재 폴더의 구분자를 _문자로 설정하여 새로운 파일 이름을 정하고 한 폴더에 몰아두는 방식을 채택했는데, 원래의 파일 이름에 _ 문자가 있었다면 원래 경로로 복원하는 과정에서 큰 문제가 된다.

    flatten_and_move 사용 시 로그 파일을 남기고, 그걸 사용하여 복원하는 방식으로 바꾸어야 해결 할 수 있을 것으로 보이고 조만간 업데이트 할 예정이다.

    아래는 2024.02.02 에 작성된 README.md 의 내용이다.

    FileFlattener-and-Restorer

    이 프로젝트는 다양한 경로에 퍼져있는 파일들을 단순화하고 정리하는 파이썬 스크립트를 제공합니다. 스크립트는 파일 이름을 변경하고, 지정된 출력 디렉토리로 파일을 이동시키며, 작업 로그를 기록합니다.
    또한 원래 경로로 복원이 가능한 스크립트를 제공합니다.

    기능

    • 파일 평탄화 및 이동: 지정된 디렉토리 내의 모든 파일을 스캔하고, 파일 이름을 변경하여 지정된 출력 디렉토리로 이동시킵니다.
    • 원본 경로 복원: 변경된 파일 이름을 사용하여 원본 디렉토리 구조로 파일을 복원합니다.
    • 로그 기록: 모든 작업에 대한 로그를 Logs 디렉토리에 기록합니다.

    사용 방법

    ▷ flatten,move ▷

    ▷ restore ▷

    이 리포지토리를 클론하거나 직접 압축파일을 다운로드 받아 파일정리를 원하는 곳으로 위치시킨 후에 실행시켜 사용합니다.

    폴더 경로의 구분자() 를 언더바(_)로 치환하여 바뀌어질 파일이름으로 사용하기 때문에

    원래의 파일명에 언더바가 섞여있는 경우 오작동을 일으킬 가능성이 매우 크며, 특히 원래 경로로 복원이 어렵습니다!!!

    (현재 구현하지는 않았으나, 로그파일을 참조하는 방식으로 위 문제를 해결 할 수 있을 것으로 보입니다)

    image

    위와 같이 해당 폴더의 주소창에 cmd를 입력하여 명령 프롬프트를 실행합니다.

    파일 평탄화 및 이동

    flatten_and_move.py 스크립트를 실행하여, 현재 디렉토리 및 하위 디렉토리에 있는 모든 파일을 flatten 디렉토리로 이동시키고 이름을 변경합니다.

    python flatten_and_move.py

    원본 경로로 파일 복원

    restore_files.py 스크립트를 실행하여, flatten 디렉토리에 있는 파일을 원래의 디렉토리 구조로 복원합니다.

    python restore_files.py

    기여 방법

    풀 리퀘스트 또는 이슈 등록 환영합니다.

    반응형
    COMMENT
     
    02
    02

    과정명 : 내일배움캠프 Unity 게임개발 3기

    전체진행도 : 29일차

    부분진행도 : Chapter4.1 - 2일차

    작성일자 : 2024.02.02(금)

    개발일지 목록 : 클릭


    1. 진행중인 과정에 대해

    오는 주 수요일까지, 개인과제 및 지급된 강의를 흡수하고 있다.

    우선 지급된 유티니 3D 프로젝트 강의를 보고 있는데, 보면서 조금이라도 의문이 드는 점은 매번 찾아 주석으로 남기고 있기 때문에, 무척 시간이 지체되고 있다.

    대충 이런 느낌으로 주석을 작성해가며 진행중

    주말도 열심히 활용해서 진도를 빼야 될 것 같다.

    2일차인데 과제까지 다 끝냈다는 수강생들도 많다는 게 괴담이다.

    2. 오늘 학습에 대해

    인코딩 문제 해결

    유니티 강의를 들으며 기능 구현을 할 때마다 커밋을 하며 진행중인데, 잠깐 지나치며 File Changes 내용을 보니 아래와 같이 인코딩 문제가 있었다.

    한글로 작성한 부분이 Github Desktop엥서 깨져보인다.

    유니티 프로젝트를 시작할 때 아래와 같은 에디터 설정을 해 주었어야 했는데 잊고있었다.

    프로젝트 루트 폴더에 .editorconfig 파일 마련

    .sin 폴더가 있는 루트 폴더에 위와 같은 내용을 가진 .editorconfig 파일을 마련해주고, 스크립트 파일을 다시 저장(Ctrl+S) 해 주면 해결이지만

    Github Desktop에서 파일 Changes를 확인 할 수 있다

    기능적으로 바뀐 부분 이외에 한글 주석을 달았던 부분이 모두 바뀌기 때문에 커밋 내용이 지저분해진다.

    가능한 빠른 시점에 .editorconfig 파일을 마련하도록 하는 것이 좋다.

    Code Solve

    매 문제를 풀 때마다 검색을 다섯 번 이상 한다. 마찬가지로 주석부분에 내용을 정리하였다.

    코딩테스트 연습 > 연습문제 > 공원 산책

    using System;
    using System.Collections.Generic;
    
    public class Solution {
        public int[] solution(string[] park, string[] routes) {
            int[] answer = new int[2];
    
            // 솔루션 : 주어진 내용을 정말 그대로 수행만 하면 될 것으로 보임
            // 0-1. NSWE의 튜플값 마련
            // 1. park를 한차례 순회하며(최대 2500회) S의 위치 찾기
            // 2. routes의 원소를 foreach순회
            // 2-1. 현재자리 기억
            // 2-2. for 반복문으로 0-1에서 마련한 튜플값만큼 이동 
            // 2-2-1. 이동 불가조건 만족 시 원래자리로 복귀
            // 3. 현재 자리(index) 반환
    
            // 0-1. NSWE의 튜플값 마련
            // 찾아보기. 제네릭으로 튜플값 사용하는 방법
            Dictionary<char,(int X,int Y)> going = new Dictionary<char, (int, int)>(){
                {'N',(0,-1)}, // (x, y) 순
                {'S',(0,1)},
                {'W',(-1,0)},
                {'E',(1,0)}
            };
            // 1. park를 한차례 순회하며(최대 2500회) S의 위치 찾기
            // 찾아보기. 튜플 변수 선언과 초기화
            // 찾아보기. (int, int) index와 같이 사용하는것은 불가능
            //          (int X, int Y) 로 수정
            //          이후 코드에서도 Item1 -> X, Item2 -> Y로 수정
            (int X, int Y) index = (-1,-1);
            for(int y=0;y<park.Length;y++)
                for(int x=0;x<park[0].Length;x++)
                    if(park[y][x]=='S'){
                        index = (x,y);
                        x = park[0].Length;
                        y = park.Length;
                    }
            // 2. routes의 원소를 foreach순회
            foreach(string directionInfo in routes){
                // 찾아보기: char로의 형변환
                char direction = char.Parse(directionInfo.Split(' ')[0]);
                int moveNum = int.Parse(directionInfo.Split(' ')[1]);
                // 2-1. 현재자리 기억
                // 찾아보기: 튜플값은 값 형식으로 다른 튜플에 할당하면 내용복사
                (int X, int Y) preIndex = index;
                // 2-2. for 반복문으로 0-1에서 마련한 튜플값만큼 이동 
                for(int i=0;i<moveNum;i++){
                    // 찾아보기: 튜플은 아래와 같이 +=는 사용 할 수 없다.
                    //index += going[direction];
                    index = (index.X + going[direction].X, index.Y + going[direction].Y);
                    // 2-2-1. 이동 불가조건 만족 시 원래자리로 복귀
                    // 찾아보기: 튜플 요소에 접근
                    if(
                        index.X<0 ||
                        index.Y<0 ||
                        index.X>= park[0].Length ||
                        index.Y>= park.Length
                    ){
                        index = preIndex;
                        break;
                    }
                    else if(park[index.Item2][index.Item1] == 'X'){
                        index = preIndex;
                        break;
                    }
                    // 이동 확인 구문
                    // Console.WriteLine($"{i}:({index.X}, {index.Y})");
                }
            }
    
            // 3. 현재 자리(index) 반환
            // 아래 구문은 왠지 잘 되지 않음.
            // (answer[0], answer[1]) = index;
            // 배열의 인덱스 위치에 직접 값을 할당하는 형태는 
            // 지원이 되는경우도 있고 안되는 경우도 있다는 듯
            answer[0] = index.Y;
            answer[1] = index.X;
    
            return answer;
        }
    }
    • 제네릭 형태로 튜플 값을 사용
      • 처음 시도 해 본 내용인데, 이게 되네 싶어서 놀랐다.
      • Dictionary<char,(int X,int Y)> going = new Dictionary<char, (int, int)>();
    • 튜플 변수
      • 마찬가지로 튜플 변수라는 것도 처음 사용 해 보았다. 배우거나 찾아본 거 없이 적은 구문이 맞는 구문이라 놀랐다..
      • (int, int) index = ... 형태는 C# 7.0 버전 이상에서 사용할 수 있다고 하고, 프로그래머스의 컴파일러도 이를 만족하지만 어째서인지 되지 않았다. 대신 아래와 같은 형태는 사용 가능했다.
      • (int X, int Y) index = ... 는 사용 가능. index.X 와 같이 사용 가능
      • 위와 같은 경우 값 참조이기 때문에, (int X, int Y) preIndex = index; 의 경우 값이 복사되며 두 튜플은 별개로 작동한다.
      • 튜플끼리 덧셈 연산자는 사용할 수 없다. index += going[direction];
      • 튜플 내부 변수명으로도 튜플 내의 값을 사용할 수도 있지만 .Item1, .Item2... 로도 사용 가능하다.
    • 한 글자로 된 문자열의 char 로의 형 변환
      • 왠지 사용했던 기억이 없어 익숙하지 않아 찾아보았다.
      • char direction = char.Parse("C"); 와 같이 char.Parse()를 사용 가능하고, "C"[0]과 같이 사용도 가능하다.

    3. 과제에 대해

    • 강의 흡수 및 개인 과제 수행(남은시간 주말 포함 5일)
    반응형
    COMMENT
     
    02
    02

    복귀 한 건 아니지만 오랫만에 통계 사이트에서 내 캐릭터를 확인 해 보았다.

    1년 반 정도 전 기점으로 활동을 하지 않아 업적점수는 동결중

    당시 시점에는 월드 랭킹 2위를 한동안 유지했었다.

    현재 15위 Ecchi Clone. 2년 전 당시에도 자주 보였던 닉네임들이 보인다.

    파판을 접은 동안 랭킹이 많이 떨어졌을 줄 알았는데, 아직 서버 15위에 위치중이다.

    Aegis 월드 순위권 점수

    현재 1위의 점수는 2만 6천점 정도이다. 모르는 닉네임인 걸 보면 단시간에 빡세게 올린 것으로 예상된다.

    당시 컨텐츠도 같이 했던 모모무츠상(전 1위), 타마토라상(전 3위), Kp상은 꾸준히 게임 하는 듯.

     

    복귀 하면 그 동안 쌓인 컨텐츠에서 뽑아먹을 게 정말 많아서 점수를 쭉쭉 올릴 수 있지 않을까 싶다.

    분신

    미코테 귀엽다

    반응형

    'Game > FFXIV' 카테고리의 다른 글

    [FFXIV] Aegis서버 업적 점수 재활? 기록  (0) 2025.04.02
    [FFXIV] 탐험수첩 18번  (0) 2018.07.27
    [FFXIV] 탐험수첩 3번  (0) 2018.07.27
    [FFXIV] 탐험수첩 9번  (0) 2018.07.27
    [FFXIV] 탐험수첩 19번  (0) 2018.07.26
    COMMENT
     
    02
    02

    개요

    AlphaSlayer1964/kemono-dl

    kemono.su / coomer.su 에서 쉽게 일괄 다운로드를 할 수 있게 해 주는 파이썬 프로젝트이다.

    예전에 로컬에 Clone해서 사용하고 있었던 이게 오랫만에 쓰려고 보니 작동하지 않아, 여러번의 시행착오를 거쳐 잘 작동하도록 수정하였다.

    해당 깃허브 리파지토리의 Issues 목록을 확인 해 보니 역시 관련된 문제를 제기하는 유저들이 많았다.

    해결한 내용을 혼자만 알고 있기 아까워 처음으로 다른 개발자의 프로젝트를 손대보았다.

    사실 '오픈소스 프로젝트에 참여한다'는 게 어떤 행동까지 포함되는지 잘 알지 못하는데, 해당 프로젝트의 원래 개발자가 이 프로젝트를 public으로 던져두고 2년간 잠적한 상태라서 외부 개발자의 PR이 10개 가까이 쌓여있고, 마찬가지로 내가 수정한 코드가 반영 될 일은 없을 것 같다. 이걸 오픈소스 프로젝트라고 할 수 있을지는 잘 모르겠다.

    그래도 PR을 올려두면 다른 유저들도 수정사항을 조회 할 수 있기 때문에 의미없는 행동은 아닐 것이라고 생각한다.

    프로젝트 참여 과정

    해당 리포지토리의 우측 상단에서 Fork 기능을 사용하여 나의 리포지토리 목록에 해당 프로젝트를 복사 해 온다.

    정상적으로 Fork하였다면, 아래와 같이 새로운 리포지토리가 생성되어있고, forked from ... 의 메시지도 확인 할 수 있다.

    새로 생긴 리포지토리를 로컬에 Clone 하여 샥샥 수정 후 Commit과 Push를 하면 내 깃허브 리포지토리에 반영이 되는데

    내 리포지토리에서 Pull requests를 누르면 위와 같이 Fork했던 기존 프로젝트에 Pull Request를 할 수 있다.

    PR 메시지를 작성 후 올려두면, 아래와 같이 기존 프로젝트의 Pull Requests 목록에 올려진 것을 확인 할 수 있다.

    문제가 되었던 내용

    1. Kemono와 Coomer의 도메인 변경
    2. Kemono와 Coomer의 API 주소 변경
    3. Datetime - API 서버에서 반환되는 날짜 및 시간 문자열의 형식이 ISO 8601로 조정됨
    4. Datetime - 정수 및 문자열 데이터 타입의 혼동. 일부 데이터의 전달이 문자열(str) 타입에서 정수(int) 타입으로 바뀜

    Kemono와 Coomer의 도메인 변경

    두 서비스의 도메인이 kemono.party 와 coomer.party 에서 kemono.su 와 coomer.su 로 바뀌었다.

    세개 정도 소스코드에서 '.party'를 '.su' 문자열로 모두 찾아바꾸는 것으로 해결하였는데, 이 부분은 운좋게 해결 된 감이 없지않다.

    Kemono와 Coomer의 API 주소 변경

    기존에 요청을 보내던 API 주소가 제대로 응답을 주지 않았다. 설마 요청할 API의 주소가 바뀌었을 것이라고는 예상하기 어려울 것 같다.

    브라우저 창에서 기존에 요청하던 주소인 https://coomer.su/api/creators/ 에 접속 해 보아도 Not Found 를 받아오는 것을 보고 해당 주소의 파일구조를 확인 해 봐야겠다고 생각했다.

    루트 경로인 coomer.su 에서 개발자 도구를 통해 api로 향하는 파일구조를 확인할 수 있을 줄 알았지만, 찾아보니 이러한 방법으로는 구조를 확인 할 수 없다고 한다. coomer에서 api의 가이드를 해 주지 않는다면 알아내는 것은 어렵다고 한다.

    구글 검색을 하던 중, coomer가 제공하는 API 가이드를 발견하였다. 정말 기대조차 못했던 수확이다.

    확인 해 보니 아무래도 coomer는 API의 개선을 진행하고 있는 듯 하다. 기존 사용하던 API는 주소 뒤에 /v1라는 경로가 추가되어 있는 것을 확인했다.

    즉 소스코드에 쓰이고 있던 경로 문자열에서 .../api/....../api/v1/...로 바꿔주면 되었고, 모든 경로를 찾아 바꿔 해결 할 수 있었다.

    Datetime 관련 문제

    날짜에 관련된 문자열 처리 과정에서 문제가 있었다. 갈피를 잡지 못해 ChatGPT에게 소스코드를 보여주며 원인을 찾아보도록 하였는데, GPT는 API에 직접 접근하지 못하기 때문에 방향을 제시 해 주는 정도였다.

    입력으로 주는 날짜 정보 등을 출력해가며 이를 함께 제시 해 주니, 원인을 찾을 수 있었다.

    날짜 및 시간 형식의 불일치: API 서버의 주소 변경으로 인해 반환되는 날짜 및 시간 문자열의 형식이 ISO 8601로 조정되었습니다. 기존 코드는 특정 형식(예: %a, %d %b %Y %H:%M:%S %Z)을 기대했으나, API의 조정으로 인해 이 형식이 변경되었고, 이로 인해 기존의 datetime.strptime 함수로는 새로운 형식의 날짜 및 시간 문자열을 올바르게 파싱할 수 없게 되었습니다.

    즉 예전과는 다른 날짜형식을 API가 반환하고 있기 때문에 파싱 과정에서 문제가 되었다는 내용.

    coomer의 입장에서 보면 standard에 가까운 형식으로 반환하도록 수정한 것이기 때문에 방향성으로는 올바른 것 같다.

    그래서 문제가 된 것은, datetime.strptime함수로 새로운 형식의 날짜 및 시간 문자열을 올바르게 파싱할 수 없게 된 것이다.

    ISO 8601 형식에 대응 할 수 있도록 새로운 함수 parse_date_string를 마련하였다. 해당 함수는 여러 날짜 형식을 시도하고, 올바르게 파싱할 수 있는 형식을 찾으면 해당 형식으로 날짜 및 시간 문자열을 처리한다.

    또한, 문자열 타입(str)의 인자를 전달해야 하는 곳에 정수형 변수(int)가 전달되는 문제도 생겨, 필요한 경우 문자열로 변환하는 로직을 추가하였다.

    (위 작성한 내용의 절반 이상이 날아가 다시 작성함.. ㅠㅠ)

    Pull Request

    모든 것을 마치고 아래와 같이 PR을 작성하였다.

    다른 개발자의 프로젝트에 리퀘스트를 넣어보는 것은 처음이기도 하고 열심히 작성 해 보았다.

    반응형
    COMMENT