반응형

 

 

 

 

유니티 이벤트 함수

- 유니티는 미리 정의된 순서대로 실행되는 이벤트 함수들이 존재한다.

- 종류와 실행 순서(Life cycle)는 다음 페이지 참조

 

이벤트 함수의 실행 순서 - Unity 매뉴얼

Unity 스크립트를 실행하면 사전에 지정한 순서대로 여러 개의 이벤트 함수가 실행됩니다. 이 페이지에서는 이러한 이벤트 함수를 소개하고 실행 시퀀스에 어떻게 포함되는지 설명합니다.

docs.unity3d.com

 

 

 

 

Awake(), Start(), OnEnable()

- Awake

  • Scene이 로드될 때 스크립트가 포함된 게임오브젝트가 초기화되거나 비활성화된 게임오브젝트가 활성화 될 때, Instantiate로 생성된 게임 오브젝트가 초기화 된 후에 호출된다.
  • 스크립트가 비활성화 되어있을때도 호출이 되며, 게임 오브젝트가 초기화된 후, 단 한번 호출된다.
  • 모든 게임오브젝트가 초기화된 후 호출되기 때문에 Find와 같은 함수를 사용하여 안전하게 쿼리할 수 있다.
  • 멤버를 초기화할 때 사용된다.
  • 호출하는 순서가 정해져있지 않기 때문에 스크립트들 사이에서 Awake전이나 후에 호출되는것에 의존해서는 안된다.

- OnEnable

  • 게임오브젝트 또는 스크립트가 활성화될 때마다 호출된다. (1회성이 아님)
  • 이벤트 연결시 사용된다.

- Start

  • Update가 호출되기 전에 호출되는 함수이다.
  • Awake와 마찬가지로 단 한번 호출된다.
  • Awake와 달리 스크립트가 비활성화 되어있을때 호출이 되지 않아서 비활성화 된 스크립트에서는 Awake와 동일한 프레임에 호출되지 않을수도 있다.
  • 한 객체가 다른 객체에 의존하는 경우에 유용하게 사용할 수 있는 함수이다. (의존하는 객체 초기화는 Start에서 의존되는 객체 초기화는 Awake에서하게되면 안정성이 높아진다.)
  • 해당 함수는 코루틴으로 정의가 가능해서 yield문으로 흐름제어가 가능하다.

 

 

 

Update(), FixedUpdate(), LateUpdate()

- Update

  • 스크립트가 활성화 되어있을 때, 매 프레임마다 호출된다.
  • 게임의 핵심 로직을 작성한다.

- FixedUpdate

  • 물리 시스템 주파수에 따라 일정한 주기로 호출된다. (기본설정 기준 0.02초마다 호출됨.)
  • 프레임 속도에따라 Update보다 더 많이 호출될 수도 있고 적게 호출될 수도 있다.
  • 프레임 속도와 독립적으로 다른 타이머에서 호출되기 때문에 Time.deltaTime을 곱할 필요가 없다.

- LateUpdate

  • Update가 호출된 후 프레임마다 한 번씩 호출된다.
  • 일반적으로 Update에서 플레이어를 움직이는 계산을 하고, LateUpdate에서 카메라의 계산을 수행하기 위해 사용한다.

 

 

 

 

반응형
반응형

 

 

 

 

제네릭 싱글톤(Generic singleton)

- 싱글톤 : 객체의 인스턴스가 오직 하나인 디자인 패턴

- Generic class : 데이터 형식을 일반화한 클래스를 말한다.

 

 

코드

using UnityEngine;

public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
    [SerializeField]
    private bool dontDestroy = true;
    private static T instance = null;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = InitManager<T>();
            }
            return instance;
        }
    }

    protected static U InitManager<U>() where U : MonoBehaviour
    {
        GameObject go = null;
        U obj = FindObjectOfType<U>();
        if (obj == null)
        {
            go = new GameObject(typeof(U).Name);
            go.AddComponent<U>();
        }
        else
        {
            go = obj.gameObject;
        }

        DontDestroyOnLoad(go);
        return go.GetComponent<U>();
    }

    private void Awake()
    {
        if (instance == null)
        {
            if (dontDestroy)
            {
                Instance.Init();
            }
            else
            {
                instance = GetComponent<T>();
                Init();
            }
        }
        else
        {
            Destroy(gameObject);
        }
    }

    protected abstract void Init();
}
  • DontDestroyOnLoad를 사용하지 않으려면 인스펙터 창에서 해당 bool값을 false로 변경해준다.
  • Init 함수를 추상 함수로 지정해서 싱글톤으로 지정할 클래스의 초기화를 Init에서 하도록 유도한다.

 

 

 

 

반응형
반응형

 

 

 

 

JsonUtility

- 유니티에서 제공하는 JSON 클래스이다.

