반응형

1. 오늘 학습 키워드

Unity, Card 시스템, 애니메이션 제한, 클릭 제한, Git 협업, Detached HEAD, ScriptableObject 개념, Update 주기, GC, 캡슐화


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

 

오전에는 컴퓨터 사이언스 관련 기초 개념을 정리했다.

  • Unity에서의 Update, FixedUpdate, LateUpdate 주기 차이를 이해하고
  • 객체지향 원칙 중 하나인 **캡슐화(Encapsulation)**에 대해 복습했다.
  • C#에서 **GC(Garbage Collector)**의 동작 조건과 실행 시점도 정리했으며,
  • 값 형식과 참조 형식의 차이를 통해 메모리 구조와 호출 방식을 구분했다.

또한 C#의 박싱(Boxing)과 언박싱(Unboxing) 개념을 실습하며 성능 이슈를 확인했고,
컬렉션 구조인 Hashtable과 Dictionary의 차이점, 제네릭 사용 여부, 검색 속도 특성 등도 비교하며 학습했다.

 

오후는 Unity 팀 프로젝트에서 카드 시스템을 다듬는 데 집중했다.

카드가 애니메이션 중일 때 다른 카드가 클릭되지 않도록 static bool canClick을 사용해 클릭 제한 로직을 구현했고, 카드 2장까지만 열리고 3번째 카드를 클릭하면 기존 2장을 자동으로 닫는 방식으로 OpenCard() 로직도 수정했다.

GitHub Desktop에서 Detached HEAD 상태에 빠졌을 때 브랜치로 다시 Checkout하는 방법도 익혔고, Publish branch 버튼이 비활성화되는 이유와 해결 방법도 이해하게 되었다.

중간에 폭탄 카드(idx == -1) 처리를 시도했지만, Sprite 대신 프리팹이 들어있는 구조라서 일단 내일 다시 시도하기로 했다.

또한 ScriptableObject가 뭔지, 어떤 구조로 활용되는지 예제를 통해 개념적으로 정리했다.

 

팀 프로젝트

  • 2장씩 넘어가게 (나머지는 닫힘) (완료)
  • 카드 애니메이션 제작 (완료)
  • 카드 기본 이미지 꾸미기 (완료)
  • 성공했을떄 UI Particle 추가 (완료)

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

🔸 정의

  • 카드 애니메이션 중 다른 카드가 눌리는 문제
  • GitHub에서 Publish 버튼이 비활성화되고 Detached HEAD 상태가 나타남

🔸 시도

  • canClick bool 변수를 통해 클릭 제한 제어
  • Invoke()로 애니메이션 후 다시 클릭 가능하게 함
  • GitHub 브랜치 상태 및 Checkout 관련 메뉴 확인

🔸 해결 방법

  • OpenCard()에 canClick 조건 추가
  • Invoke("EnableClick", 0.6f) 방식으로 타이밍 제어
  • 브랜치 복귀하여 정상적인 상태로 되돌림

🔸 새롭게 알게 된 점

  • Detached HEAD는 브랜치가 아닌 커밋만 보고 있는 상태이며, 이 상태에선 커밋을 푸시할 수 없음
  • ScriptableObject는 게임 데이터 저장 및 재사용에 유용한 구조이며, 코드와 데이터를 분리할 수 있음

🔸 다시 만나게 된다면?

  • 애니메이션이 끝나는 정확한 시점을 Animation Event로 관리하면 더 안정적일 것
  • Git 상태는 항상 브랜치 이름과 History를 먼저 확인하고 작업할 것

4. 내일 학습 할 것

CS 지식, 팀 프로젝트 나머지 보완 문제


5. 메모

스택 - 정적으로 메모리에 할당. (후입선출, LIFO)

힙 - 동적으로 메모리에 할당. (선입선출, FIFO) (GC가 이 영역의 사용되지 않는 데이터들을 소멸시킴 - 언제?)

value type(값 형식) - 데이터를 메모리의 스택영역에 할당. 스택 메모리 공간에 (값)을 가지고 있다.

reference type(참조 형식) - 데이터를 힙영역에 할당. 스택 메모리 공간에(주소)를 가지고 있다. (그럼 데이터는 힙에있고 스택에는 주소값만?)

박싱 - 값 형식을 참조 형식으로 변환하는 것. 스택에 있는 값을 복사하여 힙에 할당한다.

언박싱 - 박싱했던 값을 다시 원상태로 복귀 시키는 것. 힙에 있던 데이터를 스택으로 복사한다. 힙에 가비지가 쌓이게 된다.(언제?)

해시테이블도 키값으로 값을 찾음 - 딕셔너리(상위호환)

해시테이블은 사용할때 언박싱을 해줘야한다. - 오? - 딕셔너리는 필요없음

최대기반의 GC컬렉터 - 마크 1,2,3 세대가 오래될수록 --

 

팀프로젝트 중 오류 - 즐거웠다

    public void Setting(int number)
    {
        idx = number;
        frontImage.sprite = Resources.Load<Sprite>($"Team_{idx}");

        if (frontImage.sprite != null)
        {
            frontImage.transform.localScale = Vector3.one;

            float spriteWidth = frontImage.sprite.bounds.size.x;
            float spriteHeight = frontImage.sprite.bounds.size.y;

            float targetWidth = 0.8f;
            float targetHeight = 1f;

            float scaleX = targetWidth / spriteWidth;
            float scaleY = targetHeight / spriteHeight;

            frontImage.transform.localScale = new Vector3(scaleX, scaleY, 1f);
        }
    }

