블로그 이미지
자신의 단점을 메꾸는 것을 단(鍛)이라 하고 자신의 강점을 갈고 닦는 것을 련(鍊)이라 하여, 두가지를 합친 것을 단련이라고 부른다. 붕대마음

카테고리

전체목록 (666)
참고사이트 (8)
Goal (4)
Travel (10)
My Life (105)
Game (35)
Game Review (7)
Game Plan (0)
Books (5)
English (1)
Optimizing (12)
Study (217)
유용한 것들_etc (44)
유용한 것들_func (20)
Unity (48)
Unreal (87)
작업장 (54)
RenderMonkey (6)
정리요망 (1)
따라잡기 시리즈 (0)
링크용 (0)
Total343,756
Today5
Yesterday73

unity의 awake

Unity/Unity Study / 2017.09.24 13:15

script 함수 실행 순서는 awake, onenable, start다. 

이건 알고있던 건데 작업을 하다가 자꾸 awake에 에러가 나서 에러를 찾다보니

하이라키에서 활성화 되어 있는오브젝트에 비활성화로 달려있는 컴포넌트였다.


여기에 붙어있는 컴포넌트의 내용은 아래와 같다.

public class TestAwake : MonoBehaviour 

{

    void Awake()    {        Debug.Log("Awake");    }

    void OnEnable() { Debug.Log("OnEnable"); }

    void Start () {    Debug.Log("Start"); }

    void Update () {  Debug.Log("Update"); }

}


똑같은 상태에서 TestAwake 컴포넌트의 active만 꺼 두면 어떻게 될까?

나의 예상과는 다르게 Awake는 무조건 호출이 된다.


Awake는 컴포넌트의 active 상태와 상관없이 호출이 되고 Start함수는 active 된 상태에서만 호출이 된다.

Awake 함수는 컴포넌트의 스크립트의 활성화 여부에 상관없이 컴포넌트의 오브젝트가 초기화 될 때 호출되기 때문이다.


그래서 위와 같이 컴포넌트의 오브젝트가 비활성화 되어 있으면 초기화가 안되어 컴포넌트 자체의 awake도 호출되지 않는다.





Reference Link

- MonoBehaviour.Awake()

-



'Unity > Unity Study' 카테고리의 다른 글

unity의 awake  (0) 2017.09.24
ExecuteInEditMode  (0) 2017.09.13
Inspector에서 AnimationCurve 버그  (0) 2017.07.21
unity에서 shader를 짤때..  (0) 2017.07.10
ARB_precision_hint_fastest  (0) 2017.07.10
The Magic Of Material Property Blocks  (0) 2017.06.23
Posted by 붕대마음
TAG AWAKE, Unity

댓글을 달아 주세요

작업할때 디자이너분들이 작업하기 편하게 "ExecuteInEditMode"를 자주 쓰는 편인데

어느날 에디터 실행후 종료시에 이상한 에러가 뜬다.

봤더니 에디터 실행 후 종료시에 ExecuteInEditMode 코드가 있는 스크립트의 start 함수가 호출된다.

누가 호출하는걸까..콜백도 없고...

그래서 디버그를 다 찍어서 editor을 실행하니 ExecuteInEditMode 코드가 있는 스크립트에서는


1. 에디터 실행 - script의 OnDestroy 실행, Start 실행

2. 에디터 종료 - script의 OnDestroy 실행, Start 실행


위와 같은 루틴을 탄다.



[ExecuteInEditMode]

public class ExecuteTest : MonoBehaviour {


// Use this for initialization

void Start () {

Debug.Log("Start");

}

// Update is called once per frame

void Update () {

Debug.Log("Update");

}


void OnDestroy()

{

Debug.Log("OnDestroy");

}

}


위 코드를 하이라키에 오브젝트 하나 만들어 add 시킨 후 테스트 해 보면 

아래와 같이 로그가 찍힌다.


에디터 실행..............................................에디터 종료.......................................

OnDestroy -> Start -> Update -> OnDestroy -> Start -> Update



에디터에서만 이렇게 동작하겠지만...

'Unity > Unity Study' 카테고리의 다른 글

unity의 awake  (0) 2017.09.24
ExecuteInEditMode  (0) 2017.09.13
Inspector에서 AnimationCurve 버그  (0) 2017.07.21
unity에서 shader를 짤때..  (0) 2017.07.10
ARB_precision_hint_fastest  (0) 2017.07.10
The Magic Of Material Property Blocks  (0) 2017.06.23
Posted by 붕대마음

댓글을 달아 주세요

1. 빈 프로젝트를 하나 만든다.

2. 스크립트를 하나 만든다.

3. 스크립트에 아래와 같이 AnimationCurve를 아래이름으로 만든다.

public class NewBehaviourScriptf : MonoBehaviour {


public AnimationCurve rgbUR_ = AnimationCurve.Linear(0, 0, 1, 1);

public AnimationCurve rgbVB_ = AnimationCurve.Linear(0, 0, 1, 1);

}

4. 인스펙터창 비교


위와 같이 두개의 속성값이 생기는데 위의 값을 변경하면 아래 값도 자동으로 바뀐다.

위의 값을 위와 같이 대충 바꿔주면

이렇게 아래값도 위의 값과 같이 바뀌었다.

하지만 아래값을 실제로 눌러보면 아래와 같이 정상적으로 표현된다.



머지 이현상은..

실제로 값도 정상적으로 반영된다. 단지 인스펙터창에서만 이상하게 보일 뿐.

