Resources 폴더    [원본 링크]


확인 완료한 버전 2017.3 - 난이도: 고급


이 문서는 유니티 AssetBundles 및 Resources 가이드의 3번째 챕터 입니다.


이 챕터에서는 Resources 시스템에 대해 설명합니다. 이것은 개발자가 Resources 라고 이름 지은 하나 이상의 폴더에 Asset들을 저장하고 Resources API를 이용하여 Asset들에서 Object들을 런타임 상에서 로드하고 언로드 하는 시스템 입니다.




2.1 Resources 시스템에 대한 모범 사례


사용하지 마세요.


사용하지 않도록 권장하는 이유는 다음과 같습니다.


● Resources 폴더를 사용하면 세분화 된 메모리 관리가 더욱 어려워집니다.

● 부적절한 Resources 폴더 사용 시 어플리케이션 시작 시간과 빌드 시간이 길어집니다.

- Resources 폴더의 수가 증가하면 폴더 내의 Asset 관리가 어려워집니다.

● Resources 시스템은 특정 플랫폼에 맞춰진 콘텐츠 제공 을 위한 프로젝트의 역량을 감소시키며 차후 콘텐츠 업데이트 가능성을 손실시킵니다.

- AssetBundle Variant는 장치 단위로 콘텐츠를 조절 할 수 있는 유니티의 기본 도구 입니다.




2.2 Resources 시스템의 적절한 사용


Resources 시스템이 도움이 되는 두가지 구체적인 예가 있습니다.


1. Resources 폴더의 쉬운 사용법은 빠르게 프로토 타입을 만들 때 용이합니다. 하지만 프로젝트가 본격적으로 시작된다면 사용하지 않아야 합니다.


2. Resources 폴더는 다음과 같이 사소한 경우에는 유용 할 수 있습니다:

● 프로젝트 전체에서 일반적으로 필요한 경우

● 메모리를 많이 사용하지 않음

● 패치가 발생하지 않거나 플랫폼이나 장치에 따라 다르지 않을 경우

● 최소한의 부트스트랩에 사용




2.3 Resources의 직렬화


Resources 폴더 내부의 Asset 및 Object들은 프로젝트가 빌드 될 때 하나의 직렬화 된 파일로 결합됩니다. 이 파일은 AssetBundle과 같이 metadata와 인덱싱 정보를 포함하고 있습니다. AssetBundle 문서에서 설명한 것 처럼 이 인덱스는 주어진 Object의 이름을 파일 GUID와 로컬 ID로 변환 하는데 사용되는 직렬화 된 검색 트리를 포함합니다. 이는 직렬화 된 파일 내부의 특정 바이트 오프셋에서 Object의 위치를 찾는데 사용됩니다.


대부분의 플랫폼에서 데이터 검색 구조는 균형 탐색 트리이며. O(n log(n))의 속도로 증가하는 구축 시간을 가집니다. 이 증가로 인해 인덱스 로딩 시간은 Resources 폴더에 있는 Object가 늘어날수록 선형적으로 증가합니다.


이 작업은 건너 뛸 수 없으며 초기 조작 불가능한 시작화면이 표시되는 어플리케이션 시작 시 발생합니다. Resources 폴더에 포함된 Object들이 어플리케이션의 첫 씬에 거의 필요가 없더라도 10000개의 Asset을 포함하는 Resources 시스템을 초기화 하는데 낮은 사양의 모바일 장치에서는 수 초의 시간이 걸립니다.

'유니티' 카테고리의 다른 글

유니티의 컴파일  (0) 2019.03.14
AssetBundle의 사용 패턴  (0) 2018.03.09
AssetBundle의 기본 요소  (0) 2018.03.07
Assets, Objects 그리고 직렬화  (0) 2018.03.04
AssetBundles 및 Resources 가이드  (0) 2018.03.03

Rest In Spase  (2016)

 
 기어 VR 용 비행 슈팅

             



 Unreal과 VR에 대한 학습을 위해 진행한 프로젝트


 장르 : 비행 슈팅
 플랫폼 : 기어 VR
 플레이 시간 : 약 3분
 개인 프로젝트
 사용 언어 : C++


'개인 프로젝트' 카테고리의 다른 글

Just Walk (2016)  (0) 2018.03.06
Vain Storm (2017)  (0) 2018.03.04
Run To Hell (2013)  (0) 2018.03.04
DILUVIO (2011)  (0) 2018.03.04

Vain Storm  (2017)






 1. 게임 정보

분대 단위 모바일 전략 시뮬레이션

전략적인 영웅, 일반 유닛 배치로 스테이지를 클리어 해 나가는 게임


 장르 : 전략 시뮬레이션
 플랫폼 : 모바일
 플레이 시간 : 약 10분
 참여 인원 : 3명 (기획 1, 프로그래밍 1, 그래픽 1)
 참여 부분 : 메인 프로그래머
 사용 언어 : C#
 사용한 에셋 : 유료 3D 모델 외 전체 자체 제작
 
 * 게임 진행 방식
 - 영웅, 일반 유닛을 구입
 - 유닛을 3x3의 분대 진영에 적절히 배치하여 스테이지에 도전
 - 적군의 특성을 확인하고 그에 맞는 전략적 유닛 선택, 배치가 필요


 2. 게임 구현

Unity의 모든 기능에 익숙해지기 위해서 외부 에셋을 사용하지 않음

UI, 맵 에디터, 유닛 또는 스킬 편집 등 필요한 기능을 직접 구현

유닛의 AI는 행동 트리를 사용하여 구현

A* 알고리즘으로 길 찾기를 구현하였으나 NavMesh를 사용하도록 변경

 2 - 1. 진행 상황

 프로그래밍 :  운영, 데이터 저장, 에셋 번들용 CDN + 웹서버 제작 중
 
 기획 : 웨이브 추가 작업 중

 그래픽 : 이펙트 추가, UI 디자인 정리 중


