스프라이트 애니메이션을 개발하며

유니티 애니메이션 클립 미리보기같은 느낌으로
에디터에서 애니메이션을 미리보는 기능을 만들었다

 

개발하다보니 문제가 생겼는데

에디터의 OnInspectorGUI나 OnPreviewGUI 같은 함수는
"마우스가 인스펙터 위로 지나갈 때"만 다시 그려진다는 것

https://docs.unity3d.com/ScriptReference/Editor.RequiresConstantRepaint.html

요 함수를 오버라이드해 주기적으로 Repaint를 요청할 수 있다

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using UnityEngine;
using UnityEditor;
 
[CustomEditor(typeof(AnimationData), true)]
public class AnimationDataEditor : Editor
{
    private double lastTime;
 
 
    public override bool RequiresConstantRepaint() => true;
 
    public override void OnInspectorGUI()
    {
        // EditorApplication.timeSinceStartup 을 사용해 에디터에서 시간 측정을 할 수 있다
        var currentTime = (float) (EditorApplication.timeSinceStartup - lastTime); 
 
        ...
    }
}
cs

 

블로그 이미지

stuban

ㅇ.ㅇ

,

 

유니티 패키지 매니저를 통해 Newtonsoft Json을 설치할 수 있지만
패키지 목록에서는 찾을 수 없고 
무조건 Add package by name 을 통해 추가해야 한다

(프로젝트 세팅의 enable pre-release packages 옵션과 관련 없음)

com.unity.nuget.newtonsoft-json

 

 

 

유니티 내장 json 툴을 사용하는 것을 권장하고
굳이 newtonsoft json쓸거면 패키지를 통해 설치하라고 한다

근데 왜 패키지 매니저 목록에 안나오게 하고
프로젝트 버전 바꿀때 마다 추가했던 패키지가 사라지는데???

https://docs.unity3d.com/Packages/com.unity.nuget.newtonsoft-json@3.2/manual/index.html

블로그 이미지

stuban

ㅇ.ㅇ

,

[프로그래밍/유니티] - 유니티 좌표에 따른 정렬 기준 바꾸기

기존에는 Edit->Project Setting->Graphics->Transparency Sort ModeCoustom Axis로 설정해
좌표에 따른 소팅 오더를 쉽게 세팅할 수 있었다

 

그런데 최근 URP로 전환하며 기존에 CoustomAxis를 설정하는 필드가 사라져버렸다

정확히는 숨어버린 것인데

프로젝트 경로\ProjectSettings\GraphicsSetting.asset

위 경로의 파일을 메모장으로 열고

TransparencySortModeTransparencySortAxis를 직접 바꿔주면 된다.

 

CustomAxis로 사용하기 위해서는

m_TransparencySortMode를 3으로 설정하고
TransparencySortAxis를 원하는 값으로 바꾼 뒤
프로젝트를 재시작하면 적용된다.

 

+ URP 2D에서는 Renderer 2D 설정에서 TransparencySortMode를 설정할 수 있다.
GraphicsSetting에 작성한 TransparencySortModeRenderer2D 설정으로 덮어 씌워진다

블로그 이미지

stuban

ㅇ.ㅇ

,

 

https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@16.0/manual/features/rendering-debugger.html

 

Rendering Debugger | Universal RP | 16.0.0

Rendering Debugger The Rendering Debugger window lets you visualize various lighting, rendering, and Material properties. The visualizations help you identify rendering issues and optimize Scenes and rendering configurations. This section contains the foll

docs.unity3d.com

 

urp를 사용할 때

컨트롤 + 백스페이스 혹은
게임패드의 양쪽 스틱을 동시에 누르면

렌더링 디버그 창을 띄운다

 

나 같은 경우는 게임패드의 양쪽 스틱을 동시에 눌러 발동하는 스킬을 개발하고 있었는데
디버그 창을 띄우는 단축키와 동일해 문제를 겪고 있었다
(심지어 공식 문서에서도 끄는 법이 안나와 있음)

렌더링 디버그 창을 띄우는 단축키를 변경하고 싶다면

