유니티에서 충돌을 처리하기 위해선 rigidbody와 collider를 Object에 붙여야 한다.

 

하지만 프로젝트마다 충돌의 목적 및 기대결과가 다르고 두 컴포넌트간의 옵션값 설정에 따라 충돌감지 및 물리현상 발현 유무가 다르기 때문에 충돌에 대해 정확히 정리해야 할 필요가 있다.

 

  • 충돌감지
    • 양쪽 오브젝트에 Collider추가
      • Collider와 Collider2D는 서로 감지가 안되므로 Collider는 Collider끼리 Collider2D는 Collider2D 끼리 추가
    • 충돌을 감지할 오브젝트에 rigidbody 추가
      • 위에서 2D를 달앗으면 rigidbody도 2D를 달아야함
      • 꼭 두 오브젝트 모두에 rigidbody를 달 필요는 없음
    • rigidbody가 달린 오브젝트에 monobehaviour 스크립트 추가하고 다음 세가지 함수 추가
      • OnCollisionEnter - 다른 어떤 Collider가 내 Collider 영역으로 들어왔을때 호출됨
      • OnCollisionStay - 다른 어떤 Collider가 내 Collider 영역에 있을때 호출됨
      • OnCollisionExit - 다른 어떤 Collider가 내 Collider 영역에 있다가 나갔을때 호출됨

기본은 이렇게만 하면 위 세가지 함수가 정상적으로 호출되며 충돌감지시 처리를 하면 되는데, rigidbody 옵션과 collider 의 isTrigger 옵션에 따라 함수 호출이 안되는 경우가 있다. 이럴때 아래 옵션값을 확인하며 체크를 해보자

 

  • rigidbody2D의 Simulated 가 체크되어 있는가? (다른 충돌체와 상호작용을 원하지 않을때는 체크해제한다)
  • rigidbody의 Kinematic 속성이 켜져 있을 경우 순전히 운동성(속도, 가속도, 위치)만 가지므로 위의 OnCollisionEnter, Stay, Exit 함수도 호출되지 않는다 (충돌이 일어나지 않으므로 서로 물리법칙에 의해 튕겨 나가는 등의 인터렉션이 없다 !!)
    • Kinematic 을 유지한채 충돌감지를 하고 싶을땐
      1. Collider의 isTrigger 옵션을 켠다.
      2. OnTriggerEnter, OnTriggerStay, OnTriggerExit 를 사용한다.
        • OnTrigger, OnCollision 두 종류 함수는 결코 같이 호출되는 일이 없다.

결론

만약 두 오브젝트를 중력이나 충돌상호작용 등 물리법칙에 영향받지 않고 충돌감지만 하고 싶을때는 Rigidbody의 Kinematic을 켜고, Collider의 isTrigger 옵션을 체크한 후 OnTriggerOOO 함수를 Rigidbody가 달린 스크립트에 추가하자

 

 

 

'Unity' 카테고리의 다른 글

Batch 및 SetPass Calls  (0) 2020.12.03
Quaternion 공간변환  (0) 2020.11.23
IL2CPP  (0) 2020.09.29
Addressables  (0) 2020.07.28
Mobile 최적화  (0) 2020.06.12

Unity가 제공하는 scripting backend 로서 빌드시 mono 대신 사용함.

 

C#은 msc.exe 라는 프로그램에 의해 IL 코드로 변환되며 유니티에서는 C# 코드를 빌드하면 Assembly-CSharp.dll 이라는 결과파일이 나오는데 이것을 IL 이라고 지칭한다.

이를 기계에 넣어서 실질적으로 실행시키기 위해선 Assembly코드, 즉 Binary로 변환해야 하는데 이 역할을 기존의 Mono가 함.

이 Mono가 코드를 한줄씩 읽으면서 실시간으로 Assembly 언어로 변환하는데, 이러한 일련의 과정을 JIT컴파일링 이라고 함 (Just In Time : IL을 해석하고 기계어로 변환하는 과정만을 JIT컴파일링 이라고 함)

 

IL2CPP도 msc.exe를 이용해 IL코드를 생성하는건 동일하지만, il2cpp.exe라는 프로그램을 통해 IL을 C++로 변환한후 이를 기계어까지 생성한다 (현재 대부분의 컴파일러들은 C++을 이용해 기계어를 생성할 수 있기 때문에 C++로만 바꿔도 따로 기계어로 번역하는 시스템을 안써도 됨 = Mono 로부터의 자유)