'개인 프로젝트' 카테고리의 다른 글

Just Walk (2016)  (0) 2018.03.06
Rest In Spase (2016)  (0) 2018.03.04
Run To Hell (2013)  (0) 2018.03.04
DILUVIO (2011)  (0) 2018.03.04

Run To Hell  (2013)



 1. 게임 정보

 템X런 같은 한정된 움직임은 버려라!

 라인 없이 마음대로 움직이는 프리 러닝 액션게임 런 투 헬!

 지옥으로 떨어진 여동생을 구하러 달려가는 언니의 이야기
 
 

런투헬 안드로이드 구동 영상

 
 장르 : 프리라인 액션 러닝
 플랫폼 : 모바일 (온라인 랭킹)
 플레이 시간 : 약 10분
 참여 인원 : 5명 (기획 2, 프로그래밍 2, 그래픽 1)
 참여 부분 : 메인 프로그래머
 사용 언어 : C#, 자바스크립트
 사용한 에셋 : NGUI, Dark City Sound, 몇몇 무료 3D 모델
 
 * 게임 진행 방식
 - 정해진 라인 없이 터치 + 드래그로 이동, 점프, 슬라이딩 조작, 더블 터치로 펀치 사용
 - 랜덤한 지형과 예측 할 수 없는 동적인 장애물, 타일 마다 다른 고정 장애물을 피해 최대한 멀리 달리기
 - 한번에 사망하지 않는 체력 시스템
 - 장에물에 부딪히면 충돌한 각도로 캐릭터가 회전하며 날아갑니다.
 - 회전하면서 날아가는 캐릭터를 드래그하여 자세를 바로잡고 맵으로 돌아와야 함 (영상에서 아래로 마구 드래그하는 부분 - 큰 장애물에 충돌할 수록 멀리 날아가고 많이 회전)








 2. 게임 구현

 NGUI를 사용하여 UI를 제작하였습니다.

 해상도 설정은 720 * 1280 에 최적화 되어있으며

 Character Controller 를 사용하여 캐릭터 제작하였습니다.
 
 플레이어 고정 + 맵 이동형식, 리지드바디 캐릭터 를 만들어보고 현재 형식으로 결정하였습니다.

 조작 방식 - 자동으로 앞으로 달리며 터치 위치에 따른 움직임 처리
 
 일정거리 이상 드래그 해야 액션 실행

 캐릭터 위치에 따른 바닥 타일 생성, 삭제 이루어짐

 장애물이 플레이어와 일정거리 이상 떨어진 타일에서 생성

 기획자의 장애물 등장 패턴 디자인이 쉽도록 인스펙터 인터페이스 제작

 충돌 방향을 계산하여 캐릭터를 날리고 드래그를 통해 캐릭터의 회전량을 줄여 맵으로 귀환 가능하도록 제작

 캐릭터의 스킬 - 펀치, 자기장
 
 연속으로 화면을 터치하면 펀치 발동 -> 쿨타임이 있으며 캐릭터 전면의 장애물을 날려버립니다.

 자기장이 발동하면 일정 거리안의 장애물을 감지하여 자동으로 회피합니다.



 3. 프로젝트 정리 

처음 엔진을 사용하여 만들어본 게임 입니다.

다른 프로그래머와 협동하여 만들었기 때문에 코드를 공유하고 로직 구현 방향에 대한 의논을 하며 협업에 익숙해지는 좋은 기회였습니다.


'개인 프로젝트' 카테고리의 다른 글

Just Walk (2016)  (0) 2018.03.06
Rest In Spase (2016)  (0) 2018.03.04
Vain Storm (2017)  (0) 2018.03.04
DILUVIO (2011)  (0) 2018.03.04

DILUVIO (2011)



 1. 게임 정보


 물이 차오르는 동굴에서 친구들을 구해 탈출!

 미로같은 맵과 퍼즐을 다양한 능력으로 풀어가는 퍼즐 게임

 온게임넷 'G맨 게임 종결자' 에 방영된 그 게임! (온게임넷 '켠김에 왕까지'에도 방영)

 방송 직후 다운로드 홈페이지 마비! 3만건 이상 다운로드를 기록한 게임!


 




 장르 : 액션 퍼즐
 플랫폼 : PC 윈도우 (싱글)
 플레이 시간 : 약 5시간
 참여 인원 : 4명 (기획 1, 프로그래밍 1, 그래픽 1, 사운드 1)
 참여 부분 : 프로그래밍
 사용 언어 : C++

 
 * 게임 진행 방식
 - 슈퍼 마리오 형식의 간단한 조작
 - 주인공 캐릭터를 이용하여 등장하는 몬스터 친구들을 흡수(구조) 하여 최상층 출구로 탈출하는 게임
 - 개성넘치는 다양한 친구 몬스터의 능력을 활용하여 복잡한 퍼즐을 풀어나감







 2. 구현 정보

 C++을 사용하여 객체지향 프로그래밍 활용

 다형성을 이용한 메뉴 구성, 파일 입출력을 통한 세이브, 로드, 맵 스크립트 구현

 2D 환경에서의 충돌체크 (원 <->사각, 사각<->사각 등) 구현

 옵저버 패턴을 활용하여 플레이어의 전체적인 게임 환경 상태 파악

 3. 프로젝트 정리 

 C++ 도 능숙하지 못한 상태에서 시작하여 팀원들과 밤낮 가리지 않고 작업실에서 신나게 만든 게임입니다.

 이 프로젝트를 진행하며 C++의 객체지향에 대해서 더욱 깊이 이해하고 자료구조와 디자인 패턴 등에 눈을 뜨게 되었습니다.

 열심히 노력한 만큼 방송으로 많은 사람들에게 알려지게 되어서 행복했던 프로젝트였습니다.


