250105

lililllilillll·2025년 1월 4일

개발 일지

목록 보기
42/350

✅ 오늘 한 일


  • 대마왕의 유니티 URP 셰이더 그래프 읽기
  • Udemy Unity 강의 수강


📖 대마왕의 유니티 URP 셰이더 그래프


Part 04 | 셰이더 그래프 만들기와 Property

01 오브젝트에 Material과 셰이더를 적용해 봅시다

씬 만들 때
Basic(URP): 카메라와 디렉셔널 라이트 1개가 있는 상태로 시작
Standard(URP): 카메라와 디렉셔널 라이트에 포스트 프로세스가 적용되어 있고, 포스트 프로세스에는 톤 매핑(Tone mapping)과 블룸(Bloom)이 적용된 HDR 씬 구조로 시작

오브젝트 확대 : 단축키 F 혹은 더블 클릭

셰이더 만들기 : Project 창 > Create > Shader Graph > URP > Unlit Shader Graph

셰이더 적용 방법

  • 머테리얼에 셰이더 그래프 끌어다 적용시킨 후에 오브젝트에 머테리얼 끌어다 적용시키기
  • 머테리얼 Inspector 상단에서 셰이더 변경 > 오브젝트 Mesh Renderer 컴포넌트 Materials > Element에 머테리얼 적용

02 셰이더 그래프를 열어서 경로를 바꿔 봅시다

셰이더의 '폴더'를 바꾸려면 셰이더 그래프에서 '폴더명과 경로'를 적어주어야 한다.

셰이더 선택할 때 기본 경로는 'Shader Graphs'로 돼있는데, 여러 개 만들다보면 한 폴더에 전부 몰려서 정리가 안됨.
Shader Graph 창 좌측 상단에서 셰이더 그래프 이름 아래에 있는 작은 글씨를 더블 클릭해서 경로를 바꿔주면 됨.
아예 지워버리면 루트에 노출됨. '/'를 사용해서 여러 디렉토리로 나눌 수도 있음.

셰이더 그래프 수정 후 Save Asset 또는 Ctrl+S로 저장하는거 잊지 말기

03 Blackboard와 Graph Inspector를 이용하여 셰이더 Properties를 만들어 봅시다

Properties : 셰이더의 UI를 담당. 오브젝트 선택했을 때 머테리얼에 나오는 셰이더 옵션 제어하는 부분.
(Blackboard나 Graph Inspector가 안 보이면 우측 상단 버튼 눌러서 표시)
좌측 상단의 +를 눌러서 프로퍼티 만들 수 있다.

  • Inspector에서 슬라이더로 조절 : Float 생성 > Graph Inspector > Node Settings > Mode > Slider
  • 프로그래밍의 bool과 다르게, 여기서의 Boolean은 float 형식에서 0이나 1의 값만 넘어오는 것.
  • Property가 많아지면 Category를 추가하여 정리해주자.

Property 공통 파라미터

Name : 이름. 한글도 가능. (버전 따라 실수로 한글 지원 안될수도)
Refernece : 입력 받은 값에 접근할 때의 변수명.

  • 앞에 _ 를 붙여서 외부에서 들어온 값이라는 걸 알기 쉽게 하면 좋다.
  • Name과 Reference는 통일하는게 좋다.
    Default : 셰이더가 처음 생성될 때 갖게 될 초기값. Inspector에서 값 변경하면 이 값은 의미 없어짐.
    Precision : 플랫폼에 따라 셰이더에서 사용되는 숫자의 정밀도를 조절하는 것. 이거 줄이는 것보다 텍스처나 한 장 줄이는게 더 효과적.
    Exposed : Property가 Inspector에 노출되게 할건지 말건지
    Override Property Declaration : Property의 속성을 재선언. C 버퍼에서 어떻게 Reference 변수를 처리할지에 대한 부분. 큰 프로젝트에서 유용.

Color Property

Color Property를 만들고 Graph Inspector > Mode를 확인하면 HDR 옵션이 있다.

  • Default : LDR, Low Dynamic Range, 0~1까지의 범위로 이루어진 색상
  • HDR : High Dynamic Range, 1 이상의 색도 선택할 수 있는 범위

