TIL

[멋쟁이사자처럼 부트캠프 TIL회고] 66일차 : 연휴 끝

Cadi 2025. 2. 3. 16:57

오늘 배운 것

1. 필요한 개념 간단 복습

2. PopUpPanel (재활용 가능한)

3. TicTacToe 계획

 

 

개념 간단 복습

 

재미있는 게임을 최적화 하는 것은 최적화 된 게임을 재미있게 만드는 것보다 쉽다.

 

즉 , 일단 여러개의 게임을 만들어보자 ! 

 

1. 구조체와 클래스

 

구조체

  • 값 타입, 스택(Stack) 메모리에 저장, 객체 복사할 때 값이 복사 (깊은 복사)
  • 상속 불가능
  • 주로 초기화 후 변경이 없는 데이터 집합을 표현할 때 사용

클래스

  • 참조 타입, 힙(Heap) 메모리에 저장, 객체 복사할 때 참조가 복사 (얕은 복사)
  • 상속 가능
  • 주로 초기화 후 변경이 있는 데이터 집합을 표현할 때 사용

2. 재귀 함수

  • 함수가 자기 자신을 호출하는 프로그래밍 기법
  • 큰 문제를 동일한 형태의 작은 문제로 나누어 해결하는 방법
  • 복잡한 문제를 단순하고 쉬운 코드로 표현 가능
  • 트리, 그래프 등의 자료 구조에서 사용
void RecursiveFunction(int count)
{
    if (count <= 0)
    {
        Debug.Log("종료");
        return;
    }
    
    Debug.Log("count: "+ count);
    RecursiveFunction(count - 1);
}

 

3. 상속

  • 부모로 지정한 클래스의 멤버를 상속 받아 자식 클래스에서 동이랗게 사용할 수 있는 형태

 

class 부모클래스
{
// 필드, 속성, 메서드 정의
}
class 자식클래스 : 부모클래스
{
// 부모 클래스의 멤버를 상속받음
}

 

타입 캐스팅

 

  • 업캐스팅(Upcasting) : 자식 객체를 부모 타입으로 변환(자동 변환)
  • 다운캐스팅(Downcastin) : 부모 타입의 객체를 다시 자식 타입으로 변환(명시적 변환 필요)

캐스팅 방법

  • as 키워드 : 안전한 키워드, 실패시 null 변환
  • is 키워드 : 타입 체크 후 캐스팅 수행

업캐스팅의 예

class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Some animal sound...");
}
}
class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Woof! Woof!");
}
}
Animal animal = new Dog(); // ✅ 업캐스팅
animal.MakeSound(); // 출력: Woof! Woof!

 

  • 자식 클래스의 객체를 부모 클래스 타입으로 참조하는 것
  • Dog 객체를 Animal 타입의 변수에 저장하는 것처럼, 자식 클래스의 인스턴스를 부모 타입으로 변환하는 것
  • 이렇게 업캐스팅을하면 animal 변수는 Dog의 인스턴스를 참조하지만, Animal 타입으로만 사용 가능

 

다운 캐스팅의 예   

Animal animal = new Dog(); // 업캐스팅
Dog dog = (Dog)animal; // ✅ 다운캐스팅
dog.MakeSound(); // 출력: Woof! Woof!

 

 

안전한 캐스팅들

Animal animal = new Dog();
Dog dog = animal as Dog; // ✅ 안전한 캐스팅
if (dog != null)
{
dog.MakeSound(); // 출력: Woof! Woof!
}

 

 

Animal animal = new Dog();
if (animal is Dog)
{
Dog dog = (Dog)animal; // ✅ 안전한 다운캐스팅
dog.MakeSound(); // 출력: Woof! Woof!
}

 

 

 

4. 객체 참조

 

5. 델리게이트와 이벤트

 

델리게이트를 통해 B객체에서 A객체로 메세지를 보낼 수 있다.

델리게이트로 자신을 생성한 객체를 호출함, 델리게이트를 사용하지 않으면 계속해서 새로운 객체를 생성하는 것

 

Find를 활용할 수도 있지만 , 자원을 많이 잡아먹음.

 

class B {
public delegate void Delegate();
public Delegate callback;
public B(Delegate callback) {
this.callback = callback;
}
private callA() {
this.callback.CallFromB();
}
}
class A : MonoBehaviour {
private void Start()
{
B b = new B(this);
}
public void CallFromB() {
// ...
}
}

 

재사용 가능한 PopUpPanel 만들기

 

 

GameManager와 같은 클래스에서 이렇게 이렇게 text를 써 주고 버튼 동작은 이렇게 해 줘 ! 보내면

PopUpPanelController는 그 데이터를 받아서 동작하는 방식을 만들어 봐라 ! 

이렇게 만드는 이유는 조금 더 다양한 형태로 활용할 수 있게 하기 위함

예를 들어, popUpPanelController 안에 모든 것을 구현해 버린다면, 그 패널은 한 가지 기능밖에 하지 못함.

 

using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class PopUpPanelController : MonoBehaviour
{
    [SerializeField]Button CancelButton;
    [SerializeField]private Button ExitButton;
    [SerializeField]private TextMeshProUGUI exitButtonText;
    [SerializeField]private TextMeshProUGUI mainText;

    void Awake()
    {
        // 잘 안되서 그냥 인스펙터 창으로 할당했습니다.
        // CancelButton = GameObject.Find("CancelButton").GetComponent<Button>();
        // ExitButton = GameObject.Find("ExitButton").GetComponent<Button>();
        // exitButtonText = ExitButton.GetComponentInChildren<TextMeshProUGUI>();
        // mainText = mainText.GetComponentInChildren<TextMeshProUGUI>();
    }

    
    public delegate void PopUpPanelDelegate();
    public PopUpPanelDelegate popUpPanelDelegate;

    public void SetUp(string ExitText, string MainText, Action onExit = null, Action onCancel = null)
    {
        exitButtonText.text = ExitText;
        mainText.text = MainText;

        if (onExit != null)
        {
           ExitButton.onClick.AddListener(()=>onExit?.Invoke());
        }

        if (onCancel != null)
        {
            CancelButton.onClick.AddListener(() => onCancel?.Invoke());
        }
        
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public GameObject popUpPanelPrefab;
    public Canvas canvas;


    //나중에는 특정 버튼 클릭시 (Ex: 닫기 버튼) 생성되게 바꿀 것입니다.
    private void Start()
    {
        GameObject popUpPanel = Instantiate(popUpPanelPrefab,canvas.transform, false);
        PopUpPanelController popUpPanelController = popUpPanel.GetComponent<PopUpPanelController>();
        
        
        
        popUpPanelController.SetUp("Eixt", "게임을 종료하시겠습니까 ? ", () => { Debug.Log("GameOver");}, () => { Destroy(popUpPanel); });
    }
}

 

이렇게 생성되고 정상 작동된다. (한글이 적용 안되는 폰트)

 

 

 

강사님 방식에서 배울 점

캔버스 사이즈 매칭 !

 

어느곳에서나 똑같은 사이즈 보장하기 위한 패널 하나 추가로 생성 후 그 패널 안에 새로운 패널을 더 만들어 사이즈 조정

 

 

 

TicTacToe 간단 계획

약간 잘못되었다, 테스트를 매 턴마다 해야 함.

이런 식으로 전체 흐름을 먼저 잡고 가는 것이 좋다. (너무 자세하게는 말고)

 

AI가 없을 때

 

 

오늘의 목표

1. 백준 코테 약수, 배수와 소수 2 마무리

2. 멋사 코테 강의 중 하나 듣기

3. Unity Editor 관련 강의 듣기