'개인 프로젝트' 카테고리의 다른 글

Just Walk (2016)  (0) 2018.03.06
Rest In Spase (2016)  (0) 2018.03.04
Vain Storm (2017)  (0) 2018.03.04
Run To Hell (2013)  (0) 2018.03.04

Assets, Objects 그리고 직렬화      [원본 링크]


확인 완료한 버전 2017.3 - 난이도: 고급


이 문서는 유니티 AssetBundles 및 Resources 가이드의 2번째 챕터 입니다.


이 챕터에서는 유니티의 직렬화 시스템의 깊은 내부 구조와 유니티 에디터와 런타임에서 Objects 사이의 견고한 참조를 유지하는 방법을 설명합니다. Objects와 Assets의 기술적 차이점에 대해서도 다룹니다. 여기서 다루는 내용은 유니티에서 Assets의 효율적인 로드, 언로드 방식을 이해하는 기본이 됩니다. 적절한 Asset 관리는 로딩 시간을 짧게 유지하고 메모리 사용을 줄이는데 중요합니다.


1.1 Assets와 Objects

유니티에서 데이터를 올바르게 관리하는 방법을 이해하려면, 유니티가 어떤 방법으로 데이터를 식별하고 직렬화 하는지를 알아야 합니다. 첫 번째 요점은 Assets와 UnityEngine.Objects의 차이 입니다.


Asset은 디스크에 있는 파일로 유니티 프로젝트의 Assets 폴더에 저장되어 있습니다. 텍스처, 3D 모델, 또는 오디오 클립 등 이 일반적인 타입의 Assets 입니다. materials와 같은 일부 Assets는 유니티 고유 형태의 데이터를 포함하고 있습니다. FBX파일과 같은 Assets는 기본 형태로 처리되어야 합니다.


UnityEngine.Object나 Object 와 같이 대문자 'O' 집합인 것들은 리소스의 특정한 인스턴스를 설명하는 직렬화 된 데이터의 집합입니다. 이것은 유니티 엔진이 사용하는 mesh, sprite, AudioClip, AnimationClip 등 어떤 타입이든 될 수 있습니다. 모든 Objects는 UnityEngine.Object 기본 클래스의 하위 클래스입니다.


대부분 Object 유형들은 내장되어있지만 2개의 특수 유형이 있습니다.


1. ScriptableObject 는 개발자가 고유 데이터 유형을 정의 할 수 있도록 편리한 시스템을 제공합니다. 이 유형들은 유니티에서 기본적으로 직렬화, 직렬화 해제가 가능하며 유니티 에디터의 Inspector창에서 조작이 가능합니다.


2. MonoBehaviourMonoScript를 연결하는 래퍼를 제공합니다. MonoScript는 유니티가 특정 어셈블리와 네임스페이스 내에서 특정 스크립팅 클래스에 대한 참조를 유지하는데 사용하는 내부 데이터 타입입니다.MonoScript는 실제 실행 코드를 포함하지 않습니다.


Assets와 Objects에는 일대다 관계가 있습니다.이는 Asset파일이 하나 이상의 Objects를 포함한다는 것 입니다.




1.2 Object간 참조

모든 UnityEngine.Objects는 다른 UnityEngine.Objects에 대한 참조를 가질 수 있습니다. 이런 각각의 Objects들은 같은 Asset 파일에 있거나 다른 Asset 파일에서 가져올 수 있습니다. 예를 들어 material Object는 하나 이상의 texture Object를 참조 할 수 있습니다. 이 texture Objects들은 보통 하나 이상의 texture Asset 파일(png 또는 jpg)에서 가지고 옵니다.


직렬화 될 때, 이 참조들은 '파일 GUID'와 '로컬 ID' 로 2개의 데이터로 구성됩니다. 파일 GUID는 대상 리소스가 저장된 Asset 파일을 식별합니다. 로컬 고유인[각주:1] 로컬 ID는 Asset 파일이 다수의 Object를 포함 할 수 있기 때문에 Asset 파일에 있는 각 Object를 식별합니다.


파일 GUID들은 .meta 파일 안에 저장됩니다. .meta 파일들은 유니티에 Asset이 최초로 추가될 때 생성되며 Asset이 저장된 같은 경로에 저장됩니다.


위에서 설명한 식별, 참조 시스템은 텍스트 편집기에서 볼 수 있습니다: 새로운 유니티 프로젝트를 만들고 에디터 설정을 변경하여 meta파일을 노출시키고 Asset을 text로 직렬화 하도록 합니다. material을 만들고 texture를 프로젝트에 추가합니다. 씬 안에 큐브를 만들어 material을 적용한 뒤 씬을 저장합니다.


텍스트 편집기를 사용하여  material과 연관된 .meta 파일을 엽니다. "guid"라고 표시된 줄이 파일 최상단에 나타납니다. 이 줄은 material Asset의 파일 GUID 입니다. 로컬 ID를 찾으려면 material 파일을 텍스트 편집기로 엽니다. material Object의 정의는 다음과 같습니다.


--- !u!21 &2100000

Material:

 serializedVersion: 3

 ... more data …


위의 예제에서, &가 앞에오는 숫자가 material의 로컬 ID 입니다. 이 material Object가 파일 GUID "abcdefg"로 식별되는 Asset안에 위치하면, material Object는 파일 GUID "abcdefg"와 로컬 ID 2100000로 고유하게 식별됩니다.




1.3 왜 파일 GUID와 로컬 ID 인가?

유니티의 파일 GUID와 로컬 ID가 필요한 이유는 무엇인가? 답은 견고함 그리고 플랫폼 독립적인 유연한 워크 플로우 제공을 위해서 입니다. 