Color는 float4 (Vector4)와 기본적으로 같지만,
Color는 float4와 다르게 Linear가 아니라 sRGB로 취급된다는 차이가 있다
하지만 유니티 2D를 사용하면 완전히 똑같다. 이유는 나중에.

Texture 2D Property

평범한 2D 텍스쳐를 받을 수 있다. 매우 많이 사용한다.
Mode : 이 프로퍼티에 텍스쳐 없을 때 기본 색깔. 일반적으로 White나 Black. 노말맵 텍스쳐 받는 Property는 NormalMap 사용.
텍스쳐 Tiling, Offset 조절 기능 : Node Settings > Use Tling and Offset

Cubemap Property

Cubemap : 스카이박스나 반사용 텍스쳐처럼, 주변을 360도로 감싸는 좌표를 가진 텍스쳐.

Part 05 | Shader Graph 기본 조작하기 1 : 색상 출력

01 Shader Graph 기본 사용법

Graph Inspector

  • Node Setting : 현재 선택한 노드의 세팅을 보고 제어
  • Graph Setting : 이 셰이더 전체의 세팅을 보고 제어. Lit, Unlit, 반투명, 알파 테스팅, 2side, Depth, Shadow 등 셰이더 전체 옵션 제어.

Node 생성 : 스페이스바, 또는 우클릭 > Create Node

'Color를 만들어 Fragment의 Base Color로 출력한다'는 명령.

노드 만들고 색상 바꿀 때 Property와 연결해놓으면 머테리얼 Inspector에서 색상 선택 가능. 방법은 2가지.

  • Property를 만들어 노드로 끌어와 연결하는 방법 : 드래그해서 노드로 만들어준 후 필요한 곳에 연결
  • 만들어진 노드를 Property로 승격하는 방법 : 노드 우클릭 > Convert To > Property

02 색상 출력하기

한 자리 숫자(Float)를 어딘가에 연결하면 그 곳의 비어있는 모든 자리에 들어간다.
근데 두 자리 필요하면 두 자리를, 세 자리 필요하면 세 자리 넣는게 자연스럽고 안전하다.

Part 06 | Shader Graph 기본 조작하기 2 : 분해와 재조립, 노드와 색상의 연산과 감마 코렉션

01 노드의 값을 분해하고 재조립하기 (Split과 Combine)

Split

XYZ에 들어간 값은, RGBA에 차례대로 배정. A에는 아무런 값도 안 들어갈 것.
R에는 1, G,B에는 0 들어갈 거고 A는 자동으로 0될 것.

Combine

값을 다시 합쳐줄 수 있다

셰이더 그래프 정리하는 법

  • 노드 프리뷰 창 접기 : 프리뷰에 마우스 올리고 화살표 클릭
  • 한 번 더 접기 : 노드 제목 오른쪽 화살표 누르면 선택하지 않은 옵션 숨겨짐. 동시에 드래그한 후에 하나 접으면 다 접힘.
  • 중간 연결 노드 넣기 : 선 선택하고 더블 클릭
  • 그룹 만들기 : 노드 여러개 선택하고 Ctrl+G 누르거나 우클릭 > Group Selection.
    그룹에 다른 노드 추가할 땐 노드를 그룹 안으로 드래그&드롭.
    그룹 안에 있는 노드 빼내려면 Ctrl+U 누르거나 우클릭 > Ungroups Selection
  • Sticky Note : 우클릭 > Create Sticky Note. 도움말 적어놓기. 우클릭해서 옵션 설정 가능.

02 노드(숫자)의 연산

더하기 : Add 노드
곱하기 : Multiply 노드
빼기 : Substract 노드
나누기 : Divide 노드

반전 : One Minus 노드
블랜드 : Blend 노드

숫자가 1을 넘어가면? : 1 이상일 때 Bloom 효과 발생하도록 Post Process 상태가 되어있다면 (처음 프로젝트 만들 때 Standard로 만들었다면) 빛나는 것처럼 보인다.