이렇게 되면 JIT컴파일링과는 다르게 이미 기계어로 변환되어 있기 때문에 실행중에 변환하는 Interprete 과정이 생략되어 성능이 향상됨

(외국인에게 얘기할때 중간에 통역자가 있으면 의사소통이 느리지만, 영어로 바로 얘기하면 서로 의사소통이 빠른것과 같음. 여기서 통역자는 Mono 되시겠다)

이런식의 실행도중 컴파일 과정이 없는 형태를 AOT컴파일링 이라고 하며 JIT와 반대개념이다.

물론 Mono에서도 AOT컴파일링을 제공한다. C++을 거치지않고..

 

여기서 한가지 의문점 발생

아니 그럼 Mono써서 그냥 AOT컴파일링 하면 되잖아. 왜 굳이 C++로 변환을 하지? 라고 생각이 들것이다.

몇가지 이유를 찾아봤는데,

  • 성능, 보안 및 플랫폼 호환성을 개선하는 용도
    • 성능 - 사용하지 않는 유니티 모듈들을 C++변환과정애서 제거할 수 있음 (link.xml 에 해당정보가 있음)
    • 보안 - Mono로 빌드시 디컴파일러 툴을 이용해 쉽게 소스코드로 변환이 가능한데 IL2CPP로 빌드된건 디컴파일해도 쉽게 해킹 불가능
    • 호환성 - iOS 64bit 호환 가능 (Mono는 지원하지 않음)
    • 구버전의 Mono로 최신 플랫폼등을 대응하기가 어려움

정도이다.

 

장점만 나열하니 우와 좋은거네 라고 할 수도 있지만, 단점도 분명 존재한다.

  • 컴파일 시간이 길다.
    • iOS의 경우 Xcode 프로젝트로 뽑아내는 시간 + Xcode 에서 앱빌드하는 시간
    • 중간에 C++로 변환하는 단계를 거치기 때문에 다소 시간이 더걸림
  • AOT 컴파일만 지원

'Unity' 카테고리의 다른 글

Quaternion 공간변환  (0) 2020.11.23
rigidbody, collider 개념 및 정리  (0) 2020.10.08
Addressables  (0) 2020.07.28
Mobile 최적화  (0) 2020.06.12
좌표계  (0) 2020.06.09

ttps://docs.unity3d.com/Packages/com.unity.addressables@1.11/manual/index.html

 

Unity Addressable Asset system | Addressables | 1.11.2

Unity Addressable Asset system The Addressable Asset system provides an easy way to load assets by “address”. It handles asset management overhead by simplifying content pack creation and deployment. The Addressable Asset system uses asynchronous loadi

docs.unity3d.com

 

Getting Started

  1. 유니티에서 기존 Assetbundle Browser를 대체해 만든 bundle 관리 시스템
  2. package manager를 통해 설치 가능(Addressables 검색)
  3. 유니티의 ProjectView 에서 Object 선택시 Inspector 창에 Addressables라는 체크항목이 생겼음을 확인
  4. 메뉴의 Windows -> Asset Management -> Addressables -> Groups 를 통해 번들 관리 가능

Overview

  1. 기존에는 Inspector창 아랫 부분에서 AssetBundle dropdown을 통해 설정하거나, 별도의 script를 만들어 관리
  2. Inspector에서 Addressables 를 체크하면 자동으로 Group창에 노출됨
  3. 해당 항목은 Addressables Group 창에서 드래그를 통해 다른 Group에 포함시키거나 제외 시킬 수 있음

prefab을 Addressables 등록 