파일 GUID는 파일의 특정 위치의 추상화를 제공합니다. 특정 파일과 특정 파일 GUID가 연관되어 있다면, 파일의 디스크 상의 위치는 상관 없어집니다. 파일을 참조하는 모든 Object들이 업데이트 될 필요 없이 자유롭게 파일을 옮길 수 있습니다. 


Asset 파일은 다수의 UnityEngine.Object 리소스가 포함 될 수 있기 때문에 각 Object들을 명확히 구분하기 위해서 로컬 ID가 필요합니다.


만약 Asset 파일과 연관된 파일 GUID가 손실된 경우 해당 Asset 파일을 참조하는 모든 Object들의 참조 또한 손실됩니다. 따라서 .meta파일은 연관된 Asset 파일과 같은 이름으로 같은 경로에 있어야 합니다. 유니티는 삭제되거나 잘못 배치된 .meta 파일을 다시 생성하는것을 기억하세요.


유니티 에디터는 알려진 파일 GUID들에 대한 특정 파일 경로 맵을 가지고 있습니다. Asset이 로드되거나 추가될 때 마다 맵의 항목이 기록됩니다. 맵 항목은 Asset의 특정 경로와 Asset의 파일 GUID를 연결합니다. 유니티 에디터가 열려있다면 .meta 파일이 손실되어도 Asset의 경로가 바뀌지 않았을 경우 에디터는 동일한 파일 GUID 유지를 보장합니다.


만약 유니티 에디터가 닫혀있는 동안 .meta파일이 손실되거나 경로가 변경된 Asset의 .meta파일이 함께 이동하지 않았다면 Asset을 참조하는 모든 Object들의 참조가 손실됩니다.




1.4 합성 Assets와 importer

Assets와 Objects 부분에서 언급했듯이 비 고유 Asset 타입들은 유니티로 임포트 되어야 합니다. 이 작업은 asset importer가 수행합니다. 일반적으로 자동호출 되지만 AssetImporter API를 통해 스크립트에서 노출됩니다. 예를 들어, TextureImporter API는 PNG파일과 같은 개별적인 texture Asset들을 가져올 때 사용하는 접근 설정을 제공합니다.


임포트 작업의 결과는 하나 이상의 UnityEngine.Objects 입니다. 이것들은 유니티 에디터에서 부모 Asset 하위의 여러 Asset들로 보여집니다. 예를들어 스프라이트 아틀라스로 가져온 texture Asset 아래에 내포된 다수의 sprite 들이 있습니다. 소스 데이터가 같은 Asset 파일에 저장된 Object들은 파일 GUID를 공유합니다. 각 Object는 texture Asset 내에서 로컬 ID로 구분됩니다.


이 임포트 과정은 소스 Asset들을 유니티 에디터에서 대상으로 한 플랫폼에 적합한 형식으로 변환시킵니다. 이 과정에는 texture 압축 과 같은 무거운 작업이 포함될 수 있습니다. 이 작업은 시간이 많이 소요될 수 있기 때문에, Library 폴더에 캐시되어있습니다. 따라서 다시 에디터를 실행할 때 Asset들을 임포트 하지 않습니다.


임포트 과정의 결과는 Asset들의 파일 GUID 처음 2자리로 명명된 폴더에 저장됩니다. 이 폴더는 Library/metadata/ 폴더에 저장됩니다. Asset의 개별 Object들은 Asset의 파일 GUID와 동일한 이름을 가진 단일 바이너리 파일로 직렬화 됩니다.


이 프로세스는 모든 비고유 Asset에 적용됩니다. 고유 Asset은 재 직렬화가 필요하지 않거나 변환 과정이 길지 않습니다.




1.5 직렬화와 인스턴스

파일 GUID와 로컬 ID는 견고하지만, GUID 비교는 느리고 런타임 시 더욱 성능을 요구합니다. 유니티는 내부적으로 파일 GUID와 로컬 ID들을 단순한 세션-고유의 정수 형태 캐시로[각주:2] 변환하여 유지합니다. 이는 인스턴스 ID로 부르며, 새로운 Object가 캐시에 등록될 때 마다 단순하게 증가시키며 할당됩니다.


캐시는 주어진 인스턴스 ID, 파일 GUID 및 Object들의 소스 데이터가 정의된 로컬 ID와 메모리에 있는 Object의 인스턴스 (있는 경우) 간의 매핑을 유지합니다. 이를 통해 UnityEngine.Objects는 서로간의 참조를 견고하게 유지할 수 있습니다. 인스턴스 ID의 참조를 해석하면 인스턴스 ID가 나타내는 로드된 Object를 빠르게 반환할 수 있습니다. 만약 대상 Object가 아직 로드되지 않았을 경우 파일 GUID와 로컬 ID를 통해 Object의 소스 데이터의 확인이 가능하고 유니티가 적시에 Object를 로드시킬 수 있습니다.


시작 시, 인스턴스 ID 캐시는 리소스 폴더에 포함 된 모든 Object뿐 아니라 프로젝트에서 즉시 필요한 (내장된 씬들에서 참조하는) 모든 Object에 대한 데이터로 초기화 됩니다. 캐시에 추가되는 것들은 런타임 시 새로운 Asset이 임포트 되거나[각주:3] AssetBundle에서 Object가 로드 될 경우가 있습니다. 인스턴스 ID가 캐시에서 제거되는 경우는 특정 파일 GUID나 로컬 ID에 대한 접근을 제공하는 AssetBundle이 언로드 될 때 입니다. 이 경우 인스턴스 ID와 특정 파일 GUID와 로컬 ID 사이의 매핑은 메모리 절약을 위해 삭제됩니다. 만약 AssetBundle이 다시 로드 된다면 다시 로드 된 AssetBundle에서 Object를 로드 할 때 마다 새로운 인스턴스 ID가 만들어집니다.