- 다른 JSON 라이브러리에 비해 기능이 적지만 성능이 좋다.

- 직렬화된 클래스, 구조체만 지원되고 배열, 리스트, 딕셔너리 등의 자료구조는 클래스로 래핑해야 JSON 변환이 가능하다.

 

 

 

직렬화(Serializable)

- C#은 복합 데이터 형식을 쉽게 스트림에 읽기/쓰기를 할 수 있게 하는 직렬화라는 메커니즘을 제공한다.

- 직렬화는 객체의 상태(필드에 저장된 값들)를 메모리에 저장 장치에 저장이 가능한 0과 1의 순서로 바꾸는것을 말한다.

- 직렬화는 원하는 데이터 위에 [Serializable] 어트리뷰트를 작성해주면 된다.

 

 

 

using System;
using UnityEngine;

public struct SomeStruct
{
    [SerializeField]
    private int m_iNum;
    [SerializeField]
    private bool m_bCheck;
    
    public SomeStruct(int i, bool b)
    {
        m_iNum = i;
        m_bCheck = b;
    }
}

//ToJson
SomeStruct ss = new SomeStruct(10, false);
string json = JsonUtility.ToJson(ss, true);

//FromJson
SomeStruct ss2 = JsonUtility.FromJson<SomeStruct>(json);
  • JSON으로 변환 할 클래스나 구조체를 반드시 직렬화 어트리뷰트를 작성해줄 필요는 없지만, 해당 클래스나 구조체가 다른 클래스의 멤버가 되면 반드시 직렬화 어트리뷰트를 작성해줘야한다.
  • 멤버 변수의 접근 지시자를 private로 할 경우 [SerializeField] 어트리뷰트를 붙여줘야 해당 데이터가 JSON으로 변환된다.
  • static, readonly, const 키워드가 붙은 멤버 데이터는 JSON으로 변환되지 않는다.
  • JSON으로 변환하지 못하게 할 멤버는 [NonSerialized] 어트리뷰트를 붙여준다.
  • FromJsonOverwrite(json, object)는 추후 작성할 예정(기능 파악 중..)

 

※※ 직렬화 클래스(혹은 구조체)에 멤버변수가 추가된 경우, 해당 멤버변수에 대한 에러가 발생하지 않고 기본값으로 초기화된다.

 

 

 

래핑 클래스

- 배열이나 리스트 등의 자료구조는 API에 직접 전달하는 기능은 지원되지 않기 때문에, 클래스나 구조체로 래핑 해서 변환한다.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class JsonWrapper
{
    #region ARRAY WRAPPER
    [Serializable]
    private class ArrayWrapper<T>
    {
        [SerializeField]
        private T[] m_items;
        public T[] Items { get { return m_items; } }
        public ArrayWrapper(T[] arr)
        {
            m_items = arr;
        }
    }

    public static string ToJson<T>(T[] array, bool prettyPrint = false)
    {
        ArrayWrapper<T> wrapper = new ArrayWrapper<T>(array);
        //bool : 출력 제어 (로그 출력 시, 보기 좋게 출력하는 기능 지원. default : false)
        return JsonUtility.ToJson(wrapper, prettyPrint);
    }

    public static T[] ArrayFromJson<T>(string json)
    {
        ArrayWrapper<T> wrapper = JsonUtility.FromJson<ArrayWrapper<T>>(json);
        return wrapper.Items;
    }
    #endregion

    #region LIST WRAPPER
    [Serializable]
    private class ListWrapper<T>
    {
        [SerializeField]
        private List<T> m_list;
        
        public List<T> ToList()
        {
            return m_list;
        }

        public ListWrapper(List<T> list)
        {
            m_list = list;
        }
    }

    public static string ToJson<T>(List<T> list, bool prettyPrint = false)
    {
        ListWrapper<T> wrapper = new ListWrapper<T>(list);
        return JsonUtility.ToJson(wrapper, prettyPrint);
    }

    public static List<T> ListFromJson<T>(string json)
    {
        ListWrapper<T> wrapper = JsonUtility.FromJson<ListWrapper<T>>(json);
        return wrapper.ToList();
    }
    #endregion
}
  • Dictionary 역시 위와 같은식으로 래핑 클래스를 정의해야한다.

 

 

 

참고

 

JSON 직렬화 - Unity 매뉴얼

JSON 직렬화는 오브젝트와 JSON 포맷을 상호 변환하는 기능입니다. 이 기능은 웹 서비스와 상호작용할 때 유용하거나 단순히 데이터를 텍스트 기반 포맷으로 간편하게 패킹하고 언패킹하는 데 유

docs.unity3d.com

 

 

스크립트 직렬화 - Unity 매뉴얼