Architecture

  1. Addressables Groups 창에는 Playmode가 있는데 각각 선택시마다 내부에서 처리하는 방식이 상이
    • 각 모드에 대한 특징은 위의 document 에 기술되어 있으므로 여기서는 각 모드가 어떻게 내부에서 번들을 관리하는지 설명
    • Use Asset Database(faster)
      • catalog path : Project Folder/Library/com.unity.addressables/catalog_BuildScriptFastMode.json
      • settings path :                                        ''                               /settings_BuildScriptFastMode.json
      • 번들을 빌드하지 않고, Entry Point를 통해 직접 접근하므로 Load가 빠르다(개발단계 유리)
    • Simulate Groups(advanced)
      • catalog path : Project Folder/Library/com.unity.addressables/catalog_BuildScriptVirtualMode.json
      • settings path :                                      ''                                 /settings_BuildScriptVirtualMode.json
      • 가상의 bundle을 빌드해서 그 bundle을 통해 Asset에 접근하는 방식으로, bundle간 dependency가 제대로 되어있는지, 모바일로 빌드했을때 참조 에러가 나지 않는지 editor 환경에서 bundle 참조확인이 가능하므로, 빌드 직전 리소스 테스트 단계에 유리
    • Use Existing Build(requires built groups)
      • 스크립트를 통해 빌드를 이미 수행했다는 전제하에, 물리적으로 존재하는 bundle을 직접 참조해서 Asset에 접근하는 방식
      • 개발 중 직접 bundle을 빌드해서 확인하고자 할떄 사용 (local build test에 유리)
      • catalog와 settings 파일은 빌드시에 Project Folder/Library/com.unity.addressables/StreamingAssetCopy/aa/[BuildTarget]에 만들어지므로 참조경로도 여기에 설정되어 있음
      • 이미 있는 bundle을 이용하는 모드이기 때문에 생성과정이 없으므로 실행시 가장 빠르다
  2. 각 프로젝트마다 위의 mode를 사용하지 않아야 할 떄가 있다. 가령 서버에 올라가 있는 번들을 받아서 돌리고 싶을때나, 버전 관리를 위해 json파일에 버전을 추가한다거나 할때 script를 커스터마이징 해야 하는데 이를 위해 Addressables가 번들 로드시 참조하는 값이 무엇인지, 그리고 각 파일들이 어떻게 연결되어 있는지 파악해야 함
    • 가령 한 PC 에서 bundle빌드를 돌린다고 가정
    • Addressables Group 창에서 Build -> New Build -> Default Build Script를 실행
    • Project Folder/Library/com.unity.addressables/StreamingAssetCopy/aa/[BuildTarget] 에 settings.json, catalog.json, link.xml이 생성됨
      • settings.json
        1. 이 프로젝트가 참조해야 할 catalog파일이 어디 존재하는지 명시
        2. hash파일과 remote hash 파일이 어디 존재하는지 명시
        3. 기타 Addressables 관련 환경변수가 저장되어 있음
      • catalog.json
        1. 실질적인 bundle들의 정보로서 모든 addressables의 이름, 경로, Key, Resource Type 이 정의되어 있음
        2. 해당 파일을 이용하면 이전 catalog와의 diff를 통해 자제적으로 버전관리도 가능할 수준의 detail하고 substantial한 정보
      • link.xml
        1. 본 프로젝트가 참조하고 있는 모든 라이브러리의 정보를 담고 있음
        2. editor 환경에서는 사용되지 않고, 모바일 빌드시 library포함여부에 관여
    • 결국 settings.json과 catalog.json 파일만 잘 만들어준다면, Addressables 커스터마이징을 할 수 있다는 의미