변수 이름을 좀 바꾸면 괜찮던데 변수 이름을 저렇게 두면 이런 버그가 생긴다. 

테스트는 아무것도 없는 빈 프로젝트를 만들어서 스크립트를 생성해 위의 코드만 추가해서 테스트 하였다.


'Unity > Unity Study' 카테고리의 다른 글

unity의 awake  (0) 2017.09.24
ExecuteInEditMode  (0) 2017.09.13
Inspector에서 AnimationCurve 버그  (0) 2017.07.21
unity에서 shader를 짤때..  (0) 2017.07.10
ARB_precision_hint_fastest  (0) 2017.07.10
The Magic Of Material Property Blocks  (0) 2017.06.23
Posted by 붕대마음

댓글을 달아 주세요

이전에 PC시절에는 HLSL을 사용했고 언렬3에서는 glsl을 사용했는데 유니티로 넘어와서는

처음에는 surface shader를 사용하다가 뭔가 찜찜하고 애매하고, 새 문법도 자주 까먹고,

내가 surface shader로 짜도 유니티가 vertex, fragment로 자동으로 변환해 주는데 이 과정도 없었으면 좋겠고 해서,

그냥 cg로 짜다보니 그냥 맘편히 계속 cg로 짜게 되었다.

다른 사람은 surface가 편하다고 하는데 나도 옛날 마인드인가 그냥 손에익은게 편한듯...


실제로 surface shader로 만들어진 shader 파일을 보면 인스펙터 창에 아래와 같이 generated code 버튼이 있다.

이 버튼을 누르면 자동으로 vertex, fragment shader로 변환된 코드를 보여준다.


surface shader를 사용하지 않고 vertex, fragment shader로 구현한 shader 파일은 아래와 같이 보인다.


surface shader는 실제 cg라기 보다는 unity 매크로로 이루어진 거라 cg로 한번 변환이 들어간다.

어차피 이 변환이 게임 성능이나 퍼포먼스에는 영향이 미치지 않겠지만 만들어준 코드를 보면

그냥 내가 내입맞대로 잘 짜는게 더 좋을것 같다.

그래도 surface shader는 입맛에 맞다면 나름 좋은 방식인 것 같다.

겉으로는 코드가 단순해지고 코딩 시간이 줄기 때문이다.


출처 : unity shader system


위 이미지는 cg/hlsl을 glsl로 변환하는 과정을 도식화 한 것이다.

cg로 shader를 짜면 이를 중간중간에 들어간 shaderlab 코드를 cg로 만들어 주고 이를 다시 hlsl로 만들어 준다.

그리고 다시 이를 glsl로 변환하고 최적화를 두번 해 준다.


여기서 드는 생각.

1. Cg랑 HLSL이랑 이 두 언어는 분명 다른언어인데 유니티는 왜 똑같이 취급할까?

간단하게 정리하자면 Cg랑 HLSL이랑 문법이 거의 똑같고 호환이 잘되서 걍 하나라고 말하는 듯 하다.

실제로는 Cg는 nvidia, hlsl은 microsoft거니까.. 자세히 알아보길 원한다면 아래 참고사이트를 보면 굳굳.

cg == hlsl or cg != hlsl

cg vs glsl 비교

셰이더 종류


2. 완벽하게 내입맛대로 유니티가 자동르로 바꾸는 구문없는 shader를 만들기 위해 glsl로 짜는게 좋을까?

유니티에서는 shader를 작성할 때 cg처럼 glsl도 가능하다.

CGPROGRAM 처럼 GLSLPROGRAM을 지원한다.

하지만 raw GLSL은 테스트 목적으로만 권장하며 특정 디바이스에 맞게 사용할 때만 사용해야 한다.

위의 이미지를 보면 cg/hlsl -> glsl의 변환은 지원을 하지만 glsl -> cg/hlsl의 변환은 지원하지 않는다.


유니티 도큐먼트를 보면..

"ShaderLab 내의 Shader들은 CG/HLSL 프로그래밍 언어로 작성되었다.

Cg와 Dx9-Styile HLSL 은 실제로 하나이고 같은 언어이며, 그래서 CG와 HLSL을 교대해서 쓸 수 있다.

(자세한 내용은 이곳을 참조하세요.)


Reference Link

- What would you choose to write unity shaders GLSL, HLSL/CG or Surface lang?

- unit doc, GLSL 쉐이더 프로그램

- unity doc, Shader Compilation for Multiple Platforms

- unity doc, Shading Language used in Unity

- unity shader system

- cg == hlsl or cg != hlsl

- cg vs glsl 비교

- 셰이더 종류

- Shader Compilation for Multiple Platforms

-

'Unity > Unity Study' 카테고리의 다른 글

ExecuteInEditMode  (0) 2017.09.13
Inspector에서 AnimationCurve 버그  (0) 2017.07.21
unity에서 shader를 짤때..  (0) 2017.07.10
ARB_precision_hint_fastest  (0) 2017.07.10
The Magic Of Material Property Blocks  (0) 2017.06.23
RenderQueue  (0) 2017.06.21
Posted by 붕대마음

댓글을 달아 주세요

khronos group에 적혀있는 내용을 보면...


+ Precision Hints (ARB_precision_hint_fastest, ARB_precision_hint_nicest)


Fragment program computations are carried out at an implementation-

dependent precision.  However, some implementations may be able to perform

fragment program computations at more than one precision, and may be able

to trade off computation precision for performance.