카드 스크립트중 셋팅값에서 카드가 자꾸 이상하게 스케일이 커지고 작아지는 문제가 있었다. 그래서 이것저것 건드려보고 애니메이션에서도 스케일값을 수정해봤는데 이상했었다. 근데이제 진원님이 만드신 CardMover라는 코드에서 카드의 초기 스케일값과 마지막 스케일값을 조정하는 변수를 발견했다!! 이걸 발견하기전에는 카드값이 제각각으로 막 커지고 작아졌었는데 이 값을 수정하니 완벽하게 됐다.

이 과정을 겪으며 카드가 이상하게 스케일값이 왔다갔다하며 화면을 팀원들과 같이 봤었는데 다들 왜이렇게 되냐며 즐거웠다ㅋㅋㅋ 이렇게 팀프로젝트를 진행하며 재밌는 경험도하고 같이 웃으며 팀 프로젝트를 진행하니 나도 즐거웠다!!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class CardMover : MonoBehaviour
{
    public Card _card = null;

    [Header("카드 이동 시간 / 카드 딜레이 시간")]
    public float moveDuration = 0.5f;           // 이동 시간
    public float delayBetween = 0.1f;           // 딜레이 시간

    [Header("이동 타입")]
    public Ease moveEase = Ease.OutBack;        // 이동 타입

    [Header("카드의 초기 크기 ~ 최종 크기")]
    public Vector3 startScale = Vector3.zero;   // 시작 스케일
    public Vector3 endScale = Vector3.one;      // 끝 스케일

    public void Show(Vector2 vec_TargetPos, Card card, int index)
    {
        if (_card != null) return;
        _card = card;

        Transform tf = _card.transform;

        // 초기화
        tf.localPosition = Vector3.zero;
        tf.localScale = startScale;

        float delay = delayBetween * index;

        // 로컬 위치 이동
        tf
          .DOLocalMove(vec_TargetPos, moveDuration)
          .SetDelay(delay)
          .SetEase(moveEase);

        // 스케일 애니메이션
        tf
          .DOScale(endScale, moveDuration)
          .SetDelay(delay)
          .SetEase(moveEase);
    }

    private void OnDisable()
    {
        _card = null;
    }
}

결정적인 CardMover의 스크립트였다.


오늘 오전에 공부한 내용

https://dev-jen.tistory.com/entry/C-Unity-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%ED%84%B0GC

 

C# Unity - 가비지 컬렉터(GC) 자동실행기준

✅ 가비지 컬렉터(GC)의 역할이란?더 이상 사용되지 않는 힙의 메모리를 자동으로 찾아서 정리해주는 시스템즉,메모리 누수 방지수동으로 메모리 해제하지 않아도 됨 (delete, free 필요 없음)✅ GC

dev-jen.tistory.com

https://dev-jen.tistory.com/entry/C-%EB%B0%95%EC%8B%B1%EC%96%B8%EB%B0%95%EC%8B%B1%EA%B3%BC-%EB%B0%95%EC%8B%B1%EC%96%B8%EB%B0%95%EC%8B%B1%ED%98%95%EB%B3%80%ED%99%98-%EC%B0%A8%EC%9D%B4

 

C# - 박싱/언박싱과 박싱/언박싱&형변환 차이

✅ 박싱(Boxing) & 언박싱(Unboxing)🔸 박싱(Boxing)값 형식(Value Type) 데이터를 **참조 형식(Reference Type)**으로 변환하는 것값 타입(예: int, float)을 object 타입에 저장하면 박싱이 발생이 과정에서 값이 힙

dev-jen.tistory.com

https://dev-jen.tistory.com/entry/C-%EC%BA%A1%EC%8A%90%ED%99%94

 

C# - 캡슐화

✅ 캡슐화(Encapsulation)란?"객체의 내부 상태(데이터)를 외부로부터 숨기고, 허용된 방식으로만 접근하도록 제한하는 것."✅ 핵심 요약항목설명목적데이터를 보호하고, 잘못된 접근/수정을 방지수

dev-jen.tistory.com

https://dev-jen.tistory.com/entry/Unity-Update-FixedUpdate-LateUpdate

 

Unity - Update(), FixedUpdate(), LateUpdate()

✅ Unity의 3가지 주요 루프 함수함수 이름실행 주기용도특징Update()매 프레임마다사용자 입력, 일반 로직프레임 속도에 따라 실행 빈도 달라짐 (가변)FixedUpdate()고정 시간 간격마다물리 연산 (Rigidb

dev-jen.tistory.com

https://dev-jen.tistory.com/entry/C-NET-Runtime

 

C# - .NET Runtime

✅ .NET 런타임이란?.NET Runtime은 C#, F#, VB.NET 같은 **.NET 언어로 만든 프로그램을 실행해주는 "실행 환경(엔진)"**이야.다시 말해, .NET 코드가 컴퓨터에서 실제로 돌아가도록 도와주는 핵심 소프트웨

dev-jen.tistory.com

 

반응형