AssetBundle의 언로드에 대한 더 자세한 설명은 AssetBundle 사용 패턴 문서의 로드 된 Assets의 관리 부분을 참조하세요.


특정 플랫폼에서, 특정 이벤트로 인해 Object가 메모리에서 강제로 지워질 수 있습니다. 예를 들어, IOS에서 앱이 일시적으로 멈춤다면 그래픽 Asset들은 그래픽 메모리에서 언로드 될 수 있습니다. 이때 Object가 언로드 된 AssetBundle로 부터 비롯된 경우 유니티는 Object의 소스 데이터를 다리 소르 할 수 없습니다. 이 Object에 대한 어떠한 참조도 유효하지 않습니다. 이 경우 씬은 보이지 않는 메시나 자홍색 texture로 보이게 됩니다.


구현 참고 사항: 런타임 시 위의 제어 흐름은 확실하지 않습니다. 파일 GUID와 로컬 ID들의 비교는 런타임에서 무거운 로딩 작업 시 성능이 충분하지 않을 수 있습니다. 유니티 프로젝트를 만들 때, 파일 GUID와 로컬 ID는 결정적으로 단순한 형식으로 매핑됩니다. 하지만 개념은 동일하게 유지되며 런타임 시 파일 GUID와 로컬 ID에 대한 생각은 유용할 수 있습니다. 이것은 Asset 파일 GUID가 런타임 중 쿼리 될 수 없는 이유이기도 합니다.




1.6 MonoScripts

MonoBehaviour는 MonoScript에 대한 참조가 있으며 MonoScript는 특정 스크립트 클래스를 찾는데 필요한 정보를 담고 있다는 것을 이해하는 것은 중요합니다. Object 유형은 실행 가능한 어떠한 스크립트 클래스 코드도 가지고있지 않습니다.


MonoScript는 3개의 문자열을 가지고 있습니다.: 어셈블리 이름, 클래스 이름, 네임스페이스


프로젝트를 빌드하는 동안 유니티는 Assets 폴더안에 있는 모든 느슨한 스크립트 파일들을 모노 어셈블리로 컴파일합니다. Plugins 하위 폴더 외부에 있는 C# 스크립트들은 Assembly-CSharp.dll에 저장됩니다. Plugins 폴더 내부의 스크립트들은 Assembly-CSharp-firstpass.dll에 저장됩니다. 유니티 2017.3에서는 커스텀 관리 어셈블리 정의 기능을 도입하였습니다.


이 어셈블리들은 사전 빌드 된 어셈블리 DLL과 같이 유니티 어플리케이션 최종 빌드에 포함됩니다. 또한 MosoScript가 참조하는 어셈블리들이기도 합니다. 다른 리소스들과 달리 유니티 어플리케이션에 포함된 모든 어셈블리들은 어플리케이션 시작 시 로드 됩니다.


이 MonoScript Object는 AssetBundle(또는 씬이나 프리팹)이 어떠한 MonoBehaviour 컴포넌트에도 실제 실행 가능한 코드를 포함하지 않고있는 이유이기도 합니다. 이것은 MonoBehaviours가 다른 AssetBundles에 있어도 다른 MonoBehaviours가 특정 공유 클래스를 참조 가능하게 합니다.




1.7 리소스 수명주기

로딩 시간을 줄이고 어플리케이션의 메모리 공간을 관리하려면, UnityEngine.Objects의 리소스 수명주기를 이해하는것이 중요합니다. Object들은 특정 시간이나 정의된 시간에 메모리에 로드/언로드 됩니다.


Object가 자동으로 로드 되는 경우:

1. 참조되는 Object에 인스턴스 ID가 매핑 되는 경우

2. Object가 현재 메모리에 로드 되어있지 않았을 경우

3. Object의 소스 데이터가 찾아지는 경우


Object는 Object를 생성하거나 리소스 로딩 API(AssetBundle.LoadAsset)를 사용하여 스크립트에 명시적으로 로드 할 수도 있습니다. Object가 로드되면 유니티는 각 참조의 파일 GUID와 로컬 ID를 인스턴스 ID로의 변환을 시도합니다. Object는 로드됩니다. 다음 2가지 조건에 해당되면 인스턴스 ID가 처음 참조 될 때 필요할 경우 Object가 로드 됩니다.


1. 인스턴스 ID가 아직 로드 되지 않은 Object를 참조 할 경우

2. 인스턴스 ID 캐시에 유효한 파일 GUID와 로컬 ID가 등록 된 경우


이것은 보통 참조 자체가 로드된 직후에 일어납니다.


만약 파일 GUID와 로컬 ID가 인스턴스 ID를 가지고 있지 않거나 인스턴스 ID가 언로드 된 Object를 참조하는 유효하지 않은 파일 GUID나 로컬 ID를 참조한다면 참조는 유지되지만 Object는 로드되지 않습니다. 이것은 유니티 에디터에서 Missing 참조로 나타납니다. 어플리케이션 실행중이나 씬 뷰에서는 Missing Object는 그것의 타입에 따라 다른 방식으로 표현됩니다. 예를들어 메시는 보이지 않고 texture는 자홍색으로 보입니다.


Object는 3가지 특정 시나리오에서 언로드 됩니다.


● Object들은 사용되지 않는 Asset 정리가 발생하면 자동으로 언로드 됩니다. 이 과정은 씬이 파괴적으로 변경되거나 (SceneManager.LoadScene이 비가산적으로 호출 될 때), 또는 스크립트에서 Resources.UnloadUnesedAssets API를 호출하면 트리거 됩니다. 이 과정은 참조되지 않는 Object들만 언로드 합니다. Mono 변수가 Object에 대한 참조를 유지하지 않고, Object에 대한 참조를 가진 다른 활성화된 Object가 없는 경우에만 언로드 됩니다. 또한 HideFlags.DontUnloadUnusedAssetHideFlags.HideAndDontSave 표시 된 항목들은 언로드 되지 않음을 기억하세요.