프래그먼트 프로그램 계산은 정밀도에 의존 구현을 수행한다.

하지만 몇몇 구현은 하나 이상의 정밀도로 프래그먼트 프로그램 계산이 수행될 수도 있으며,

성능을 위해 계산 정밀도를 트레이드 오프 할 수도 있다.


If a fragment program specifies the "ARB_precision_hint_fastest" program

option, implementations should select precision to minimize program

execution time, with possibly reduced precision.  If a fragment program

specifies the "ARB_precision_hint_nicest" program option, implementations

should maximize the precision, with possibly increased execution time.

만약 "ARB_precision_hint_fastest"프로그램 옵션을 프로그먼트 프로그램에 명시하면,

구현시 최소  프로그램 실행 시간을 위해 정밀도를 선택하며 정밀도는 감소한다.

만약 "ARB_precision_hint_nicest"프로그램 옵션을 프로그먼트 프로그램에 명시하면,

구현시 최대 정밀도로 구현되며 실행시간은 증가 할 수 있다.


Only one precision control option may be specified by any given fragment

program.  A fragment program that specifies both the

"ARB_precision_hint_fastest" and "ARB_precision_hint_nicest" program

options will fail to load.

반드시 프로그래먼트 프로그램에 하나의 옵션만 명시해야 한다.

위의 옵션을 둘 다 준다면 로드는 실패할 것이다.


Reference Link

- khronos, fragment program4

-

'Unity > Unity Study' 카테고리의 다른 글

Inspector에서 AnimationCurve 버그  (0) 2017.07.21
unity에서 shader를 짤때..  (0) 2017.07.10
ARB_precision_hint_fastest  (0) 2017.07.10
The Magic Of Material Property Blocks  (0) 2017.06.23
RenderQueue  (0) 2017.06.21
There are inconsistent line endings  (2) 2017.06.20
Posted by 붕대마음

댓글을 달아 주세요

이 글은 번역글입니다. 

원문을 참고하시길 강력권장합니다.

원문 : http://thomasmountainborn.com/2016/05/25/materialpropertyblocks/


MaterialProperyBlocks과 관련 API인[PerRendererData]을 발견했는데 무척 유용하긴 한데 정보가 별로 없다.

그래서 관련 API들이 어떤일을 하는지, 어떻게 쓰는게 가장 좋은지를 빠르게 정리하기로 했다.

만약 아직 이들에 대해 잘 모른다면, 이들은 분명 유니티 스킬에 좋은 도구가 되어 줄것이다.

자, 이제 어떻게 사용되는지 한번 살펴보자.

한 오브젝트의 색상이 애니메이트 되야 한다고 가정해 보자.

앞에서 이야기 했던건 무시하고, 2500개의 오브젝트가 색상이 애니메이트 되야 한다고 가정해 보자.


마음속에 가장먼저 떠오른 것은 아래 내용을 것이다.

1
GetComponent<Renderer>().material.color = ...


간단하지 않은가? 단지 색상만 바뀌고 애니메이트 되지는 않는다.

문제는 셰이더에서 색상을 바꾸기 위해 유니티가 GPU에게 이 오브젝트는 다르게 그려질 거야 라고

말해야 하며, 유일한 방법은 머티리얼 인스턴스를 바꾸는 것이다.

이 때문에, 유니티는 renderer.material에 처음 접근할 때

(비록 그 렌더러가 이미 그 머티리얼을 사용하는 유일한 렌더러가 아닐지라도)

머티리얼의 카피본을 만든다.

이 카피본은 그 renderer. 이후에 사용된다.

(이 카피본은 자동으로 파괴되지 않는것에 주의하자. 자기가 만든 메모리 릭은 자기가 제거해야 한다)


이는 메모리를 소비하는 머터리얼 복사본이 많이 존재할 수 있음을 의미한다.

아래 그림은 모든 구체가 하나의 고정 머티리얼을 사용했을때 메모리 프로파일러 모습이다.

scene에 40개의 머티리얼이 존재하고 47 KB정도를 필요로 하는것에 주목하자.

40개의 머티리얼중 오직 하나만이 우리의 구체에 사용되며, 나머지는 

평면이나 스카이박스등에 사용되는 기본 머티리얼이다.


이제, renderer.material을 사용할 때 메모리 프로파일러의 내용을 보자.

예상한대로, 2500개의 머티리얼이 생성되었다.

6 MB정도는 기가바이트 단위의 세계에서 그다지 커 보이지 않지만, 꽤나 많이 증가했다.

하지만, 내 생각엔 단지 몇메가 바이트를 아끼기 위해 이 글을 읽으려 하지 않을 것이다.

핵심 이슈를 보자 : GPU에 머티리얼을 변경을 업로딩 하기 위해 상당한 CPU 오버헤드가 있다.

2500개의 머티리얼들이 renderer.material을 사용하여 애니메이팅 될 때 CPU 프로파일러를 보자.

소중한 15.19 밀리세컨 시간이 가버렸다!

이 시간들을 다시 돌려 다른 유용한 곳에 잘 사용하고 싶어할 거라고 것이다.

예를 들자면 90 FPS에 도달하는것이다.

이제 MaterialPropertyBlocks과 [PerRendererData]을 만나보자.

이들은 이전과 정확하게 같은 scene에 대한 프로파일러지만, renderer.material 대신에 앞서말한 기술을 사용한다.


보이는가?

같은 효과에 0.01 밀리세컨이 걸린다.