DebugManager.Actions.csRegisterInputs() 함수 내용을 수정해주면 된다.
(12.1.9 버전 기준 295번줄)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void RegisterInputs()
    {
#if UNITY_EDITOR && !USE_INPUT_SYSTEM
    var inputEntries = new List<InputManagerEntry>
    {
        new InputManagerEntry { name = kEnableDebugBtn1,  kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left ctrl",   altBtnPositive = "joystick button 8" },
        new InputManagerEntry { name = kEnableDebugBtn2,  kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "backspace",   altBtnPositive = "joystick button 9" },
        new InputManagerEntry { name = kResetBtn,         kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left alt",    altBtnPositive = "joystick button 1" },
        new InputManagerEntry { name = kDebugNextBtn,     kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page down",   altBtnPositive = "joystick button 5" },
        new InputManagerEntry { name = kDebugPreviousBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page up",     altBtnPositive = "joystick button 4" },
        new InputManagerEntry { name = kValidateBtn,      kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "return",      altBtnPositive = "joystick button 0" },
        new InputManagerEntry { name = kPersistentBtn,    kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right shift", altBtnPositive = "joystick button 2" },
        new InputManagerEntry { name = kMultiplierBtn,    kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left shift",  altBtnPositive = "joystick button 3" },
        new InputManagerEntry { name = kDPadHorizontal,   kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right",       btnNegative = "left", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f },
        new InputManagerEntry { name = kDPadVertical,     kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "up",          btnNegative = "down", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f },
        new InputManagerEntry { name = kDPadVertical,     kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Seventh, btnPositive = "up",    btnNegative = "down", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f },
        new InputManagerEntry { name = kDPadHorizontal,   kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Sixth,   btnPositive = "right", btnNegative = "left", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f },
    };
 
    InputRegistering.RegisterInputs(inputEntries);
#endif
 
#if USE_INPUT_SYSTEM
    // Register input system actions
    var enableAction = debugActionMap.AddAction(kEnableDebug, type: InputActionType.Button);
    enableAction.AddCompositeBinding("ButtonWithOneModifier")
        .With("Modifier""<Gamepad>/rightStickPress")
        .With("Button""<Gamepad>/leftStickPress")
        .With("Modifier""<Keyboard>/leftCtrl")
        .With("Button""<Keyboard>/backspace");
 
    ...    
 
#endif
    }
}
cs

 

난 인풋 시스템을 사용하고 있고
디버그 창을 띄우는 키를 게임패드의 스타트와 메뉴 버튼으로 바꿨다

1
2
3
4
5
6
var enableAction = debugActionMap.AddAction(kEnableDebug, type: InputActionType.Button);
enableAction.AddCompositeBinding("ButtonWithOneModifier")
    .With("Modifier""<Gamepad>/start")
    .With("Button""<Gamepad>/menu")
    .With("Modifier""<Keyboard>/leftCtrl")
    .With("Button""<Keyboard>/backspace");
cs

 

블로그 이미지

stuban

ㅇ.ㅇ

,
1
2
3
4
5
6
7
8
9
10
11
12
13
SystemLanguage lang = Application.systemLanguage;
 
switch(lang)
{
    case SystemLanguage.Korean:    
        break;    
 
    case SystemLanguage.English:
        break;
 
    case SystemLanguage.Japanese:
        break;
}
cs

SystemLanguage 열거형과 Application클래스는 UnityEngine 네임스페이스안에 들어있음

 

블로그 이미지

stuban

ㅇ.ㅇ

,


유니티에서 스프라이트를 쓸때

색깔을 바꾸면 뭔가 칙칙하게 바뀌는 듯한 느낌이 든다


기본 스프라이트에서 왼쪽이 흰색 , 오른쪽이 파란색을 넣었을 때


이유는 기본 스프라이트 쉐이더가 색깔을 적용할때

곱해서 처리하기 때문이다


쉐이더에서 색을 저장할때 fixed4라는 자료형을 쓰는데

R,G,B,A값을 저장하는 역활을 한다


그러니깐  

(0,0,0,0) 이 투명한 검은색

(1,1,1,1)이 불투명한 흰색

이 되는 것이다.


만약 (0.5,0.5,0.5,1)(회색)과 (0.5,0.5,0.5,1)을 합칠때


더한다면 (1,1,1,2)이 되어서 하얀색이 되고 (2는 1로 취급)

곱한다면 (0.25,0.25,0.25,1)이 되어서 어두운 회색이 된다


따라서 곱하기를 쓰는 유니티 기본 스프라이트에

색을 넣으면 더 칙칙해지는 것이다


그런데 그냥 + 를 쓰면

색이 1을 넘어갔을때 짤리게 된다


그래서 스크린이라는 방식이 있는데

result = 1-(1-A)*(1-B);

원래 색상들을 1에서 빼서 곱하고

그 값을 또 1에서 빼는 것



그래서 만드는 방법은


1.

https://unity3d.com/kr/get-unity/download/archive?_ga=1.66259950.1501402159.1471086308


유니티 다운로드 아카이브에서 내장 셰이더를 다운로드한다.

기왕이면 버전에 맞게 다운로드 하면 된다.


그러면 셰이더들이 잔뜩 들어있는 압축파일을 받게 되는데


ctrl + f 로 Sprites-Diffuse.shader 를 찾는다


Diffuse 를 쓰는 이유는 Default 쉐이더는 너무 간소화되서 어떻게 수정하는지 모르기 때문에......



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
 
Shader "Sprites/Diffuse"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
        [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
        [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
        [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    }
 
    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
 
        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha
 
        CGPROGRAM
        #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing
        #pragma multi_compile_local _ PIXELSNAP_ON
        #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
        #include "UnitySprites.cginc"
 
        struct Input
        {
            float2 uv_MainTex;
            fixed4 color;
        };
 
        void vert (inout appdata_full v, out Input o)
        {
            v.vertex = UnityFlipSprite(v.vertex, _Flip);
 
            #if defined(PIXELSNAP_ON)
            v.vertex = UnityPixelSnap (v.vertex);
            #endif
 
            UNITY_INITIALIZE_OUTPUT(Input, o);
            o.color = v.color * _Color * _RendererColor;
        }
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color;
            o.Albedo = c.rgb * c.a;
            o.Alpha = c.a;
        }
        ENDCG
    }
 
Fallback "Transparent/VertexLit"
}
 
cs

아무튼Sprites-Diffuse.shader는 요로케 생겼는데 여기서 수정할 부분은 


2. 

이름 바꾸기


이미 유니티에는 Diffuse 쉐이더가 들어있기 때문에

쉐이더의 이름을 바꿔줘야한다


저 "/" 는 폴더같은 느낌으로 머터리얼에서 쉐이더를 고르기 편하게 해준다.


2. 

surf함수 수정

1
2
3
4
5
6
7
8
void surf (Input IN, inout SurfaceOutput o)
{
    fixed4 c = 1 - ((1 - SampleSpriteTexture(IN.uv_MainTex)) * (1 - IN.color));
    c.a = SampleSpriteTexture(IN.uv_MainTex).a * IN.color.a;
 
    o.Emission = c.rgb * c.a;
    o.Alpha = c.a;
}
cs

surf함수를 이렇게 바꾸면 된다.


여기서 스크린이아니라 + 를 쓰고 싶으면 3번 줄을 

fixed4 c = SampleSpriteTexture(IN.uv_MainTex) + IN.color;

로 바꾸면 된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
 
Shader "Sprites/Screen"
{
    Properties
    {
        [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
        [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
        [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
        [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    }
 
    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
 
        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha
 
        CGPROGRAM
        #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing
        #pragma multi_compile_local _ PIXELSNAP_ON
        #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
        #include "UnitySprites.cginc"
 
        struct Input
        {
            float2 uv_MainTex;
            fixed4 color;
        };
 
        void vert (inout appdata_full v, out Input o)
        {
            v.vertex = UnityFlipSprite(v.vertex, _Flip);
 
            #if defined(PIXELSNAP_ON)
            v.vertex = UnityPixelSnap (v.vertex);
            #endif
 
            UNITY_INITIALIZE_OUTPUT(Input, o);
            o.color = v.color * _Color * _RendererColor;
        }
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = 1 - ((1 - SampleSpriteTexture(IN.uv_MainTex)) * (1 - IN.color));
            c.a = SampleSpriteTexture(IN.uv_MainTex).a * IN.color.a;
 
            o.Emission = c.rgb * c.a;
            o.Alpha = c.a;
        }
        ENDCG
    }
 
Fallback "Transparent/VertexLit"
}
 
cs

완성본!




기본 흰색 , 기본 파란색 , 스크린 파란색

블로그 이미지

stuban

ㅇ.ㅇ

,
1
dir + hit.normal * (-2 * Vector2.Dot(dir, hit.normal));
cs


dir은 물체가 향하는 방향

노말은 레이캐스트나 OnCollisionEnter 같은걸 사용해서 구할 수 있음

블로그 이미지

stuban

ㅇ.ㅇ

,

나는 주로 유니티에서 간단하게 움직이는  스크립트를 짤 때

Lerp 함수를 자주 이용한다.

 

근데 문제는 이동에 뭔가 색다른 효과를 주고 싶을 때

처음에는 느리다가 점점빨라지거나

갑자기 뒤로갔다가 반동으로 튀어나가거나

 

그런 동작을 추가하려면 뭔가 복잡한 처리를 해야한다는 것 이었다

 

근데 AnimationCurve 클래스를 최근에 알게 되었다

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public AnimationCurve curve;//인스펙터에서 조정하면 됨
 
 
IEnumerator Close()
{
    float progress = 0;
    while (true)
    {
        progress += Time.DeltaTime;
          
        cutOff = Mathf.Lerp(01, curve.Evaluate(progress));//여기 가 중요한 부분
        if (progress > 1) yield break;
 
        yield return 0;
    }
}
cs

 

인스펙터에는 이런식으로 뜬다

 

클릭하면 나오는 창에서 잘 조정하면 된다

밑에있는 톱니바퀴를 누르면

지금 편집하고 있던 커브를 프리셋으로 등록할 수도 있다.

블로그 이미지

stuban

ㅇ.ㅇ

,