Remote Version 관리

  1. Remote Path
    • 서버의 catalog.json, catalog.hash 파일과 로컬의 catalog.json 파일을 비교해서 업데이트된bundle만 서버에서 선별해 받을 수 있는 Addressables Remote 시스템
  2. Firebase 를 통한 Addressables Remote
    • 문서를 만들게 된 계기가 된 항목으로서 firebase에 bundle을 업로드 한 후 RemoteLoadPath에 gs:// 로 시작하는 링크를 연결시 파일을 받아오지 못하는 문제가 발생
    • 기본적으로 Unity는 http, https로 시작하는 주소만 remote path라고 인식을 하기 때문에 기존 Addressables 에 대한 커스터마이징이 필요하게 됨
    • 해결법
      • 문제 해결을 위해선 LoadAsset을 통한 bundle요청시 gs://로 시작하는 주소를 https://주소로 변환한 다음 서버에 요청하고 그 결과를 반환해줘야 함
      • Addressables 에서는 이를 위해 AssetbundleProvider라는 함수를 제공
        1. 단 위 함수는 Addressables Group의 bundle로드시에만 동작하는 함수이기 때문에 Addressables의 주요 기능인 DownloadDependencyAsync 함수를 쓰기 위해선 별도의 방법이 필요
        2. Addressables.InternalIdTransformFunc 함수는 provideHandle.ResourceManager.TransformInternalId 함수 호출시 타도록 Unity가 제공하는 API
          • 이름에서도 알 수 있듯 개발자들이 Provider 에서 TransformId를 입맛대로 수정이 용이하도록 제공한 함수로서 v.1.75부터 제공한다
        3. 이를 이용해 서버에 존재하는 .hash, .json 로드시에도 서버에 gs protocol을 날리기 전에 동작을 가로채어 변환후 넘겨줄 수 있다.
      • 사용법(여기는 소스코드가 있다고 가정하고 설명, 소스는 github에서 확인가능)
        1. Addressables의 각 그룹을 선택한 후 Advanced Options 를 열어 Assetbundle Provider를 firebase assetbundle provider로 바꾸기
        2. Firebase 초기화가 완료되는 시점에 ResourceManager에 추가한 Provider를 등록
        3. Addressables.InternalIdTransformFunc에 콜백 함수 등록
          1. Provider를 상속받은 3개의 Class 내부의 Provide() 함수 안에서 TransformInternalId() 함수를 호출해서 gs internal id -> https internal id 로 바꿔준다
  3. Firebase가 아닌 서버에서 Addressables 의 Remote System을 적용하기 위한 코드 절차
    1. 서버로 요청하는 url이 https 가 아닌지 확인
    2. 총 3개의 Provider를 만들어 상속받기
      1. hash 파일을 위한 Provider (ResourceProviderBase 상속)
      2. catalog 파일을 위한 Provider (JsonAssetProvider 상속)
      3. bundle파일을 읽기 위한 Provider (AssetBundleProvider 상속)
    3. Addressables Group의 Inspector 창에서 Advanced Options -> Assetbundle Provider 항목에서 추가한 bundle provider 로 바꿔준다
    4. 사용하는 서버의 초기화 시점에서 추가한 Provider들을 등록해준다
      1. Addressables.ResourceManager.ResourceProviders.Add()
    5. Provider 함수 내부의 Provider() 를 override 해서 internal id 를 바꾼 후 provideHandle.ResourceManager.ProvideResource() 함수를 호출하고 Complete 성공 시 provideHandle.Complete() 를 호출해서 Unity에 넘겨준다

'Unity' 카테고리의 다른 글

rigidbody, collider 개념 및 정리  (0) 2020.10.08
IL2CPP  (0) 2020.09.29
Mobile 최적화  (0) 2020.06.12
좌표계  (0) 2020.06.09
유니티 셰이더 - UV 연산기법  (0) 2020.05.22

Mobile Profiler

각 플랫폼별 profiler 셋팅

프로파일러 항목별 최적화

  1. Meshskinning.SkinOnGPU
    렌더링 전 버텍스당 스키닝을 각 프레임마다 재계산하는데, 이 폴리곤이 많아지면 연산부담도 증가하게 됨.
    이 연산은 CPU에서 처리하는데 Unity에서 옵션값을 통해 GPU에게 할당할 수도 있음
    Player Settings > Player > Other Settings > Compute Skinning
    해당 값이 활성 > GPU 연산, 비활성 > CPU 연산
    언뜻 보면 GPU에게 맡기면 빠를거 같지만 모바일 환경은 GPU 사양이 제한되어 있어, 병목 원인에 따라 선택해야 함
    CPU로 연산하면 SIMD라는 아키텍처를 이용해 고속연산을 수행하기 때문에 모바일 환경이라면 비활성 하는게 이득
    하지만 프레임 드랍의 원인이 CPU라면 GPU에게 처리하도록 하는게 더 나은 방법
    *단, GPU 스키닝 연산은 OpenGL ES2에서는 지원되지 않음. DX11과 OpenGL ES3에서만 유효 (지원여부는 바뀔수있다)

  2. Dynamic Batching
    메시 렌더링시 월드공간 변환을 VS(버텍스셰이더) 에서 담당하는데 (=GPU 연산)
    해당 값 활성화시 이를 CPU에게 맡김 (CPU에게 오버헤드 가중)
    메시 렌더링(드로우콜)은 그래픽스 API 영향이 커서 좋은 API (Metal, Vulkan) 일 경우에는 이를 GPU에게 맡기는 것이 낫다

 

 

유니티 그래픽스 최적화 - 4. 드로우콜과 배칭 (Draw Call & Batching)

. . 4. 드로우콜과 배칭 (Draw Call & Batching) 4-1 드로우콜 (Draw Call) 수많은 병목지점이 있지만, 드로우콜이 병목인 경우가 많다. 최적화를 많이 간과하기 때문. 01) 드로우콜의 이해 CPU가 GPU에 오브젝��

wonsorang.tistory.com