이게 바로 승리이지 않은가.

강조된 두꺼운 녹색 띠가 어떻게 사라졌는지 살펴보자.

또한 모든 구체가 사실 같은 머티리얼을 사용하여 메모리 사용량이 단일 고정 머티리얼을 

사용할 때의 상태로 돌아간 사실을 알수 있다.


이 기술의 가치를 확인 했으므로 이제 직접 구현해 보자.

우선, 커스텀 셰이더를 만들어야 한다.

만약 셰이더 작성에 익숙하지 않다고 해도 조바심 내거나 할 필요가 없다.

그냥 프로젝트 탭에서 "Create"메뉴로 "Standard Surface Shader"를 만들면 된다.

그리고 나서, _Color 프로퍼티 앞에 [PerRendererData]를 추가하자.

이 속성은 셰이더를 사용하는 모든 렌더러에 공유되는 대신

_Color 속성이 렌더러 별로 설정되는 방식으로 유니티에 셰이더를 컴파일 하도록 요청한다.

(이러면 셰이더 컴파일 시간이 많이 늘어나지 않을까?)

이 속성은 모든 셰이더 프로퍼티에 추가할 수 있다.

1
2
3
4
5
6
7
Properties
{
    [PerRendererData]_Color ("Color", Color) = (1,1,1,1)
    _MainTex ("Albedo (RGB)", 2D) = "white" {}
    _Glossiness ("Smoothness", Range(0,1)) = 0.5
    _Metallic ("Metallic", Range(0,1)) = 0.0
}

에디터에서 이 셰이더를 사용하는 머티리얼을 만들어 메시에 적용시키자.

머티리얼 에디터에 색상값 속성이 없어진 걸 확인할 수 있으며, 렌더 프로퍼티는 

스크립트에 의해서만 변경될 수 있다.

그러면 어떻게 스크립트에서 렌더러 데이터를 변경하는지 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class SphereWithMaterialPropertyBlock : MonoBehaviour
{
    public Color Color1, Color2;
    public float Speed = 1, Offset;
 
    private Renderer _renderer;
    private MaterialPropertyBlock _propBlock;
 
    void Awake()
    {
        _propBlock = new MaterialPropertyBlock();
        _renderer = GetComponent<Renderer>();
    }
 
    void Update()
    {
        // Get the current value of the material properties in the renderer.
        _renderer.GetPropertyBlock(_propBlock);
        // Assign our new value.
        _propBlock.SetColor("_Color", Color.Lerp(Color1, Color2, (Mathf.Sin(Time.time * Speed + Offset) + 1) / 2f));
        // Apply the edited values to the renderer.
        _renderer.SetPropertyBlock(_propBlock);
    }
}

중요한 코드는 Update()에 있다.

두번째 줄을보면 MaterialPropertyBlock에 셰이더 프로퍼티를 쓰기 위해 SetColor()을 사용하였다.

MaterialPropertyBlock 클래스는 키와 값을 가지는 일반적인 c# 클래스보다 특별한건 없다.

키는 셰이더 프로퍼티 이름이며 값은 무슨값이든 해당속성으로 원하는 값을 넣으면 된다.


renderer.SetPropertyBlock()을 사용하여 렌더러에 새로운 값을 적용할 수 있다.

모든 작업이 완료되었다.

하지만, 렌더러의 프로퍼티 블럭을 설정하면 그 렌더러의 프로퍼티 블럭으로 다른 데이터를

덮어쓴다는 것을 아는것이 중요하다.

만약 새 프로퍼티 블럭이 기존의 값들을 가지고 있지 않다면, 값은 재설정 될 것이다.

즉, 머티리얼 프로퍼티 블럭을 통해 렌더러에 영향을 주는 여러 스크립트가 있는 경우

서로 영향을 미치게 된다.

그러므로 항상 새 값으로 바꾸기 전에 현재 프로퍼티 값을 먼저 얻자.

이 부분에 대한 내용은 Update()의 첫번째 줄에 있다.

걱정하지 마라, 이는 GPU에서 검색하는 것이 아니고 일반 메모리에 있는 데이터일 뿐이다.


[PerRendererData]키워드가 없는 셰이더 속성에서도 renderer.SetPropertyBlock()을 사용할 수는 있지만

이렇게 하면 유니티가 내부적으로 새 머티리얼 인스턴스를 만든다.


마지막으로 가장 좋은 연습은 MaterialPropertyBlock 인스턴스에 대한 필드 레퍼런스를 유지하는 것이다.