● Resources 폴더에서 가져온 Object들은 Resources.UnloadAsset API를 통해 명시적으로 언로드 가능합니다. 이러한  Object의 인스턴스 ID는 계속 유효하며 유효한 파일 GUID와 로컬 ID를 유지합니다. 만약 Mono 변수나 다른 Object가 Resources.UnloadAsset 으로 언로드 된 Object를 참조하고 있다면 참조가 불릴 경우 해당 Object는 즉시 다시 로드 됩니다.


● AssetBundle에서 가져온 Object는 AssetBundle.Unload(true) API를 호출하여 즉시 언로드 됩니다. 이것은 Object 인스턴스 ID의 파일 GUID와 로컬 ID를 즉시 무효화 하고 실시간으로 참조중인 참조는 손실된 참조로 변합니다. C# 스크립트에서는 언로드 된 Object의 메서드나 속성에 접근을 시도하면 NullReferenceException이 발생합니다.


만약 AssetBundle.Unload(false)가 불리면, AssetBundle에서 불러와 작동중인 Object는 파괴되지 않지만, 유니티는 인스턴스 ID의 파일 GUID와 로컬 ID에 대한 참조를 무효화 합니다. 만약 그것들이 후에 메모리에서 언로드 되면 언로드 된 Object에 대한 참조가 남아있더라도 유니티에서 해당 Object를 다시 로드하는것은 불가능해집니다.[각주:4]




1.8 큰 계층 로드

프리팹 직렬화와 같은 유니티 GameObjects 계층을 직렬화 할 때, 전체 계층이 완전히 직렬화 되는것을 기억해야 합니다. 즉, 계층의 모든 GameObject와 컴포넌트는 직렬화된 데이터에 개별적으로 표현됩니다. 이는 계층의 GameObjects들을 인스턴스화 하고 불러오는데 필요한 시간에 흥미로운 영향을 줍니다.


GameObjects 계층을 만들 때, CPU 시간은 여러가지 방향으로 사용됩니다.

● 소스 데이터 읽기 (저장소, AssetBundle, 다른 GameObjects 등)

● 새로운 Transform 사이에서 부모-자식 관계 설정

● 새로운 GameObjects나 컴포넌트의 인스턴스화

● 새로운 GameObjects나 컴포넌트를 메인 스레드에서 깨울 때


위 4가지 중 아래 3가지의 시간 비용은 기존 계층에서 복제되거나 저장소에서 로드되는지에 관계 없이 일반적으로 변하지 않습니다. 하지만, 소스 데이터를 읽어오는 시간은 컴포넌트나 GameObjects가 계층에서 직렬화 되는 수에 따라 선형적으로 증가합니다. 그리고 데이터 소스의 속도에 따라 배가 됩니다.


모든 플랫폼에서 장치의 저장소에서 데이터를 로드 하는것 보다 메모리에서 불러오는것이 훨씬 빠릅니다. 또한 사용 가능한 저장소의 특성은 플랫폼마다 매우 다양합니다. 따라서 플랫폼의 느린 저장소에서 프리팹을 불러오면 직렬화된 프리팹 데이터를 저장소에서 읽어오는데 걸리는 시간은 프리팹을 인스턴스화 하는데 걸리는 시간을 빠르게 초과 할 수 있습니다. 즉, 로딩 작업의 비용은 저장소 I/O 시간에 종속됩니다.


앞서 언급했듯이, monolithic 프리팹을 직렬화 하면 모든 GameObjects와 컴포넌트들의 데이터가 별도로 직렬화 되고 이 데이터는 중복 될 수 있습니다. 예를 들어 UI 화면의 30개의 동일한 요소들은 30번 직렬화 되어 큰 이진 데이터가 생기게 됩니다. 로드시에는 30번 복제 된 요소의 각 GameObjects 및 컴포넌트들에 대한 데이터는 새로 인스턴스화 된 Object로 전송되기 전에 읽어져야 합니다. 이 파일 읽기 시간은 큰 프리팹의 인스턴스화에 걸리는 시간에 큰 영향을 줍니다. 큰 계층은 모듈 단위로 인스턴스화 하여 런타임 중에 합쳐야 합니다.


유니티 5.4 노트 : 유니티 5.4는 메모리의 transform 표현 방법을 변경했습니다. 각 루트 transform의 하위 계층은 작고 연속된 메모리 영역에 저장됩니다. 새로운 GameObject를 인스턴스화 할 때 다른 계층 안으로 재배치 될 예정이라면, GameObject.Instantiate 의 부모 인수를 허용하는 새 오버로드 형태의 사용을 고려해보세요. 이것을 사용하면 새 GameObject에 대한 루트 transform 계층 할당이 이루어지지 않습니다. 테스트 결과 이 경우 인스턴스화 작업에 필요한 시간이 5~10% 단축되었습니다.




  1. AA 로컬 ID는 Asset 파일 내의 다른 모든 로컬 ID에서 유일합니다. [본문으로]
  2. 내부적으로 이 캐시를 PersistentManager라고 부릅니다. [본문으로]
  3. 런타임 중 생성 된 Asest의 예는 다음과 같은 스크립트에서 만들어진 Texture2D Object가 있습니다. var myTexture = new Texture2D(1024, 768); [본문으로]
  4. 런타임 중 언로드가 일어나지 않고 Object가 메모리에서 제거되는 가장 일반적인 경우는 유니티가 그래픽 컨텍스트의 제어 권한을 상실하는 경우 입니다. 이는 보통 모바일 앱이 일시 중지되어 백그라운드로 강제 실행되는 경우 발생합니다. 이 경우 모바일 OS는 일반적으로 GPU 메모리에서 모든 그래픽 리소스를 제거합니다. 앱이 다시 활성화 되면, 유니티는 GPU가 씬을 다시 랜더링 하기 전에 필요한 모든 텍스처, 쉐이더, 메쉬를 다시 로드해야 합니다. [본문으로]

