241204

lililllilillll·2024년 12월 4일

개발 일지

목록 보기
10/350

✅ 오늘 한 일


  • 유니티 스크립트 생명 주기 번역 및 요약
  • 백준 1문제 풀기
  • C# 교과서 읽기


🎮 유니티 스크립트 생명 주기


https://docs.unity3d.com/2023.2/Documentation/Manual/ExecutionOrder.html

매뉴얼 버전: 2023.2
영문 문서 보고 번역 및 요약했다.

이 이벤트 함수들은 MonoBehaviour 붙인 스크립트에서 선택적으로 실행되게 할 수 있는 내장 이벤트들이다.
Application, SceneManager, Camera 같은 클래스들을 이용하면 이것들 말고도 다른 이벤트를 등록할 수 있다.

처음 씬이 load될 때

  • Awake: 오브젝트 인스턴스 생성되면 가장 처음으로 호출됨.
    시작할 때 게임 오브젝트가 비활성화됐다면 활성화될 때까지 호출 안됨.
  • OnEnable: 오브젝트가 활성화되면 Awake 다음, Start 이전에 호출됨.

서로 다른 오브젝트끼리의 AwakeOnEnableStart 순서는 보장되지 않음.
A의 Start가 호출된 이후 B의 Awake가 호출될 수도 있다.

씬이 load되고 unload될 때

씬이 load되고 unload될 때 콜백 함수를 받을 수 있게 해주는
SceneManager.sceneLoaded와 SceneManager.sceneUnloaded 이벤트는 위 그림에 없다.
sceneLoaded 알림은 OnEnable 이후, Start 이전에 받는다.

Unity 실행 시 특정 메서드를 자동으로 호출하게 만드는 RuntimeInitializeOnLoadMethodAttribute의 BeforeSceneLoad, AfterSceneLoad를 사용하면 특정 메서드를 씬 로드 이전과 이후에 실행되게 할 수 있다.

에디터

  • Reset: 스크립트가 오브젝트에 처음 부착되거나 Reset을 눌렀을 때 스크립트의 속성을 초기화한다. (스크립트 컴포넌트 우측 상단 점 세개 눌러보면 Reset 버튼이 있다.)
  • OnValidate: 스크립트의 속성값이 수정되거나, 오브젝트를 메모리로 불러오며 역직렬화 과정이 일어날 때 호출된다.

오브젝트를 메모리로 불러올 때, 직렬화되어 저장된 데이터들을 역직렬화하여야 한다.
에디터에서 씬을 열거나, domain reload가 일어난 후에 역직렬화가 일어난다.
이미 메모리에 존재하는 오브젝트를 단순 참조할 때는 역직렬화할 필요 없다.

domain reload: 코드 변경 후 컴파일이 완료되거나 플레이 모드를 종료할 때 Unity가 스크립트를 다시 로드하는 과정

첫 프레임 업데이트 이전

  • Start: 스크립트 인스턴스가 활성화돼있을 때 첫 프레임 업데이트 이전에 호출됨.

프레임 사이에

  • OnApplicationPause: 일시중지를 누르면 프레임 끝에 호출된다. 정지된 화면을 보여주기 위해 프레임 하나가 추가로 만들어진다.

업데이트 순서

게임 로직, 상호작용, 애니메이션, 카메라 위치 등을 조작하려면 보통 Upadte를 이용한다.
그냥 Update 말고도 다른 함수들도 있다.

  • FixedUpdate: 프레임 단위가 아니라 고정된 in-game 시간 간격대로 발생한다.
    업데이트들은 고정돼있고 frame rate는 가변적이기 때문에,
    frame rate가 높을 땐 frame 사이에 fixed update가 하나도 발생하지 않을 수 있고,
    frame rate가 낮을 땐 frame당 여러 개의 fixed update들이 발생할 수 있다.
    모든 물리 계산과 update들은 FixedUpdate 직후에 발생한다.
    frame rate에 독립적이라, FixedUpadte에서 이동을 계산할 때 Time.deltaTime을 곱할 필요 없다.
    fixed update들 사이의 간격은 Time.fixedDeltaTime으로 정의돼있다.
    fixedDeltaTime은 에디터의 Time settings의 Fixed Timestep 속성값을 건드리거나 스크립트를 통해 직접 설정 가능하다.
  • Update: 프레임 당 한 번 호출된다.
  • LateUpdate: Update가 끝난 뒤 프레임 당 한 번 호출된다. 3인칭 시점 카메라에 자주 사용된다.

애니메이션 업데이트 루프

MonoBehaviour에 의해 호출되는 애니메이션 루프 콜백 함수들

  • MonoBehaviour.OnAnimatorMove: 루트 모션 처리를 위한 콜백
  • MonoBehaviour.OnAnimatorIK: Inverse Kinematics를 설정하기 위한 콜백