이는 실제 재질로 나중에 Destroy 시켜야 하기 때문이 아니라(MaterialPropertyBlock는 일반적인 C#클래스 임을 기억해라)

가비지에 콜렉트되어야 하는 새로운 오브젝트를 매 프레임마다 힙에 생성하지 않기 위해서 이다.

이렇게 MaterialPropertyBLock 과 [PerRendererData]에 대해 전반적으로 알아봤다.

15.19 밀리초 에서 0.01초 줄어든다.

이 API를 잘 활용할 수 있길 바란다.

한가지 아쉬운 점이 하나 있는데 모든 개체가 동일한 머티리얼을 공유하더라도

MaterialPropertyBlocks는 동적 일괄 처리(dynamic batching)를 해 주지 않는다.


Reference Link

- unity, MaterialPropertyBlock

- Learn how to use MaterialPropertyBlocks and [PerRendererData] for great performance gains!

- unity, Renderer.Material

- unity, Renderer.SharedMaterial

- material과 shareMaterial, 그리고 Material Property Block

-

'Unity > Unity Study' 카테고리의 다른 글

unity에서 shader를 짤때..  (0) 2017.07.10
ARB_precision_hint_fastest  (0) 2017.07.10
The Magic Of Material Property Blocks  (0) 2017.06.23
RenderQueue  (0) 2017.06.21
There are inconsistent line endings  (2) 2017.06.20
assetbundle building, change file  (0) 2017.06.03
Posted by 붕대마음

댓글을 달아 주세요

RenderQueue

Unity/Unity Study / 2017.06.21 12:29

유니티에서는 Queue를 설정해서 오브젝트를 그릴 순서를 조절할 수 있다.

셰이더는 오브젝트가 속하는 render queue를 결정하며, 이 방법에 의해 어떠한

반투명 셰이더들도 불투명 오브젝트들 이후에 그려지게 보장한다.


유니티 도큐에 보면 아래와 같이 되어있다.


Background : 가장 먼저 그려짐

Geometry : 불투명(Opaque) 물체

AlphaTest : 알파테스트 물체

GeometryLast : 불투명(Opaque)에서 가장 나중에 그려짐.

Transparent : Geometry와 AlphaTest 이후에 그려짐. 순서는 뒤에서부터 앞으로.

Overlay : 중첩되는 효과.


큐 사이에서 좀 더 특별하게 사용할 수도 있다. 내부적으로 각 큐들은 정수 인덱스로 표시된다.

Background는 1000, Geometry는 2000, AlphaTest는 2450, Transparent는 3000, 그리고 Overlay는 4000이다.

만약 셰이더에서 쓸려면 아래와 같이 하면 된다.

Tags { "Queue" = "Geometry+1"}

이렇게 하면 이 오브젝트는 모든 불투명(opaque) 오브젝트들이 그려지고 나서, 그리고 반투명 오브젝트들 이전에

그려지며, render queue 인덱스는 2001이 될 것이다.(geometry +1)

이 기능은 특정 오브젝트가 항상 다른 오브젝트들 사이에 그려져야 할 때 유용하다.

예를 들자면, 대부분의 경우 반투명 물은 불투명 오브젝트보다 나중에, 반투명 물체이전에 그려져야 한다.

2500번까지는(Geometry+500) "반투명(Opaque)"로 간주되며 최상의 퍼포먼스를 위해 객체의 그리기 순서를 최적화 한다.

더 높은 큐 값은 "불투명(Transparent) 오브젝트"로 간주되며 거리에 따라 정렬된다.

스카이박스는 모든 불투명(Opaque)와 모든 반투명(Transparent) 사이에 그려진다.


대충 내용은 위와 같고 이를 실제로 사용하는 방법을 좀 보자.

우선 머티리얼을 하나 만들면 머티리얼에 아래와 같은 값이 있다.

예전부터 있던건지는 잘 모르겠지만 큐브와 스피어를 몇개 만들어서 테스트를 해 봤다.

Shader는 그냥 유니티가 제공하는 Unlit Color을 사용했다.


다 같은 셰이더를 사용하고 있다.

처음 만들면 Render Queue는 "From Shader"로 되어있고 여기에 내가 수정하면(예를들어 2050) "Custom"으로 자동으로

바뀌며, 다시 원래값인 2000으로 바꾸면 "Geometry"가 된다.

값을 2050로 바꿔서 "Custom" 으로 바꾼 상태에서 "Geometry"나  "From Shader"로 바꾸면 다시 값이 2000이 된다.


못찾은 건지 인스펙터창에서 이 옵션에 대한 내용은 없어서... 적당히 정리해 보자면

From Shader : shader 파일에 설정한 값을 우선으로 한다. 

  예를들어 "RenderType"="Opaque" "Queue" = "Geometry+100"의 경우 인스펙터에서 From Shader라면 

  자동으로 2100이 된다.

Geometry : Shader에 설정된 값을 무시하고 그냥 Geometry 값인 2000 설정한다.

AlphaTest : Shader에 설정된 값을 무시하고 그냥 AlphaTest 값인 2450으로 설정한다.

Transparent : Shader에 설정된 값을 무시하고 그냥 Transparent값인 3000으로 설정한다. 

Custom : 0~5000까지의 값을 지원한다.


테스트를 해 보자.

위와같이 네가지를 설정해 주었으며 From Shader는 위에서 설정한 대로 "Geometry+100" 이다.

렌더링을 하면 순서는 아래와 같다.

위에 두개는 불투명으로 해서 순서대로 그려지고 뒤에 두개는 반투명으로 해서 두개가 그려진다.


결국은 셰이더에 작업을 잘 해도 디자이너분이 저 값을 인스펙터에서 건드는 순간 셰이더에서 설정한 값 보다

인스펙터값을 우선하게 된다.


Reference Link

- unity, RenderQueue

- unity, material.renderQueue

- unity, ShaderLab: SubShader Tag

-

'Unity > Unity Study' 카테고리의 다른 글

ARB_precision_hint_fastest  (0) 2017.07.10
The Magic Of Material Property Blocks  (0) 2017.06.23
RenderQueue  (0) 2017.06.21
There are inconsistent line endings  (2) 2017.06.20
assetbundle building, change file  (0) 2017.06.03
메모리 프로파일러  (0) 2017.05.19
Posted by 붕대마음

댓글을 달아 주세요

There are inconsistent line endings in the 'Assets/Scripts/SomeThing.cs' script. Some are Mac OS X (UNIX) and some are Windows.

This might lead to incorrect line numbers in stacktraces and compiler errors. Many text editors can fix this using Convert Line Endings menu commands.


유니티에서 가끔 위와같은 경고가 찍힌다.
대략적인 내용은 아래와 같다.

스크립트의 줄끝이 명확하지 않습니다. 
어떤건 Mac을 따르고 어떤건 Window를 따릅니다.
이렇게 되면 나중에 컴파일러 오류시 스택 추적할 때 잘못된 행번호가 찍힐 수 있다.
Convert Line Ending 메뉴명령을 사용해서 문제를 해결해라.

대략 디버깅때 문제될 수 있으니까 정리하는걸 권고한다는 내용인듯하다.

그런데 사실 여러명이 작업하다 보니 이런게 은근 많이 발생한다.

그래서 기능을 만들어 볼까 하다가 구글링 해 보니 역시 먼저 작업해서 올려주신 분이 있다.

그대는 멋쟁이!!


이곳을 참조하자

코드를 대략적으로 살펴보면 폴더경로에 해당 확장자 파일을 찾아서 라인의 끝을 바꿔준다.




'Unity > Unity Study' 카테고리의 다른 글

The Magic Of Material Property Blocks  (0) 2017.06.23
RenderQueue  (0) 2017.06.21
There are inconsistent line endings  (2) 2017.06.20
assetbundle building, change file  (0) 2017.06.03
메모리 프로파일러  (0) 2017.05.19
Asset Bundles vs. Resources : A Memory Showdown  (0) 2017.04.14
Posted by 붕대마음

댓글을 달아 주세요

  1. 2018.01.26 10:38 dre0112  댓글주소  수정/삭제  댓글쓰기

    감사합니다. 덕분에 도움이 되었습니다.

내용은 이러함.

1. 에셋번들 빌드

2. 빌드결과 파일들 복사.

3. 프로젝트 아무것도 안 건드리고 다시 빌드

4. 두번째 빌드결과 파일들과 첫번째 빌드 파일들 비교

이상하게 몇몇 파일들이 자꾸 결과물이 다르다.

실제로 파일용량도 다르다.

대략 내용을 보면 내용은 같은데 파일의 내용 부분에서 저장 데이터 위치가 

조금씩 바뀌면서 용량도 틀려지고 하는듯 하다.

근데 왜 저장 위치가 달라지는 거지?


현재 사용 버전 : 5.5.1p3

결론 : 빌드할 때마다 특정 scene들의 파일 용량이 다르며, 실제이 조금씩 달라진다.

         그럼으로 인해 파일의 CRC 또한 달라진다.


첫번째 해결 시도

혹시 editor 관련 코드들이 random 을 만들어 내거나 하지 않을까?

editor 코드들을 제거. 끝없이 제거..딱히 정확한 연관성을 찾지 못함.


두번째 해결 시도

scene이 제대로 저장되지 않은게 아닐까?

프리팹들을 여기저기에 쓰는데 scene에서도 정보를 자체적으로 저장하니까,

그리고 이미 유니티 버전업도 몇번 진행했으니까 마이그레이션에서 문제가 있을수도 있고..

그래서 모든 신을 오픈하고 다시 저장하는 스크립트를 만들어서 돌림.

그랬더니!!!

파일 해쉬는 여전히 바뀌지만 파일 용량은 바뀌지 않음!!!

이 부분에서 유추할 수 있는 내용은 뭘까?

어느 부분이 해결되서 파일 용량이 안바뀌게 된걸까?

버전에 따른 추가정보 저장이 있는걸까?

그런데 왜 특정 scene만 저장해서 하면 계속 용량이 바뀌는 걸까?

결국 뭔가의 연관성이라는 게 있는걸까?


세번째 해결 시도

복사 붙여넣기 프리팹이 문제일까?

실제로 하나의 프리팹을 만든 후 그걸 여러군데에서 떙겨쓰고 apply하고 수정하고 하는 

일들을 많이 한다.

이는 프리팹을 쓰는 정확한 가이드 라인과 잘못 사용하는 프리팹을 찾을 수 있는 기능을

처음부터 제시하지 못한 나의 잘못. 그래서 이 부분에 대해 조사.

우선 프리팹의 문제인지 검증하기 위해 의심가는 프리팹을 링크를 끊어서 테스트.

여러번 빌드해도 해시과 변경되지 않는다!!

결국은 프리팹이 문제인 건데 여기서 다시 프리팹에 붙어 있는 특정 script가 문제 인가 하여

script를 지우면서 테스트 해 봐도 그건 아닌 듯 하다.

프리팹 링크에 대한 문제인듯 하다.

scene에 올려져 있는 세개의 프리팹의 링크를 끊었다.

a.prefab : 해당 scene에서만 사용하는 프리팹으로 editor 관련 컴포넌트가 붙어있다.

b.prefab : 몇군데의 scene에서 사용하는 프리팹으로 프리팹 안에 다른프리팹들이 여러개 들어 있다.

c.prefab : 해당 scene에서만 사용하는 프리팹으로 컴포넌트에 다른 프리팹에 대한 링크를 들고 있다.

위 프리팹들을 하나씩 다시 재 구축하며 테스트를 진행하였다.


a.prefab를 위한 테스트.

다시 프리팹으로 만들어서 테스트 : 두번의 빌드 후 scene 비교 결과 결과값이 다르다.

새로 만든 프리팹이며 하나의 신에서만 사용하는데도 신 빌드 결과값이 다름.

이 프리팹에 붙어있는 두개의 컴포넌트는 아래와 같다.

- script1 : editor script

- script2 : mono script

테스트를 진행해 봤다.

script1을 제거하고 테스트, script2를 제거하고 테스트 등 몇가지 테스트를 해 봤지만

script가 하나라도 붙어 있으면 계속 빌드를 하면 결과값이 바뀐다.

왜 script가 하나라도 붙어있으면 결과값이 바뀌는 걸까? 

다른 프리팹은 안바뀌는데... 

결과값에 영향을 안주는 프리팹과 비교해 본 결과 차이점은 결과값에 차이를 안 주는 프리팹은 

유니티 자체 컴포넌트(ex : animation, mesh 등)을 사용하고 있었다.

그래서 다시 a.prefab에 유니티 자체 컴포넌트를 붙여서 테스트 해 보니 결과값이 바뀌지 않음.

결론은....커스텀 script를 컴포넌트로 가지는 프리팹이 scene의 하이라키에 있으면 scene을 빌드할 때 문제가 생긴다??

혹시 custom하게 추가 한 스크립트 실행순서 때문일까? 모두 지우고 테스트 해 보니 이건 원인이 아님.

(지웠던 순서를 되돌리기 위해선 해당 스크립트의 메타를 고쳐야 한다. 순서는 메타에 저장된다)


여기까지의 정리를 보자면

1. scene의 하이라키에 프리팹이 올려져 있고 그 프리팹이 unity 지원이 아닌 자체 script을 컴포넌트로 가지면 

   번들을 빌드할 때 마다 파일이 조금씩 달라진다.

2. 새로 프로젝트를 만들어서 똑같이 테스트 해 본 결과 달라지지 않는다. 즉 현재 작업중인 프로젝트에 무었인가가 

   빌드시 프리팹을 건드는게 있다고 추측할 수 있다.

3. 그리고 scene의 하이라키에 missing난 컴포넌트가 있으면 결과 번들파일이 달라진다.

   그러니 missing난 컴포넌트를 잘 살펴보자.


분석 시작 3주째....

어느순간 내가 분석한 데이터가 다 필요없다는걸 깨달았다.

분명 두번 빌드해서 결과값이 같은걸 보고 연관성을 찾으려 했는데

사실 두번 빌드 했을 경우 우연히 결과값이 맞을수도, 틀릴수도 있다는 걸 알았다.

그래서 연속으로 30번 빌드하는 기능으로 바꿔서 테스트 해 보니 내가 찾았던 문제로 의심되던 것들이 

다 의미가 없어졌다. 아무런 연관성이 없다. 이런 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX...

미친 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

깊은 빡침이란 이런걸까...아..미친듯이욕하고싶다...이런...

AssetBundleExtractor의 도움으로 내부 덤프파일을 일일이 검사해보니 특정파일의

SInt64 m_PathID 값이 다른걸 발견했다.

이 m_PathID를 검색해 보니 이런 을 발견했다.


작업을 위해 필요했던 것들.

1. 모든 번들을 다 빌드하면 시간이 많이 걸리기 때문에 하나의 번들과 그에 연관된 번들만

   빌드하기 위해 파일별 개별 빌드 기능을 만듬.

2. scene 파일이 많기 때문에 모든 scene을 열어서 새로 저장하는 기능이 필요해서 만듬.

3. 특정 프리팹을 지울 때 이 프리팹을 쓰는 scene들을 찾기 위한 기능을 만듬.

   모든 scene을 열어서 하이라키에 특정 프리팹을 쓰는 곳이 있는지 찾음.

4. 특정 번들만 다른이름 으로 두번 연속 빌드해서 결과값 비교 기능 만듬.

5. 모든 스크립트 재컴파일 기능 추가.

6. 모든 scene의 모든 컴포넌트를 검사하여 missing 찾는 기능 추가.



딮빡침......그래서 유니티 패치를 찾아봄.....

아...이런..딮딮딮...빡침...미친...빡침...

나의3주가...나의시간이....허무하게소비되었어.....패치를꼼꼼히읽어야지.늘생각했거늘...이런...

업그레이드 후 테스트 하니 잘 됨.

이 버그를 발견해서 수정하려고 시작한 날짜가 5.12일 이고 위 패치노트가 나온날이 5.24일 이니까

이 때 미친듯이 구글링 했을때 못찾았던건 당연한건가.......

찜찜하지만 해결하는데 한달이 넘게걸렸군.....이런 거지같은...내 인생 최대의 고난이었음...


업그레이드 하지 않고 이 문제를 피해가기 위해서는 나름 테스트한 결과를 토대로 방법을 강구하자면

scene의 하이라키상에 프리팹이 있고 이 프리팹이 유니티가 지원해주는 스크립트가 아닌것을 컴포넌트로 가지면

문제가 발생한다. 그러니 프리팹을 끊던지 컴포넌트를 없애던지 프리팹을 동적로드로 바꾸던지 해야 한다.

이건 테스트 할 당시에는 발생을 안했는데 확실성을 가지진 않는다.

그러니 업그레이드를 추천한다.


Reference Link

- [SCENE]M_ROOTORDER ORDER BEING SAVED AS A PREFABMODIFICATION 

  WITHIN THE SCENE FILE HAS AN INCORRECT VALUE

UNITY TEXT FORMAT AND M_ROOTORDER TEXT

- SOME ASSET BUNDLE COMPONENTS HAVE DIFFERENT M_PATHID COMPARED TO 

  NEW ASSET BUNDLE WITH DELETED LIBRARY

-

'Unity > Unity Study' 카테고리의 다른 글

RenderQueue  (0) 2017.06.21
There are inconsistent line endings  (2) 2017.06.20
assetbundle building, change file  (0) 2017.06.03
메모리 프로파일러  (0) 2017.05.19
Asset Bundles vs. Resources : A Memory Showdown  (0) 2017.04.14
Asset Bundle Compression  (0) 2017.03.22
Posted by 붕대마음

댓글을 달아 주세요

개인 필요에 의해 번역한 글입니다.

원문을 참고하시길 강추드립니다.


유니티 5.3a4는 상당히 저레벨의 새로운 메모리 프로파일러 API가 있다.

이 프로파일러는 어느 오브젝트가 얼마나 많은 c++ 메모리 할당을 받았는지에

대해 찾아낼 수 있다.

IL2CPP 플랫폼에서 c#타입의 설명 뿐 아니라 전체 c# 힙의 덤프까지 제공한다.


이 API는 대부분의 사람들이 사용하기에는 너무 저레벨이다.

이 말은 이 API를 사용하기 위해 멋진 UI 윈도우가 더해지면

정말로 많은 사람에게 활용하기 유용할 것이며,

어느 오브젝트가 로드되었는지, 어느 오브젝트가 많은 메모리를 차지하는지,

그리고 가장 중요한 왜 그 오브젝트가 메모리에 있는지를 찾는데 도움을 줄 것이다.

이 레퍼지토리는 더 멋진 UI 윈도우로 작업이 진행중에 있다.


일반적인 "메모리 릭"의 패턴은 우리가 알고 있듯이, 

만약 정적 필드가 있는 c#클래스에 큰 크기의 Texture2D의 레퍼런스를 가지는

오브젝트의 리스트를 가지고 있는 경우이다.

이 Texture2D는 c#에서 여전히 접근할 수 있으므로 절대 언로드 되지 않는다.

이런 경우를 파악하기는 무척 힘들다.

이 새로운 메모리 프로파일러 윈도우는 직관적으로 만들어 질 것이며,

만약 큰 Texture2D를 선택하면, Texture2D가 로드되는 원인이 되는

정적 c# 필드(클래스 이름을 포함한)에 대한 대한 레퍼런스의 역추적 정보가 표시될 것이다.

이는 il2cpp 플렛폼에서만 작동하며, 이 역추적을 하기 위해 전체 il2cpp힙이 필요하다)