'유니티' 카테고리의 다른 글

유니티의 컴파일  (0) 2019.03.14
AssetBundle의 사용 패턴  (0) 2018.03.09
AssetBundle의 기본 요소  (0) 2018.03.07
Resources 폴더  (0) 2018.03.05
AssetBundles 및 Resources 가이드  (0) 2018.03.03

AssetBundles 및 Resources 가이드      [원본 링크]


확인 완료한 버전 2017.3 - 난이도: 고급


이것은 유니티 엔진에서 Assets와 resource 관리에 대하여 심층적인 내용을 다루는 문서 모음입니다.

상급 개발자에게 유니티의 Asset과 직렬화 시스템에 관한 깊이있는 source-level의 지식을 제공하고자합니다.

Unity AssetBundle 시스템의 기술적 도태와 현재 그것들을 사용하는 최상의 사례를 살펴봅니다.


이 가이드는 4개의 챕터로 분류되어 있습니다.


1. Assets, Objects 그리고 직렬화

유니티가 low-level에서 Assets를 어떻게 직렬화 하고 Assets간 참조를 어떻게 관리하는지에 대하여 자세한 사항을 다룹니다. 이 챕터에서 가이드 전체에서 사용하는 용어를 정의하기 때문에 이 챕터부터 읽기를 강하게 추천합니다.


2. Resources 폴더

내장 Resources API 에 대하여 설명합니다.


3. AssetBundle의 기본 요소

챕터1에서 익힌 정보를 바탕으로 AssetBundles의 작동방식을 설명하고 AssetBundles의 로드 그리고 AssetBundles에서 Assts을 로드하는 방법을 다룹니다.


4. AssetBundle 사용 패턴

AssetBuldles의 실제 사용을 둘러싼 많은 주제를 다루는 긴 문서 입니다. 이는 AssetBundles에 Assets을 할당하거나 로드한 Assets를 관리하는 내용을 포함하고 있으며, AssetBundles를 사용하는 개발자들이 자주 접하는 문제를 설명합니다.


참고: 이 가이드에서 사용하는 용어 Objects와 Assets는 유니티의 공개 API에서 사용하는 명명 규칙과 다릅니다.

이 가이드에서 Objects라고 부르는 데이터는 AssetBundle.LoadAsset이나 Resources.UnloadUnusedAssets와 같은 유니티 공개 API에서 Assets라고 부릅니다. 이 가이드에서 Assets라고 부르는 파일들은 공개 API에서 잘 노출되지 않습니다. 일반적으로 노출 될 경우 AssetDatabaseBuildPipeline같은 빌드 관련 코드에서만 노출됩니다. 이 경우 공개 API에서는 files라고 부릅니다.


'유니티' 카테고리의 다른 글

유니티의 컴파일  (0) 2019.03.14
AssetBundle의 사용 패턴  (0) 2018.03.09
AssetBundle의 기본 요소  (0) 2018.03.07
Resources 폴더  (0) 2018.03.05
Assets, Objects 그리고 직렬화  (0) 2018.03.04

행 집합을 다루는데 편리한 기능

성능을 크게 떨어뜨리는 요인이라 사용을 자제하는것이 좋음


여러 개의 행을 쿼리한 후에 쿼리의 결과인 행 집합을 한 행씩 처리하기 위한 방식



커서의 처리 순서

커서 선언 (declare)

커서 열기 (open)

-------------------------------------------

커서에서 데이터 가져오기 (fetch)

데이터 처리

------------------------------------------- while문으로 모든 행이 처리될 때까지 반복

커서 닫기 (close)

커서의 해제 (deallocate)



커서의 확장 구문

[local/global] 디폴트는 global

local

지역 커서는 지정된 범위 안에서만 유효하며 해당 범위를 벗어나면 소멸함

프로시저에서 output 매개변수로 커서를 밖으로 돌려주면 커서를 참조하는 변수가 해제되거나 소멸할 때 같이 커서도 소멸됨 (close, deallocate 자동)


global

전역 커서는 모든 프로시저나 일괄처리에서 커서의 이름을 참조 가능


[forward_only/scroll]

forward_only

시작 행부터 끝행의 방향으로만 커서가 이동함

사용 가능한 데이터 가져오기는 detch next 한정


scroll

커서 이동이 자유로움

fetch next, first, last, prior 등 여러가지 사용 가능


[static/dynamic/keyset/fast_forward] 디폴트는 dynamic

static

원본 테이블을 tempdb로 가져올 때 사용할 데이터를 보두 복사해서 데이터를 사용함

커서의 선언 이후 원본 테이블에 변경사항이 있어도 커서에서는 변경 전 데이터를 사용하여 변경 사항을 알 수 없음


dynamic

행 데이터를 가지고 올  때마다 원본 테이블에서 가져옴

원본 테이블의 update, insert 내용이 모두 보임


keyset

모든 키 값을 tempdb에 저장

원본 테이블의 update 된 내용만 보이며 insert된 내용은 보이지 않음

keyset을 사용하려면 원본 테이블에 꼭 고유 인덱스(unique key)가 있어야 함 


fast_forward

forward_olny와 read_only 옵션이 합쳐진 것

커서에서 행 데이터를 수정하지 않을 것이라면 가장 바람직한 옵션


[read_only, scroll_locks, optimistic]

read_only

읽기 전용으로 설정하는 것


scroll_locks

위치 지정 업데이트나 삭제가 가능하도록 설정하는 것


optimistic

커서로 행을 읽어들인 후 원본 테이블의 행이 업데이트 되었다면 커서에서 해당 행을 위치 지정 업데이트나 삭제하지 않도록 지정