Texture 최적화

  1. 한프레임당 생성할 텍스쳐가 많을 경우 new Texture()를 통해 LoadImage(byte[]) 함수를 쓰는 경우 이를 피하는 것이 좋다.
    • 만약 local file path를 알고 있다면, UnityWebRequestTexture 를 통해 GetTexture()로 바로 얻어오는게 이득 
  2. new Texture() 함수는 의외로 저비용. 만약 텍스쳐를 생성하는 중에 프레임 저하가 발생한다면, Texture에 색상값을 write하는 함수를 의심해볼것.

GC 최적화

  1. GC는 실행될때마다 메인 쓰레드를 잠시 멈추고 메모리를 한번 훑은 뒤 파편화된 공간들의 정리가 완료되면 메인쓰레드를 마저 실행해준다
    • 당연하게도 사용중인 힙메모리가 많을수록 GC.collect 실행시간이 증가하게되고 이는 곧 프레임저하의 주요 원인인 GC Peak를 유발한다
    • 주기적으로 호출하여 메모리를 자주 정리해주는건 좋지만 과도한 호출은 원활한 플레이에 지장을 줌
  2. 2019.3 버전부터 Incremental GC 기능이 추가되었는데, 이 기능은 GC 실행시 처리할 항목들을 여러 개로 나눠 처리하게 해주는 기능임. GC가 빈번히 호출되진 않지만, 호출시마다 GC Peak 가 가파른 환경에서 저 옵션을 켜는 것만으로도 눈에 띄는 효과를 볼 수 있음. 총 처리해야 할 총량이 줄어들진 않지만 나눠서 처리하기 때문에  많은 환경에서 이득을 기대할 만 함
  3. 위와 같은 처리를 해도 결국 메모리는 할당되어야 하고, 이 때문에 개발자들은 메모리를 절약할 수 있는 방법을 찾아야 함
    • 같은 동작이라도 처리방식에 따라 메모리 사용량이 다르기 때문에 병목현상이 발생한다면 API교체를 고려해보자
    • 총 힙메모리 양 대비 일정 가용량을 넘어서면 프레임 저하가 발생할 수 밖에 없으므로 현재 메모리 사용량을 항상 체크
      1. Profiler.usedHeapSizeLong과 Profiler.GetMonoUsedSize를 사용하여 현재 메모리 사용량을 파악할 수 있다
        • usedHeapSize : 우리가 아는 그 힙메모리로서, 변수 할당, 클래스 선언부터 Unity에서는 Texture, GameObject, Material등 런타임 관련 오브젝트를 다룰때 할당되는 영역
        • monoUsedSize : script, Asset, 등은 해당 영역에 할당. Unity의 스택 영역이라고도 볼 수 있다
      2. SystemInfo.SystemMemorySize : Unity가 쓸수 있는 메모리 총량

Shader 최적화

  1. Galaxy S20 폰에서 몇몇 머티리얼 렌더링 시 프레임 렉이 발생(픽셀이 깨져 해상도가 매우 낮아보임)
    • 60 frame 이상을 찍고 있는 상태에 렌더링 부분만 프레임 렉이 발생해서, 전형적인 GPU쓰로틀링 현상이라 쉐이더 픽셀연산을 살펴보았지만, 단순히 텍스쳐에 _Time.y 을 이용한 UV 애니메이션이 들어간 쉐이더조차 프레임 렉이 발생
    • 원인은 _Time 변수 때문이었는데, 요 값은 게임시작 시부터 지금까지 흐른 시간을 받아오는 변수라서, 수많은 유니티 강좌에서 UV 애니메이션을 설명할때 자주 등장한다.
    • 문제는 이 값이 계속 증가하면서 모바일GPU 칩의 부동소수점 연산처리 한도를 벗어나게 되어, 제대로 된 _Time.y 값이 반환되지 않았던 것이다.
    • Galaxy S20의 GPU칩은 16bit 나 그 이하의 비트만을 부동소수점 연산으로 제공하기 때문에 문제가 도드라져 보였던 것
    • 해결책으로는 _Time.y 값을 쓰지 않고 외부의 script에서 Time.deltaTime 값을 누적해 직접 쉐이더에 전달하고, 해당 값은 일정 값을 넘지 않도록 클램핑하는 것이다.
    • _Time 을 이용한 UV 애니메이션이 들어간 모든 Shader 를 고치는 대공사를 진행함