우리는 유니티 제품 자체에서 저수준 레벨 API를 올려 접근하는 방식을 채택하였고,

"적절하게 유니티에 포함될 충분한 준비"로 이미 오래전에 

이 메모리 프로파일러 윈도우를 오픈소스 형태로 해 두었다.

우리는 이 윈도우를 오픈소스 프로젝트로 개발할 것이다.

기부는 환영합니다.

어떤 시점에서 우리는 이 기능이 충분하다고 느낄 것이고,

그 시점에 유니티와 함께 상자 밖으로 나올 것이다.


오늘날, 이 기능의 UI 부분은 여전히 무척 힘들다.

우리는 어쨌든지 프로젝트를 오픈소스로 하기로 결정했으며,

너의 프로젝트에서 "메모리를 절약해야 하는데, 지금 우리가 무었을 할 수 있을까?" 라고 생각한다면,

너는 아마 메모리 릭을 찾는 것에 대해 더 많은 관심을 가질 것이며, 그리고

지금부터 6개월 뒤에는 이 기능의 훌륭한 버튼과 사용 경험으로 메모리 릭들을 찾을 것이다.


사용 :

- 유니티 5.3a4나 그 이상 버전 사용

- il2cpp 프로젝트로 빌드 & 실행 (어느 il2cpp 플렛폼이라도 괜찮다.)