03 Color의 연산과 감마 코렉션

RGB(0.5,0.5,0.5)인 Vector3 노드 2개를 Add 노드로 합치면 흰색이 되지만,
RGB(0.5,0.5,0.5)인 Color 노드 2개를 합치면 약간 밝은 회색이 된다.
(0이나 1이면 상관 없음)

굳이 안 더해도 Color 회색이 숫자 0.5로 만든 회색보다 어둡다.
Color에는 sRGB 처리가 돼있어서 숫자 회색의 Linear와는 다르기 때문.
이를 사람의 색 감각에 맞추기 위한 색상보정인 '감마 코렉션'이라 한다.

감마 코렉션?
인간 눈은 어두운 부분의 변화에 민감하기 때문에, 모니터는 인간의 감각에 맞추기 위해 중간 부분을 어둡게 끌어내림. 이것을 감마(Gamma)라 부름.

하지만 그렇게 되면 원래 이미지보다 어두워지기 때문에, color는 sRGB 공간이라는 밝은 영역으로 저장됨. 셰이더로 불러올 때 감마가 연산되어 다시 원래 색으로 돌아옴.

Color를 제대로 연산하려면 Color 노드를 Linear 공간으로 만들어야 함.
Colorspace Conversion 노드를 만들고, Linear > RGB로 컬로 공간 변환을 하면 컬러가 정상적으로 돌아온다.

여기까지 잘 이해 안되면, '컬러는 무조건 Colorspace Conversion으로 Linear > RGB로 해주는게 옳은 계산'이라고 외워도 된다.
(유니티 3D URP의 기본 컬러 공간이 Linear라서 생기는 문제다. 2D URP로 프로젝트를 만들면 컬러 공간이 Gamma가 되면서 이런 문제가 발생하지 않는다.)



🎮 Udemy Unity 강의 수강


10. 내브메시 에이전트를 활용한 움직임

카메라를 Scene 뷰에서 보이는 시점으로 옮기기 : GameObject > Align With View

AI Navagarion 설치 > Terrain에 Navmesh Surface > Bake > Player에 Navmesh Agent 컴포넌트 추가

(Troubleshooting) Navmesh 구웠는데 안 보임. 모든 걸 확인했는데 bake가 안됨. 우측 하단 AI Navigation > Surfaces > Show Navmesh 토글 켰더니 보이기 시작.

public class Mover : MonoBehaviour
{
    [SerializeField] Transform target;
    [SerializeField] NavMeshAgent navMeshAgent;

    void Update()
    {
        navMeshAgent.destination = target.position;
    }
}

이러면 Navmesh agent를 붙인 오브젝트가 Navmesh surface를 따라 간다.

11. 내브메시 조정

Window > AI > Navigation

  • Radius : Agent가 이동 가능한 경로의 너비
  • Height : Agent가 통과할 수 있는 경로의 최소 높이 (캐릭터의 키)
  • Step Height : Agnet가 걸어서 넘을 수 있는 최대 장애물의 높이
  • Max Slope : Agent가 올라갈 수 있는 최대 경사 각도

Generated Links

  • Drop Height : Agent가 떨어질 수 있는 최대 높이
  • Jump Distance : Agent가 점프할 수 있는 최대 거리

강의에선 오브젝트 우측 Static이 설정돼있지 않으면 Navmesh Bake할 때 인식하지 못한다고 했지만, 버전이 올라가서 그런가 알아서 잘 인식해줬음.

동적으로 움직이는 물체를 피해가도록 설정 : (강의에서 말하기론 Static을 풀고) Navmesh Obstacle 컴포넌트 추가. Carve를 설정하면 접근 금지 범위가 넓어진다.

  • Use Geometry : Navmesh 생성할 때 mesh, collider, both 기준을 뭘로 할지.
  • Collect Objects : Navmesh에 포함될 오브젝트 선택

Advanced

  • Override Voxel Size : Navmesh를 생성할 때 얼마나 세밀하게 생성할지
  • Override Tile Size : 한 번에 처리하는 영역 조정.
  • Minimum Region Area : Navmesh에 포함될 영역의 최소 크기