type_warning

요청한 커서 형식이 다른 형식으로 암시적으로 변환된 경우 클라이언트에 경고 메시지를 보내는 것

예를 들어 코유 인덱스가 없을 때 keyset 커서 를 만들려고하면 암시적 변환이 작동해 static 커서로 만들어짐

이 엽션을 설정하지 않으면 아무 메시지가 나오지 않아 알수없음

이 옵션을 설정하면 문제를 미리 경고 메시지로 확인 가능함



FORselect_statement

select 문장을 사용하는 부분

select문의 결과가 한 행씩 처리됨

compute, compute by, for browse, into 키워드는 사용 불가



for update [of column_name [...n]]

그냥 for update만 지정하면 select 문의 모든 열을 업데이트 가능

of 열이름 을 지정하면 특정 열 지정 가능




커서 사용 시 기본적으로 전역 커서로 열기를 시도함

만약 지역, 전역에 같은 이름의 커서가 있다면 지역이 우선 됨

같은 이름이 있다면 꼭 global 키워드를 써줘야 전역 커서 열기 가능



'MSSQL' 카테고리의 다른 글

사용자 정의 함수  (0) 2016.03.10
블로킹과 교착상태  (0) 2016.03.10
트랜잭션과 잠금  (0) 2016.03.10
저장 프로시저  (0) 2016.03.10
인덱스  (0) 2016.03.10


프로시저와 비슷해 보이지만 일반 프로그래밍 언어에서 사용되는 함수와 갗이 복잡한 프로그래밍이 가능하며 return문에 의해 특정 값을 돌려주는 기능이 있음

select문에 포함되어 실행 가능하며 스칼라 함수는 exec로 실행 가능


시스템 함수

sql server 에서 제공하는 함수


사용자정의 스칼라 값 함수

리턴 값이 단일 값인 함수로서 text, ntext, image, cursor, timestamp를 제외한 모든 데이터 형식이 가능



사용자정의 테이블 값 함수

테이블 함수 라고도 하며 리턴 값이 테이블인 함수

인 라인 테이블 함수, 다중 문 테이블 함수가 있음


인 라인 테이블 함수

테이블을 돌려주는 함수이며 뷰와 비슷한 역할을 함

select문이 와서 결과 집합을 돌려줌


다중 문 테이블 함수

begin ~ end 로 정의되며 내부에 일련의 T-SQL을 이용해서 반환될 테이블에 행 값을 insert 하는 형식을 가짐



스키마 바운드 함수

테이블, 뷰 등이 수정되지 못하도록 설정한 함수

예를 들어 함수A가 테이블B, 뷰C 를 참조하고 있다면 이 테이블이나 뷰를 삭제하거나 열 이름을 바꾸지 못하게 함

함수 생성 시 with schemabinding 옵션을 주면 됨


사용자 정의 함수에서는 try~catch 사용이 불가하며 create, alter, drop또한 사용이 불가능함

함수 실행 중 오류가 발생하면 함수의 실행이 멈추고 값을 반환하지 않음


'MSSQL' 카테고리의 다른 글

커서  (0) 2016.03.10
블로킹과 교착상태  (0) 2016.03.10
트랜잭션과 잠금  (0) 2016.03.10
저장 프로시저  (0) 2016.03.10
인덱스  (0) 2016.03.10


트랜잭션이 발생할 경우 개체에 접근할 수 없는 것을 블로킹이라고 함

만약 트랜잭션을 끝내지 않아 무한대로 기다리는 상황이 생길 수 있어 이것을 막기위해 타임아웃 옵션을 설정할 수 있음


select @@LOCK_TIMEOUT 로 조회 가능하며 -1 일 경우 무한대로 대기함


exec sp_who 프로시저로 블로킹 중인 프로세스 확인이 가능하며 kill프로세스로 해당 프로세스를 중단시킬 수 있음


set lock_timeout 1000 식으로 설정 가능하며 단위는 밀리초 이므로 1000 = 1초 임


타임아웃이 지난다고 트랜잭션이 취소되는 것은 아니며, 잠금이 걸린 데이터에 접근하는 쿼리를 취소하는 것임



두 잠금이 서로 상대가 풀리도록 대기하는 상태를 교착상태라고 함

서로 풀릴때까지 기다리느라 무한대로 멈추어야하지만 sql server에서 이런 상황을 자동으로 검색하여 한쪽을 희생시켜 해결 함 (검색 주기 디폴트 5초)

이 또한 시스템 자원을 소모하므로 성능을 위해 이런 상황을 만들지 않는게 좋음

되도록 트랜잭션 격히 수준을 read committed로 두고 하나의 트랜잭션에 너무 많은 쿼리를 넣지 않아야 함



분산 트랜잭션

서로 다른 서버에서 하나의 트랜잭션으로 데이터를 처리하는것

개념적으로는 하나의 트랜잭션이며 서버가 분리되어있다는 것만 차이 있음

begin tran 대신 begin distributed transaction을 사용하며 커밋은 동일하게 commit tran을 사용

분산 트랜잭션을 사용할떄는 xact_abort 옵션을 on으로 설정해야함

xact_abort를 on으로 설정하면 하나의 트랜잭션이 오류를 일으키면 전체 트랜잭션을 취소하므로 분산 트랜잭션에서는 꼭 ON으로 설정해야함 디폴트는 OFF임


또한 분산 트랜잭션을 사용하기 위해서는 MS DTC가 설치되고 가동되고 있어야 함


'MSSQL' 카테고리의 다른 글

커서  (0) 2016.03.10
사용자 정의 함수  (0) 2016.03.10
트랜잭션과 잠금  (0) 2016.03.10
저장 프로시저  (0) 2016.03.10
인덱스  (0) 2016.03.10

+ Recent posts