직렬화는 데이터 구조나 오브젝트 상태를 Unity 에디터가 저장하고 나중에 재구성할 수 있는 포맷으로 자동으로 변환하는 프로세스를 말합니다. Unity 에디터에서는 저장 및 로딩, 인스펙터 창, 인

docs.unity3d.com

 

 

 

 

 

반응형
반응형

 

 

 

※ isometric 타일맵을 기준으로 작성된 포스팅입니다.

 

타일맵 컴포넌트에서 타일을 그리면 그려진 타일의 배열의 크기를 가져올 수 있다. isometric 기준으로 타일맵의 배열은 다음과 같이 구성된다.

 

 

주의할 점이 있는데 타일맵 자체에서 배열을 제공하는것이 아니라 타일맵이 그려진 사이즈(Vector2) 값을 가지고있는것이기 때문에 타일맵의 사이즈 값과 타일맵의 셀 바운드값을 가져와서 직접 배열을 초기화해줘야한다.

이 때, 셀 바운드값은 최하단 타일을 기준으로 값이 정해지기 때문에 이 값이 무조건 0에서부터 시작하지 않는다.

 

 

  • 타일맵 초기화 코드
private void InitTileArray()
{
    Tilemap tilemap = GetComponent<Tilemap>();
    Vector2[,] tileArray = new Vector2[m_cTilemap.size.y, m_cTilemap.size.x];
    
    Vector3Int tilePos;
    for (int y = tilemap.cellBounds.yMin; y < tilemap.cellBounds.yMax; y++)
    {
        for (int x = tilemap.cellBounds.xMin; x < tilemap.cellBounds.xMax; x++)
        {
            tilePos = new Vector3Int(x, y, 0);
            if (tilemap.HasTile(tilePos))
            {
                int arrX = x - tilemap.cellBounds.xMin;
                int arrY = y - tilemap.cellBounds.yMin;
                Vector3 tileWorldPos = tilemap.CellToWorld(tilePos);
                tileArray[arrY, arrX] = tileWorldPos;
            }
        }
    }
}

  ※ tileWorldPos의 값은 타일의 중앙좌표가 아닌 하단 모서리의 좌표이기 때문에, 중앙좌표를 위한 추가값을 넣어줘야한다.

 

 

 

 

  • 추가 주의사항

- 특정 위치에 타일맵을 한번 그리게되면 그 위치의 타일맵을 지운다고해도 그 위치는 바운드값에 포함이 된다. 그렇기때문에 타일맵 컴포넌트에서 옵션(…)을 눌러서 'Compress Tilemap Bounds'를 눌러주거나 코드에 CompressBounds()를 호출해준다.

 

 

 

 

반응형
반응형

 

2018 LTS에서 2019 LTS로 넘어오면서 이상한게 눈에 띄었다.

위와 같이 한글로 주석해놓은게 유니티 인스펙터 창에서 미리보기할 때 깨져서 보이는것이었다.

간단하게 작업할때는 그냥 무시하고 사용했는데, 깃허브에 올리고 맥에서도 사용하려하니 장애가 많아서 결국 해결을 해야했다.

 

원인은 뻔했다. 파일이 UTF-8로 저장되어있지 않은것..

저장할 때마다 UTF-8로 변경해서 저장하면 되긴 한데, 매번 스크립트 생성할때마다 신경쓰기는 너무나 귀찮다.

해결법을 찾아보던 중, 스크립트 템플릿이 있는데 그 파일을 UTF-8로 변경해두변 된다고해서 해봤는데 어림없었다..

그 뒤, EditorConfig라는것을 찾아서 해결을 했다. 지금부터 설정법을 알아보자.

 

 

 

 

1. 기존 스크립트 변경법

- 이 부분은 노가다하는 수밖에 없다.

 

1-1) 스크립트를 연 뒤, 파일다른 이름으로 저장으로 저장을 시도한다.

1-2) 저장 옆에 화살표를 눌러 인코딩하여 저장을 선택한다.

1-3) 고급 저장 옵션창에서 인코딩란을 다음과 같이 설정한 다음 확인을 눌러 저장한다.

 

 

 

 

2. EditorConfig로 인코딩 설정하기

- EditorConfig : 프로젝트의 구성 파일 형식, 코딩 스타일을 정의하는 텍스트 편집기 플러그인(이라고 한다.)

 

2-1) 프로젝트안에 파일을 생성한 뒤, .editorconfig로 파일명을 설정해준다.

2-2) 생성한 파일을 메모장이나 VS로 연 뒤, 다음과 같이 작성해준다.

root = true

[*]
charset = utf-8

2-3) 저장을 하게되면 이후에 생성되는 스크립트는 UTF-8 인코딩으로 자동으로 설정된다.

 

※ 추가 설정법은 다음 사이트 참고

 

EditorConfig

What is EditorConfig? EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection o

editorconfig.org

 

 

 

결과)

 

반응형

+ Recent posts