12. 레이캐스팅 소개

        if (Input.GetMouseButtonDown(0))
        {
            lastRay = Camera.main.ScreenPointToRay(Input.mousePosition);
        }
        Debug.DrawRay(lastRay.origin, lastRay.direction * 100);

13. 클릭으로 이동 구현

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            MoveToCursor();
        }
    }

    private void MoveToCursor()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        bool hasHit = Physics.Raycast(ray, out hit);
        if (hasHit) navMeshAgent.destination = hit.point;
    }

파라미터 확인 : 파라미터 괄호에 커서 두고 Ctrl+Shift+Space
VS Code 키보드 단축키 모음 보기 : Help > Keyboard Shorcuts References

14. 고정 팔로우 카메라 생성

    void Update()
    {
        transform.position = target.position;
    }

시네머신 없이 follow camera 구현하기 위해 follow camera라는 빈 게임 오브젝트 생성하고 main camera를 자식으로 두기

15. 애니메이션 블랜드 트리

원래 있던 Player 게임 오브젝트에서 Mesh Filter, Collider 지우고 애셋 프리팹 추가해준 후에
Navmesh Agent에서 Base Offset을 0으로 바꿔주고 Radius를 조정함.

Animator 컴포넌트 : Animator Controller를 통해 게임 오브젝트에 애니메이션 할당
Animator Controller : 애니메이션과 애니메이션 전환 모음 (state machine)
Blend Tree : 여러 개의 애니메이션 자연스럽게 섞기

Character를 위한 Animator Controller 생성 > Animator 창 우클릭 > Create State > From New Blend Tree > 생성된 노드 더블 클릭 > Inspector에서 Motion의 + 버튼, Add Motion Field > (애셋에 있던 motion들 사용) > 우측 하단 Blend Tree에서 재생하고 슬라이더를 조절하여 테스트

16. 움직임에 애니메이션 적용

만들었던 Controller 적용하고, 애셋에 있던 Avatar 적용하고, Apply Root Motion 체크 해제 확인

해야 하는 것

  • Navmesh Agent에서 속력을 구해온다
  • 캐릭터에 대한 local value로 변환한다
  • Animator의 blend value를 forward speed와 같게 설정한다

Animation Clip > Inspector > 하단 Average Velocity를 보면 애니메이션의 이동 속력이 있다.
Blend Tree의 Inspector > Automate Threshholds > Compute Thresholds > Velocity Z : Average Velocity에 맞게 조정된다.
Navmesh Agent 컴포넌트 > Speed를 최고 Threshhold로 변경한다.

InverseTransformDirection : 글로벌을 로컬로 변환
월드 좌표계 기준인 Navmesh Agent의 속도를 현재 게임 오브젝트 기준의 로컬 방향으로 변환한다.

    private void UpdateAnimator()
    {
        Vector3 velocity = navMeshAgent.velocity;
        Vector3 localVelocity = transform.InverseTransformDirection(velocity);
        float speed = localVelocity.z;
        GetComponent<Animator>().SetFloat("forwardSpeed", speed);
    }

Navmesh Agent의 Angular Speed와 Acceleration을 조절하여 움직임 자연스럽게 조정

17. 기본적인 움직임 변형

    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            MoveToCursor();
        }
        UpdateAnimator();
    }

GetKey : 해당 키 누르는 동안 true 반복적 반환
GetKeyDown : 해당 키 누르면 단 한 번 true 반환
GetKeyUp : 해당 키 누름 해제되면 true 한 번 반환

    void LateUpdate()
    {
        transform.position = target.position;
    }

플레이어가 이동한 후에 카메라를 움직여야 하니까 카메라 이동 로직은 LateUpdate()

18. 프로젝트 폴더 구조

t:material 이런 식으로 검색하면 머테리얼만 검색 가능. 물론 검색창 오른쪽에서 태그 설정도 가능.

profile
너 정말 **핵심**을 찔렀어

0개의 댓글