프로그래밍 & 코드 최적화

  1. 적절한 targetFrameRate 설정
    • Adaptive Performance 사용 고려
      • 현재 메모리 가용상태에 대한 콜백을 제공하고, 병목의 원인이 GPU인지 CPU인지 정보도 알려줌
      • PackageManager 에서 설치 후 콜백만 연결해주면 바로 사용 가능
      • Galaxy S10 이상의 안드로이드만 지원
      • 추후 지원폰을 확대하겠다고 했지만, 마지막 버전이 나온지 1년이 넘었네..
  2. 비동기 로딩 사용
    • AssetBundle.LoadFromFileAsync() 등..Async가 붙은 함수를 사용하자
  3. 사용하지 않는 MonoBehaviour 함수 제거
    • Start(), Update(), FixedUpdate() 등은 C++ (엔진) 단에서 C# 함수와 매핑과정을 거치는데 많을수록 엔진 메모리에 할당을 많이 해줘야 하므로 안쓰면 지워줘야 한다.
    • 코드 내부에 아무것도 없으니까 남겨놔도 되겠지 생각하지만, 엔진은 내부가 비어있는지를 판단할 수 없기 때문에 무조건 호출함(맵핑함)
  4. Update() 내부에서 다음 함수들의 사용은 지양할것(모두C++단을 통해 찾은 뒤 C#단으로 넘겨주는 함수)
    • GameObject.xxx (Find(), FindObjectsOfType() 등..)
    • GetComponent()
    • Camera.main
  5. Debug.Log() 주의
    • 코드가 그대로 빌드에 넘어가므로 출시 전쯤에는 전처리를 이용해 비활성화 설정
  6. 정적 데이터 파싱 주의
    • XML/JSON 은 런타임시 바로 읽는건 지양하고 Scriptable Object 형태로 읽을 수 있도록 개발툴을 마련하기

본 포스팅은 'Dev Weeks : 성능 프로파일링과 최적화' Youtube 영상을 정리한 것입니다.

'Unity' 카테고리의 다른 글

rigidbody, collider 개념 및 정리  (0) 2020.10.08
IL2CPP  (0) 2020.09.29
Addressables  (0) 2020.07.28
좌표계  (0) 2020.06.09
유니티 셰이더 - UV 연산기법  (0) 2020.05.22

Viewport 좌표계

카메라에 종속적인 normalize 된 데이터
bottom-left : 0,0
top-right   : 1,1
top-left    : 0,1
bottom-right: 1,0

Screen 좌표계

스크린 해상도에 따른 픽셀 데이터
bottom-left : 0,0
top-right   : Screen.width,Screen.height
top-left    : 0,Screen.height
bottom-right: Screen.width,0

UV 좌표계

viewport 좌표계와 동일
bottom-left : 0,0
top-right   : 1,1
top-left    : 0,1
bottom-right: 1,0

'Unity' 카테고리의 다른 글

rigidbody, collider 개념 및 정리  (0) 2020.10.08
IL2CPP  (0) 2020.09.29
Addressables  (0) 2020.07.28
Mobile 최적화  (0) 2020.06.12
유니티 셰이더 - UV 연산기법  (0) 2020.05.22

색상값에 따라 UV를 조작한 결과

 

이를 응용하면 아래와 같은 흥미로운 효과를 연출할 수 있음

r값이 1에 가까운 부분일수록 UV가 더 많이 이동되어 뽀올록 한 결과가 나타남

 

 

그렇다면 아래 2 텍스처를 이용하면 어떤 결과가 나올까?

왼쪽은 원본, 오른쪽은 일명 노이즈 텍스쳐라 불리는 UV 조작용 텍스처다

 

2개의 텍스쳐를 받는 쉐이더를 만들고, surf 함수 내부에서 아래와 같이 연산을 가해주면,

위 코드는 노이즈 텍스쳐를 계속 움직여 주는 코드, 아래는 뽀올록 효과를 주는 코드

물이 일렁이는 효과를 줄 수 있다.

 

쉐이더 공부 중 uv연산 응용의 맛보기를 본 것 같아 퍼왔습니다.

 

출저 : https://darkcatgame.tistory.com/9?category=806332

'Unity' 카테고리의 다른 글

rigidbody, collider 개념 및 정리  (0) 2020.10.08
IL2CPP  (0) 2020.09.29
Addressables  (0) 2020.07.28
Mobile 최적화  (0) 2020.06.12
좌표계  (0) 2020.06.09

+ Recent posts