StateMachineBehaviour에 의해 호출되는 애니메이션 관련 이벤트 함수들

  • StateMachineBehaviour.OnStateMachineEnter
  • StateMachineBehaviour.OnStateMachineExit
  • StateMachineBehaviour.OnStateEnter
  • StateMachineBehaviour.OnStateUpdate
  • StateMachineBehaviour.OnStateExit
  • StateMachineBehaviour.OnStateMove
  • StateMachineBehaviour.OnStateIK

렌더링

이 실행 순서는 Built-in Redner Pipeline에만 적용되며, SRP, URP, HDRP는 약간 다르다.
렌더링 직전에 무언가를 발생시키고 싶다면, Application.onBeforeRender를 이용하라.

  • OnPreCull: 카메라가 필요없는 씬을 잘라내기(cull) 전에 호출된다.
  • OnBecameVisible/OnBecameInvisible: 오브젝트가 아무 카메라에 보여지거나, 안 보여질 때 호출.
    OnBecameInvisible이 플로우 차트에 없는 이유는 오브젝트가 아무 때나 안 보여질 수 있기 때문.
    (카메라의 이동, 오브젝트 비활성화, 오클루전 컬링 등 다양한 이유로 인해 안 보여질 수 있다)
  • OnWillRenderObject: 오브젝트가 각 카메라에 보일 때 한 번만 호출된다.
  • OnPreRender: 카메라가 씬을 렌더링하기 전에 호출된다.
  • OnRenderObject: 모든 기본적인 렌더링 과정이 끝나고 난 뒤에 호출된다.
    이때 GL 클래스나 Graphics.DrawMeshNow를 통해 custom geometry를 그릴 수 있다.
  • OnPostRender: 카메라가 씬 렌더링을 완료한 이후에 호출된다.
  • OnRenderImage: 씬 렌더링이 완료된 이후에 post-processing을 할 수 있도록 호출된다.
  • OnGUI: IMGUI에서 GUI 이벤트를 처리하기 위해 호출된다.
  • OnDrawGizmos: 씬 뷰에 Gizmo들을 그릴 때 사용된다. 게임 실행 여부와 상관없이 동작하며, 에디터 전용이다.

IMGUI(Immediate Mode GUI): 일반적으로 사용하는 UGUI와는 다른 GUI 시스템. 인게임 디버깅 도구, 커스텀 인스펙터 등에 쓰인다. 매 프레임 UI를 다시 그리므로 Canvas 기반의 UGUI보다 성능이 안 좋다.

코루틴

일반적인 코루틴 업데이트들은 Update 함수가 반환된 뒤에 실행된다.
코루틴은 주어진 YieldInstruction이 끝날 때까지 실행을 중단(yield)하는 함수이다.

  • yield: 다음 프레임에서 모든 Update 함수들이 실행된 이후에 재개됨.
  • yield WaitForSeconds: 지정된 시간이 지나고, 해당 프레임의 모든 Update 함수들이 호출된 이후에 재개됨.
  • yield WaitForFixedUpdate: 모든 FixedUpdate가 호출된 이후에 재개됨. 코루틴이 FixedUpdate 이전에 yield했다면, 현재 프레임의 FixedUpdate들이 끝난 이후에 바로 재개됨.
  • yield WWW: WWW 다운로드가 끝나면 재개됨.
  • yield StartCoroutine: 다른 코루틴을 시작시킨 뒤 다시 재개될 때까지 기다림.

WWW class: 웹 요청을 통해 데이터를 다운로드하거나 업로드할 때 사용되는 클래스. 2017 이전 버전 유니티에서 사용됐으며, 현재는 UnityWebRequest로 대체됨. 이해하기 쉽고 구현이 간단해서 아직 쓰기도 함.

오브젝트가 파괴됐을 때

  • OnDestory: 파괴될 오브젝트의 마지막 프레임의 모든 작업이 끝나고 난 뒤 호출됨
    (오브젝트는 씬을 닫거나 Object.Destoy을 호출할 때 파괴됨)

닫을 때

이 함수들은 씬에 있던 모든 활성화된 오브젝트들에서 호출됨

  • OnApplicationQuit: 이 함수는 프로그램이 종료되기 전에 모든 게임 오브젝트에서 호출됨. 에디터에선 플레이 모드 종료할 때 호출됨.
  • OnDisable: 컴포넌트가 비활성화되거나, 오브젝트가 비활성화되면 호출됨.


📖 C# 교과서


21 닷넷 API

마소에서 닷넷 API 검색할 수 있는 사이트 제공해준다.

닷넷에서 제공하는 수학 관련 내장 클래스 Math : Math.Abs(), Math.Max(), Math.Pow(), Math.Floor() 등

using static System.Math; 사용하면 Math.Pow()가 아니라 Pow()로 줄여 쓸 수 있다

nameof 연산자로 클래스 또는 메서드 이름 자체를 문자열로 가져올 수 있다

22 구조체 사용하기