- 이 레퍼지토리에서 프로젝트를 연다.

- 일반적인 프로파일러 윈도우를 연다.

- 일반적인 프로파일 하듯이 플레이어 연결

- 메모리 프로파일러 윈도우 열기(Window-MemoryProfilerWindow)

- "SnapShot" 클릭

- 또는 이 비디오 참조 : https://www.youtube.com/watch?v=7B6xRYMzst8


개인 생각

이 툴의 존재를 안지는 좀 되었는데 그다지 잘 활용하지 않았던 이유가 현재 프로파일러를 사용함에 있어

그다지 모자른 감이 없었고 이 툴 역시 기존 프로파일러와 같이 에디터상에서 종료시 깔끔하게

내부 캐시정보? 같은걸 정확하게 내려주지 않아서 아직 로드하지 않은 것들도 메모리에 로드되어 있어 보이기 때문이다.

물론 이 현상은 기존 프로파일러에도있어서 최적화 작업을 할 때는 보통 최대한 에셋을 클릭하지 않거나

클릭을 했다면 에디터 종료가 아니라 유니티 프로그램을 껏다 켜야 제대로 정보가 나왔다.

비주얼 적으로 훌륭하기 때문에 추천할만한 기능이다.


Reference Link

- unity technologies, MemoryProfiler

- c# 컴파일 그리고 il2cpp

- unity community, memory profiler

-

Posted by 붕대마음

댓글을 달아 주세요

최근에 달린 댓글

최근에 받은 트랙백

글 보관함