Eu4ng / TIL

Today I Learned
1 stars 0 forks source link

[Unity] 2D Background Scrolling (배경 무한 스크롤) #217

Open Eu4ng opened 1 year ago

Eu4ng commented 1 year ago

만드는 법

  1. Quad 생성
  2. Material 생성
    • Unlit/Texture
  3. Texture 생성
    • Wrap Mode : Repeat
  4. Material에 Textrue 입히기
  5. mainTextureOffset.y 값을 변경함으로써 Background Scrolling 구현

여러 텍스처를 사용하는 셰이더

Shader "Unlit/MultipleTextures"
{
    Properties
    {
        _MainTex ("First Texture", 2D) = "white" {}
        [NoScaleOffset] _SubTex ("Second Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            sampler2D _SubTex;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col;
                float flag = 0;
                if(fmod(i.uv.y, 2) < 1)
                {
                    flag = 1;
                }

                col = tex2D(_MainTex, i.uv) * flag + tex2D(_SubTex, i.uv) * (1 - flag);

                return col;
            }
            ENDCG
        }
    }
}
Eu4ng commented 1 year ago

참고 링크

Eu4ng commented 1 year ago

TextureArray.shader

Shader "2D/ScrollingBackground/TextureArray"
{
    Properties
    {
        _MainTex ("Texture Array", 2DArray) = "" {}
        _TexCount ("Texture Counts", INT) = 2
        [Toggle] _SideScrolling ("Side Scrolling", Range(0, 1)) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 uv : TEXCOORD0;
            };

            UNITY_DECLARE_TEX2DARRAY(_MainTex);
            float4 _MainTex_ST;
            int _TexCount;
            float _SideScrolling;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.uv.xy += _MainTex_ST.zw;

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 uv = i.uv;
                if(_SideScrolling >= 1)
                {
                    uv.z = floor(fmod(uv.x, _TexCount));
                }
                else
                {
                    uv.z = floor(fmod(uv.y, _TexCount));
                }

                return UNITY_SAMPLE_TEX2DARRAY(_MainTex, uv);
            }
            ENDCG
        }
    }
}
Eu4ng commented 1 year ago

텍스처 배열 애셋 생성 스크립트

using UnityEditor;
using UnityEngine;

public class TextureArrayWizard : ScriptableWizard
{
    [MenuItem("Assets/Create/Texture Array")]
    static void CreateWizard()
    {
        ScriptableWizard.DisplayWizard<TextureArrayWizard>(
            "Create Texture Array", "Create"
            );
    }

    public Texture2D[] textures;

    void OnWizardCreate()
    {
        // 유효성 검사
        if (textures.Length == 0) return;

        string path = EditorUtility.SaveFilePanelInProject(
            "Save Texture Array", "Texture Array", "asset", "Save Texture Array"
            );

        // 유효성 검사
        if (path.Length == 0) return;

        Texture2D t = textures[0];
        Texture2DArray textureArray = new Texture2DArray(
            t.width, t.height, textures.Length, t.format, t.mipmapCount > 1
            );

        textureArray.anisoLevel = t.anisoLevel;
        textureArray.filterMode = t.filterMode;
        textureArray.wrapMode = t.wrapMode;

        for (int i = 0; i < textures.Length; i++)
        {
            for (int m = 0; m < t.mipmapCount; m++)
            {
                Graphics.CopyTexture(textures[i], 0, m, textureArray, i, m);
            }
        }

        AssetDatabase.CreateAsset(textureArray, path);
    }
}
Eu4ng commented 1 year ago

만드는 순서

  1. Assets > Create > Texture Array (TextureArrayWizard)

    • 텍스처 선택 후 텍스처 배열 애셋 생성
    • Wrap Mode : Repeat
  2. 머터리얼 생성

    • 2D/ScrollingBackground 셰이더 선택
    • 1.에서 생성한 텍스처 배열 애셋 할당
    • 텍스처 배열에 포함된 텍스처 개수 입력 (Texture Counts)
    • 스크롤 할 방향(종/횡) 옵션 설정 (Side Scrolling)
  3. 스크립트로 머터리얼의 텍스처 Offset 제어

    • Update에서 이동 거리를 누적하여 측정
    • 이동거리 = 텍스처 Offset (X : 횡, Y : 종)
Eu4ng commented 1 year ago

shader_feature 특징 shader_feature에서 미사용 배리언트는 최종빌드에서는 포함되지 않는다.

즉, 빌드 이후 실행할때는 상태를 변경하지 못한다는 것이다.

“multi_compile” 셰이더 배리언트를 사용하면, 이문제를 해결 할 수 있다.