구조체 : 이름 하나로 서로 다른 데이터 형식을 묶어 관리

C#에는 클래스 있으니까 닷넷 내장 구조체 몇 개만 학습하고
뒤에서 배울 클래스 위주로 사용하면 된다.

22.2 구조체 만들기

struct Point
{
    public int X;
    public int Y;
}

class StructDemo
{
    static void Main()
    {
        Point point;
        point.X = 100;
        point.Y = 200;
        Console.WriteLine($"X:{point.X}, Y:{point.Y}");
    }
}

22.4 구조체 배열

Point[] points = new Point[2];

구조체 배열도 만들 수 있다.

22.6 내장형 구조체

닷넷 프레임워크 내장 구조체 중 자주 사용되는 것들

  • DateTime 구조체: 시간/날짜 관련 모든 정보 제공
  • TimeSpan 구조체: 시간/날짜 간격에 대한 모든 정보 제공
  • Char 구조체: 문자 관련 모든 정보 제공
  • Guid 구조체: 절대로 중복되지 않는 유일한 문자열을 생성

날짜 관련 구조체 사용하기

> DateTime.Now.Year
2019
> DateTime now = DateTime.Now;
> Console.WriteLine(now.Date);
2019-09-23 오전 12:00:00

DateTime 예제

class TimeSpanDemo
{
    static void Main()
    {
        // 시간 차 구하기
        TimeSpan dday = Convert.ToDateTime("2024-12-25") - DateTime.Now;
        Console.WriteLine((int)dday.TotalDays);
    }
}

TimeSpan 예제

1부터 8760까지 정수에 해당하는 날짜를 반환하는 함수

class GetDateTimeFromYearlyHour
{
    static void Main()
    {
        Console.WriteLine(GetDateTimeFromYearlyHourNumber(1));
        Console.WriteLine(GetDateTimeFromYearlyHourNumber(8760/2));
        Console.WriteLine(GetDateTimeFromYearlyHourNumber(8760));
    }

    static DateTime GetDateTimeFromYearlyHourNumber(int number)
    {
        return (new DateTime(2024, 1, 1, 0, 0, 0)).AddHours(--number);
    }
}

문자 관련 구조체 사용하기

Char.IsUpper(a) // 대문자인지?
Char.Number(c) // 숫자형인지?
Char.IsWhiteSpace(d) // 공백 문자인지?

Guid 구조체로 유일한 값 출력하기

Guid는 GUID(Globally Unique Identifier)를 출력.
GUID 값은 실행할 때마다 동일한 값을 만날 확률이 0.

string unique = Guid.NewGuid().ToString();

23 열거형 형식 사용하기

23.1 열거형 형식 사용하기

기억하기 어려운 상수들을 기억하기 쉬운 이름 하나로 묶어 관리하는 표현 방식.

ConsoleColor 열거형으로 콘솔의 전경색 및 배경색 바꾸기

    static void Main()
    {
        //전경색
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine("Blue");
        Console.ResetColor();

        //배경색
        Console.BackgroundColor = ConsoleColor.Yellow;
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("Red");
        Console.ResetColor();
    }

신기

23.2 열거형 만들기

enum Priority
{
	High,
    Normal=5,
    Low // 상수 6
}

초기화 안 시키고 쓰는게 기본.
초기화 시키면 그 다음부터의 값도 바뀐다.

상수로만 구분하면 어려우니까 이름을 붙여서 쓰는 느낌.

    enum Priority
    {
        High,
        Normal,
        Low
    }

    static void Main()
    {
        Priority high = Priority.High;
        Priority normal = Priority.Normal;
        Priority low = Priority.Low;

        Console.WriteLine($"{high}, {normal}, {low}");
    }

어째서인지 "High, Normal, Low"가 출력된다.
열거형 변수값을 콘솔에서 문자열로 출력하면 열거형의 멤버 이름이 문자열로 출력된다고 함.

Animal animal = Animal.Dragon;
int num = (int)animal;
string str = animal.ToString();

이러면 num은 상수값, str은 Dragon이 된다.
열거형 값은 변환하는대로 변환된다.

Animal animal = Animal.Dog;

switch (animal)
{
	case Animal.Chicken:
		break;
	case Animal.Dog:
		break;
}

switch 문과 같이 사용하면 유용하다.

string[] colors = EnumGetNames(cc); // 모든 색상 이름을 반환

열거형 이름들을 저장한다.



⚔️ 백준


7573 고기잡이

모눈 종이가 아니라 고기에 대해서 생각해야하는 것까진 떠올려냈는데
시간 낭비가 되는 것 같아 그냥 답지를 봤더니
고기에 대해 모든 그물의 경우의 수를
고기에서부터 시작하는게 아니라
그물이 걸리는 최대한 끝점에 고기를 놨어야 했다

이런;



profile
너 정말 **핵심**을 찔렀어

0개의 댓글