블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2737)
Unity3D (817)
Script (91)
Extensions (14)
Effect (3)
NGUI (77)
UGUI (8)
Physics (2)
Shader (36)
Math (1)
Design Pattern (2)
Xml (1)
Tips (200)
Link (22)
World (1)
AssetBundle (25)
Mecanim (2)
Plugins (70)
Trouble Shooting (68)
Encrypt (7)
LightMap (4)
Shadow (4)
Editor (8)
Crash Report (3)
Utility (9)
UnityVS (2)
Facebook SDK (2)
iTween (3)
Font (11)
Ad (14)
Photon (2)
IAP (1)
Google (8)
Android (45)
iOS (41)
Programming (474)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (58)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
04-23 22:23

[링크] https://dark0946.tistory.com/226

 

[ Unity ] 유니티 로컬라이징, 태국어 폰트 적용 문제

태국어라곤 사와디캅( 정작 태국어로 어떻게 적는지도 모름 ) 밖에 모르던 저에게 태국어 로컬라이징 작업이 떨어졌습니다. 이전부터 게임 한글패치 작업을 좀 해본 경험이 있어서 관련 툴 사

dark0946.tistory.com

[참고] https://github.com/SaladLab/Unity3D.ThaiFontAdjuster

 

GitHub - SaladLab/Unity3D.ThaiFontAdjuster: Utility to render Thai text correctly in Unity3D, especially for positioning tone ma

Utility to render Thai text correctly in Unity3D, especially for positioning tone mark (ก์กิ์ป์ปิ์ฎุญุ). - GitHub - SaladLab/Unity3D.ThaiFontAdjuster: Utility to render Thai text correctly in Unity...

github.com

 

반응형
Posted by blueasa
, |

こんにちは。技術部平山です。

今回は小ネタで、サンプルもありません。ビルドの解像度設定についてです。

スクリーンショットにあるように、PlayerSettingsのResolution and Presentation の項に、Resolution Scalingというものがあり、 Resolution Scaling ModeをデフォルトのDisabledからFixed DPIに 設定することができます( Androidマニュアル iOSマニュアル )。

これは、画素(ピクセル)の密度が同じになるように、機種によって解像度を自動で変える、という設定です。 上の画像では326dpi(dot per inch。1インチあたりの画素数)になっており、 これはiPhone4あたりからの伝統的な値です。 iPhone6Plusのような上位機種を除けば、だいたいこの密度になっています。

実際どうなるのか?

この設定にしておくと、ディスプレイの画素密度が326dpiの機械では、 元の解像度で描画されます。例えばiPhone8なら1334x750です。

ところが、画面の大きさの割に解像度が高い端末、 例えばiPhone8Plusであれば、元よりも低い解像度になります。 元の解像度は1920x1080ですが、これが1560x878になります。 元の画素密度は406dpiもありこれを326dpiに落とすと、 解像度が縦横それぞれ(326/406)倍されるわけです。

何のために使うの?

「無駄に高い解像度で描画して、フレームレートや電力消費を悪化させるのを防ぐため」です。

高解像度で描画する方が綺麗なのは確かですが、タダではありません。 GPUの処理負荷はかなりの部分が画素数に比例しますから、 1920x1080で描画する負荷は、1560x878で描画する負荷に比べて、 およそ1.5倍になります。 CPU側に余裕があって、フレームレートが画素数で決まっているようなケースでは、 この設定を有効にすることでフレームレートが1.5倍になる可能性がある、ということです。

また、元々60fpsで動いているような場合は、電力消費が改善します。 微々たる差しか感じられないことに無駄に電気を食うよりは、 少し解像度を下げて余力を残した方が良いかもしれません。 スマホの場合、あまり電力消費が大きいと熱のために処理能力が低下し、 フレームレートが落ちてくることもよくあります。 前もって解像度を下げておくことは、これを防ぐ効果もあるのです。

実際の例

実際の例としては、iPhone6Plus(1920x1080)で40FPSしか出なかったアプリが、 この設定を有効にするだけで60FPSに改善した例があります。

また、一部Android機のように、 GPU性能の割に解像度が高い(例えば京セラS2で1280x720、S4で1920x1080) 端末では、 元々フル解像度でゲームを動かすことには無理があり、 解像度を下げることで大きくフレームレートが改善します。 S2の場合、対角5インチのサイズで1280x720で、 1280画素ある長辺の長さは4.345インチです。 1280をこれで割ると、294dpiとなります。

iPhoneの326dpiよりも低いですが、 「そもそもこのゲームって、そんなに解像度高くてうれしいの?」 ということをよく考えてみれば、 製品によっては「もう少し低くてもいいな」という判断にもなるでしょう。

お客さんが選べるように選択肢を用意するのも一つの考えかと思いますが、 ほとんどのお客さんにとって適切な設定をデフォルトにするのもまた重要なことです。 画質とフレームレート、電力消費のバランスを鑑みて、 画素密度(dpi)で設定するのは悪くない選択でしょう。 設定一つで済むので実装コストはほぼゼロです。

製品の性質にもよりますが、200から300くらいを設定するのが良いのかな、 と個人的には思います。Nintendo Switchが235dpiであり(Switch Liteは268dpi) それだけあれば十分な気もします。 もし不安があるのであれば、たくさん売れたiPhoneを基準にして上の例のように326 に設定するのも良いでしょう。それでもPlus系での処理落ちを防げます。 その場合も、Androidでは低スペック機に配慮して下げる方が良い気がします (dpi設定はiOSとAndroidを別に持てないので、ビルド前にスクリプトで変更するのが良いでしょう)。

ダイナミックなフォントは解像度が高いほど綺麗になり、 3Dのポリゴンも解像度が高いほど輪郭が綺麗になりますが、 前もって用意したテクスチャは元解像度以上にはなりません。 解像度が高すぎてもボケて見えるだけで、 それは解像度を落として描くのとほとんど変わらないのです。 しかしフレームレートと電力消費は確実に悪化します。

別の方法

お客さんに解像度設定を委ねる場合には、これを使っての設定はできません。 一律になってしまうからです。 設定を見て、 Screen.SetResolution を起動後に呼ぶことになります。

Screenクラスからはdpiも取れますので、FixedDPIを使うのと同じこともできますが、 解像度変更はその場では終わらず次のフレームまでかかりますし、 解像度に依存した処理があると、解像度が変わった時におかしくなる危険もありますから、 注意しましょう。起動直後のみの反映が安全ですが、すぐに確認できないので利便性は落ちます。 設定画面を作るコストの問題もありますから、 製品の性質やお客さんにとっての価値を考えた上で、 良い選択をしてください。

なお、お客さんに設定して頂けるのであれば、 かなり攻めた設定(768x432まで解像度を下げるなど)ができ、 電気が気になる方(例えば私)や、低性能の機種をお使いの方(例えば私)に とってはうれしいのではないかと思います。 過去参加した製品 では、768x432で20fpsという省エネ設定ができるようにしましたが、 完全に私のためでした。

代表的な機械の画素密度

以下に代表的な機械のDPIを表にしておきます。 「この機械はドット粗いなあ」と思う機械よりは上げたいですが、 「これ以上細かくても差がわからないよ」「そもそもそんな高解像度で素材作ってないよ」 という場合には下げて良いかと思います。 素材の解像度が上がれば容量も増えて、通信料金やスマホのストレージにも 悪影響を与えますから、何事も程々のバランスが良いでしょう。

機種対角インチ解像度DPI

iPhone 5S,SE 4 1136x640 326
iPhone 6, 6S, 7, 8 4.7 1334x750 326
iPhone 6Plus, 6S Plus, 7Plus, 8Plus 5.5 1920x1080 406
iPhoneX, XS, 11Pro 5.85 2436x1125 458
iPhoneXS Max, 11ProMax 6.46 2688x1242 458
iPhoneXR, 11 6.06 1792x828 326
古めのiPadの多く 9.7 2048x1536 264
今のiPad 10.5 2224x1668 264
対角5インチの16:9機 5 960x540 221
対角5インチの16:9機 5 1280x720 295
対角5インチの16:9機 5 1920x1080 442
対角24インチのFullHDモニタ 24 1920x1080 92
Retina MacBookPro 13インチ 13 2560x1600 232
Nintendo Switch 6.2 1280x720 238
Nintendo Switch Lite 5.5 1280x720 268

QualitySettingsでの補正

この項目は試していないのですが、たまたま調べたら出てきたので紹介しておきます。

dpi値はQualitySettingsで修正することができるようです。 公式マニュアル にあるように、Resolution Scaling Fixed DPI Factorを設定すれば、 lowやmediumのような設定ごとに、先程設定したdpi値を補正することができるとあります。 0.5を書けば半分になり、例えば326dpiであれば163dpiになって、 解像度が半分になるのでしょう。

機械の性能を見てQualitySettings.SetQualityLevel などを呼んでいる場合には、動的に解像度も変わるのでしょうか? 正常に動くのか、どれくらい処理が止まるのか、といったことはわかりません。

終わりに

今回は小ネタでしたが、下手に最適化で苦労するよりもよほど簡単に効果が上がるので、強くオススメしておきます。

個人的には、多くのゲームのように画面に動きがあるアプリケーションで 300dpiを超えた描画するのは、電池が惜しいと感じます。 もし余力があるのであれば、解像度を上げるよりも、 ライティングなどのピクセルあたりの処理を豪華にする方が、 おそらくは品質も上がるでしょう。

 

 

[출처] https://techblog.kayac.com/unity-fixed-dpi

 

Unityで画素密度を固定する解像度設定(FixedDPI) - KAYAC engineers' blog

こんにちは。技術部平山です。 今回は小ネタで、サンプルもありません。ビルドの解像度設定についてです。 スクリーンショットにあるように、PlayerSettingsのResolution and Presentation の項に、Re

techblog.kayac.com

 

반응형
Posted by blueasa
, |

[추가] 2024-03-06

2024년 기준 폰 스펙이 많이 올라와서 이젠 최신폰에서 326으로는 깨지는게 보인다.

그래서 아이폰 최신인 아이폰15(460ppi)에 맞추기로 했다.

→ Target DPI : 326 -> 460으로 변경

----

 

1. Player Settings - Resolution and Presentation - Resolution Scaling

    1.1. Disabled → Fixed DPI로 변경

    1.2.1 Target DPI(Default:30) 280으로 변경(iPhone 13에서도 깨지는지 모르겠다고 함)

    1.2.2 Target DPI 326으로 변경(iPhone XR/11 : 326) : 나는 아이폰 기준 맞추기 위해 326으로 변경함

        [참조] https://techblog.kayac.com/unity-fixed-dpi

Fixed DPI : 280

 

2. Android 6.0(API Level 23) 이상이면 Android Texture Format : ASTC 사용 권장

    2.1. iPhone은 이전부터 ASTC 사용 권장하기 때문에 Android 6.0 이상이면 양쪽 플랫폼 동일하게 ASTC 사용가능 할 듯

 

 

[출처] 게임코디-선후님

 

 

반응형
Posted by blueasa
, |

[링크] https://blog.naver.com/dj3630/221461311485

 

[유니티 기초] - Audio

적절한 배경음악이나 효과음만으로도 게임의 분위기가 크게 좌우된다. 유니티는 사운드 미들웨어인 FMO...

blog.naver.com

 

반응형
Posted by blueasa
, |

Integrated Success 팀은 유니티 고객들이 복잡한 기술적 문제를 해결할 수 있도록 지원합니다. 유니티의 선임 소프트웨어 엔지니어로 구성된 이 팀과 함께 모바일 게임 최적화에 관한 전문적인 지식을 공유하는 자리를 마련했습니다.

유니티의 엔진 소스 코드를 완벽하게 파악하고 있는 Accelerate Solutions 팀은 Unity 엔진을 최대한 활용할 수 있도록 수많은 고객을 지원합니다. 팀은 크리에이터 프로젝트를 심도 있게 분석하여 속도, 안정성, 효율성 등을 향상시키기 위해 최적화할 부분을 파악합니다. 모바일 게임 최적화에 관한 인사이트를 공유하기 시작하면서, 원래 계획한 하나의 블로그 포스팅에 담기에는 너무나 방대한 정보가 있다는 사실을 알게 되었습니다. 따라서 이 방대한 지식을 한 권의 전자책(여기에서 다운로드 가능)과 75가지 이상의 실용적인 팁을 담은 블로그 포스팅 시리즈를 통해 제공하기로 했습니다.

이번 최적화 시리즈 최종 포스팅에서는 에셋, 프로젝트 구성 및 그래픽의 성능을 향상하는 방법을 자세히 살펴봅니다. 이전 포스팅에서는 프로파일링, 메모리, 코드 아키텍처뿐 아니라 물리, UI, 오디오에 대한 팁을 다뤘습니다. 게임 최적화 방법에 관한 시리즈 전체 내용을 확인하고 싶다면 무료 전자책을 다운로드하시기 바랍니다.

프로젝트 구성

모바일 성능에 영향을 줄 수 있는 몇 가지 프로젝트 설정이 있습니다.

Accelerometer Frequency 감소 또는 비활성화 

Unity는 모바일 기기의 가속도 센서를 1초에도 몇 번씩 풀링합니다. 애플리케이션에서 가속도 센서를 사용하지 않는다면 비활성화하거나 빈도를 줄여 성능을 개선하세요.

 
모바일 게임에서 활용하지 않는다면 Accelerometer Frequency를 비활성화해야 합니다.확장

불필요한 플레이어 설정 또는 품질 설정 비활성화

플레이어 설정에서 지원되지 않는 플랫폼의 Auto Graphics API를 비활성화하면 셰이더 배리언트가 과도하게 생성되지 않도록 방지할 수 있습니다. 애플리케이션이 오래된 CPU를 지원하지 않는다면 해당 CPU에 대해 Target Architectures를 비활성화합니다.

품질 설정에서 불필요한 품질 수준을 비활성화합니다.

불필요한 물리 비활성화

게임에서 물리를 사용하지 않는다면 Auto Simulation Auto Sync Transforms를 선택 해제합니다. 해당 기능을 선택하면 별다른 이득 없이 애플리케이션의 속도가 저하될 수 있습니다.

올바른 프레임 속도 선택 

모바일 프로젝트에서는 프레임 속도와 배터리 수명, 서멀 스로틀링이 균형을 이루어야 합니다. 기기의 한계인 60fps까지 밀어 붙이기 보다는 30fps 정도에서 타협해 실행하는 것이 좋습니다. Unity는 모바일의 경우 30fps를 기본으로 설정합니다.

또한 Application.targetFrameRate를 활용해 런타임 중에 프레임 속도를 동적으로 조정할 수도 있습니다. 예를 들어 속도가 느리거나 비교적 정적인 씬의 경우 30fps 아래로 낮추고 게임플레이 중에는 더 높은 fps 설정을 유지할 수 있습니다.

대규모 계층 구조 사용 지양

Split your hierarchies. 게임 오브젝트가 계층 구조 내에 중첩될 필요가 없다면 부모 자식 관계를 간소화하세요. 계층 구조가 단순하면 씬에서 트랜스폼을 새로고침할 때 멀티스레딩의 이점을 누릴 수 있습니다. 계층 구조가 복잡하면 불필요한 트랜스폼 연산과 높은 가비지 컬렉션 비용이 발생합니다.

트랜스폼에 관한 베스트 프랙티스는 계층 구조 최적화와 이 Unite 세션을 참고하세요. 

트랜스폼 한 번에 이동

아울러 트랜스폼 이동 시, Transform.SetPositionAndRotation을 사용하여 위치와 회전을 한 번에 업데이트하세요. 이렇게 하면 트랜스폼을 두 번 수정함으로써 발생하는 오버헤드를 방지할 수 있습니다.

런타임에서 게임 오브젝트를 인스턴트화해야 한다면 다음과 같이 단순한 최적화로 인스턴스화 중에 부모 자식 관계를 설정하고 다시 포지셔닝할 수 있습니다.

GameObject.Instantiate(prefab, parent);

GameObject.Instantiate(prefab, parent, position, rotation);

Object.Instantiate에 대한 자세한 정보는 Scripting API를 참고하세요.

Vsync가 활성화되어 있다고 가정 

모바일 플랫폼은 절반 프레임을 렌더링하지 않습니다. 에디터에서 Vsync를 비활성화하더라도(Project Settings > Quality) 하드웨어 수준에서는 Vsync가 활성화되어 있습니다. GPU가 충분히 빠르게 새로고침할 수 없는 경우, 현재 프레임이 유지되면서 사실상 fps가 줄어듭니다. 

에셋

에셋 파이프라인은 애플리케이션의 성능에 지대한 영향을 줄 수 있습니다. 숙련된 테크니컬 아티스트가 에셋 형식, 사양, 임포트 설정을 정의하고 실행하여 프로젝트를 원활하게 진행할 수 있도록 팁을 제공합니다.

기본 설정에 의존하지 마세요. 플랫폼별 오버라이드 탭을 사용하면 텍스처, 메시 지오메트리와 같은 에셋을 최적화할 수 있습니다. 잘못된 설정으로 인해 빌드 크기가 커지고 빌드 시간이 길어지며 메모리 사용 상황이 열약해질 수 있습니다. 프리셋 기능으로 특정 프로젝트에 사용할 기본 설정을 커스터마이징하는 것이 좋습니다.

자세한 내용은 아트 에셋 베스트 프랙티스 가이드 또는 Unity Learn의 '모바일 애플리케이션용 3D 아트 최적화' 강의에서 확인하시기 바랍니다.

올바른 텍스처 임포트 

대부분의 메모리가 텍스처에 사용되기 때문에 임포트 설정이 매우 중요합니다. 일반적으로 다음 가이드라인을 따릅니다.

  • 최대 크기 줄이기: 시각적으로 허용 가능한 결과를 내는 최소한의 설정을 사용합니다. 이렇게 하면 결과물의 손상을 피하면서 빠르게 텍스처 메모리를 줄일 수 있습니다.
  • POT(Powers of Two) 사용: Unity에서 모바일 텍스처 압축 형식(PVRCT 또는 ETC)을 사용하려면 POT 텍스처가 필요합니다.
  • 텍스처 아틀라스 사용: 하나의 텍스처에 여러 텍스처를 배치하면 드로우 콜을 줄이고 렌더링 속도를 높일 수 있습니다. Unity 스프라이트 아틀라스 또는 타사의 TexturePacker 를 사용하여 아틀라스를 만들어 보세요.
  • Read/Write Enabled 옵션 해제: 활성화할 경우 이 옵션은 CPU와 GPU로 처리 가능한 메모리에서 사본을 만들기 때문에 텍스처의 메모리 사용 공간이 중복됩니다. 대부분의 경우 이 옵션은 비활성화 상태로 유지합니다. 런타임에서 텍스처를 생성할 경우 Texture2D.Apply 함수를 사용하고, makeNoLongerReadable 값은 true로 전달합니다.
  • 불필요한 밉맵 비활성화: 2D 스프라이트와 UI 그래픽처럼 화면상에 일정한 크기로 유지되는 텍스처에는 밉맵이 필요하지 않습니다(카메라의 거리에 따라 다른 3D 모델에 대해서는 밉맵을 활성화된 상태로 유지).
 
빌드 크기를 최적화하는 데 도움이 되는 적절한 텍스처 임포트 설정확장

텍스처 압축 

동일한 모델과 텍스처를 사용하는 두 가지 예를 생각해 보겠습니다. 왼쪽의 설정은 오른쪽에 비해 거의 8배 많은 메모리를 사용하지만 화질에서 큰 차이를 보이지 않습니다.

 
압축되지 않은 텍스처에는 더 많은 메모리가 필요합니다.확장

iOS와 Android 모두에서 ASTC(Adaptive Scalable Texture Compression)를 사용하세요. 개발 중인 대부분의 게임이 ASTC 압축을 지원하는 최소 사양 기기를 대상으로 합니다.

유일한 예외는 다음과 같습니다.

  • A7 이하 버전인 기기(예: iPhone 5, 5S)를 대상으로 하는 iOS 게임 - PVRTC 사용
  • 2016년 이전의 기기를 대상으로 하는 Android 게임 - ETC2 (Ericsson Texture Compression) 사용

PVRTC와 ETC 같은 압축 형식의 화질이 충분히 높지 않고 ASTC가 대상 플랫폼에서 완전히 지원되지 않는다면 32비트 텍스처 대신 16비트 텍스처를 사용해 보세요.

플랫폼별 추천 텍스처 압축 형식에 관한 자세한 정보는 매뉴얼을 참고하세요.

메시 임포트 설정

텍스처와 마찬가지로 메시도 신중하게 임포트하지 않으면 과도한 메모리 사용으로 이어질 수 있습니다. 메시의 메모리 사용량을 최소화하려면 다음 지침을 따르세요.

  • 메시 압축: 과감한 압축으로 디스크 공간을 줄일 수 있습니다(런타임 시 메모리에는 영향을 주지 않음). 메시 양자화로 인해 정확성이 떨어질 수 있으므로 압축 수준을 다양하게 조절해보고 모델에 적합한 수준을 파악하세요.
  • Read/Write Enabled 비활성화: 이 옵션을 활성화하면 각각 메시 사본이 시스템 메모리와 GPU 메모리에 유지되므로 메모리에서 메시가 중복됩니다. 대부분의 경우에는 비활성화해야 합니다(Unity 2019.2 이하에서는 이 옵션이 기본으로 선택되어 있음).
  • Rig과 BlendShapes 비활성화: 메시에 골격 또는 블렌드 셰이프 애니메이션이 필요하지 않다면 이 옵션을 비활성화합니다.
  • Normal과 Tangent 비활성화: 메시의 머티리얼에 노멀 또는 탄젠트가 필요하지 않은 것이 확실하다면 이 옵션을 선택 해제하여 추가로 메모리를 절감할 수 있습니다.
 
메시 임포트 설정 확인확장

폴리곤 개수 확인 

해상도가 높은 모델은 메모리 사용량이 더 많고 잠재적으로 GPU 시간이 더 길 수 있습니다. 백그라운드 지오메트리에 폴리곤이 50만 개나 필요할까요? DCC에서 모델 수를 줄여 보세요. 카메라의 시점에서 보이지 않는 폴리곤은 삭제하고, 고밀도 메시 대신 텍스처와 노멀 맵을 사용하여 정교한 디테일을 표현하세요.

AssetPostprocessor를 사용하여 임포트 설정 자동화 

에셋을 임포트할 때 AssetPostprocessor를 사용하여 스크립트를 실행할 수 있습니다. 이렇게 하면 모델, 텍스처, 오디오 등의 임포트 전후로 설정을 커스터마이즈하라는 메시지가 표시됩니다.

어드레서블 에셋 시스템 사용 

어드레서블 에셋 시스템을 사용하면 콘텐츠를 간단하게 관리할 수 있습니다. 이 통합된 시스템은 로컬 경로 또는 원격 콘텐츠 전송 네트워크(CDN)에서 비동기적으로 '주소' 또는 별칭에 따라 AssetBundle을 로드합니다.

 
확장

코드가 아닌 에셋(모델, 텍스처, 프리팹, 오디오, 전체 씬)을 AssetBundle에 나눌 경우 다운로드 가능한 콘텐츠(DLC)로 분리할 수 있습니다.

그런 다음 어드레서블을 사용하여 모바일 애플리케이션에 사용할 더 작은 초기 빌드를 만듭니다. 클라우드 콘텐츠 전송을 사용하면 게임 콘텐츠를 호스트하고 게임이 진행됨에 따라 플레이어에게 데이터를 전송할 수 있습니다.

 
어드레서블 에셋 시스템을 사용하여 '주소'에 따라 에셋 로드확장

여기를 클릭하여 어드레서블 에셋 시스템이 에셋 관리의 번거로움을 덜어주는 방법에 대해 알아보세요.

그래픽스 및 GPU 최적화

Unity는 프레임마다 렌더링해야 하는 오브젝트를 지정한 다음 드로우 콜을 만듭니다. 드로우 콜은 오브젝트(예: 삼각형)를 그리기 위한 그래픽스 API 호출이며, 배치는 함께 실행되는 드로우 콜의 그룹입니다.

프로젝트가 복잡해질수록 GPU의 워크로드를 최적화해 주는 파이프라인이 필요합니다. URP(Universal Render Pipeline, 유니버설 렌더 파이프라인)는 현재 싱글 패스 포워드 렌더러를 사용하여 모바일 플랫폼에서 고화질 그래픽을 구현합니다(디퍼드 렌더링은 향후 릴리즈에서 제공될 예정). 콘솔과 PC에서의 동일한 물리 기반 광원 및 머티리얼도 스마트폰이나 태블릿으로 확장할 수 있습니다.

다음 가이드라인은 그래픽의 속도를 높이는 데 도움이 될 수 있습니다.

드로우 콜 배칭 

함께 그릴 오브젝트를 배치로 구성하면 각 오브젝트를 그리는 데 필요한 상태 변화가 최소화됩니다. 그 결과 오브젝트를 렌더링하는 데 드는 CPU 비용이 감소하므로 성능이 향상됩니다. Unity는 여러 기법을 사용하여 여러 오브젝트를 보다 적은 수의 배치로 구성할 수 있습니다.

  • 동적 배칭: 작은 메시의 경우 Unity는 CPU에서 버텍스를 그룹화하고 변환한 다음 모두를 한 번에 그립니다. 참고: 로우 폴리 메시가 충분한 경우에만 이 기법을 사용하세요(버텍스 속성 900개, 버텍스 300개 미만). Dynamic Batcher는 이보다 큰 메시를 배칭하지 않으므로, 용도에 맞지 않게 활성화할 경우 프레임마다 배칭할 작은 메시를 찾느라 CPU 시간을 낭비하게 됩니다.
  • 정적 배칭: 움직이지 않는 지오메트리의 경우 Unity는 동일한 머티리얼을 공유하는 메시에 대한 드로우 콜을 줄일 수 있습니다. 동적 배칭에 비해 더 효율적이지만 메모리 사용량은 늘어납니다.
  • GPU 인스턴싱: 동일한 오브젝트의 수가 많을 때 이 기법을 사용하면 그래픽 하드웨어의 사용을 통해 더 효율적인 배칭이 가능합니다.
  • SRP 배칭: 유니버설 렌더 파이프라인 에셋 Advanced 항목에서 SRP Batcher를 활성화합니다. 이렇게 하면 씬에 따라 CPU 렌더링 시간이 크게 빨라집니다.
 
이와 같은 배칭 기법을 활용할 수 있도록 게임 오브젝트를 정리하세요.확장

프레임 디버거 사용 

프레임 디버거는 개별 드로우 콜에서 각 프레임이 구성된 방식을 보여줍니다. 게임이 렌더링되는 방식을 분석하는 데 도움이 되는 셰이더 속성의 문제 해결에 유용한 도구입니다.

 
각 프레임을 개별 단계로 나누는 프레임 디버거확장

프레임 디버거를 처음 접한다면 여기에서 이 소개 튜토리얼을 확인하세요.

동적 광원 수 줄이기 

모바일 게임에는 동적 광원을 지나치게 많이 추가하지 않는 것이 매우 중요합니다. 동적 메시에는 커스텀 셰이더 이펙트나 라이트 프로브, 정적 메시에는 베이크된 광원과 같은 대안을 고려해 보세요.

URP와 빌트인 파이프라인에서 실시간 광원의 구체적인 지원 및 제한 사항을 보려면 기능 비교 테이블을 참고하세요.

그림자 비활성화 

MeshRenderer 및 광원별로 그림자 드리우기를 비활성화할 수 있습니다. 가능하면 그림자를 비활성화하여 드로우 콜을 줄이세요. 

캐릭터 아래의 간단한 메시나 쿼드에 블러된 텍스처를 적용하여 가짜 그림자를 만들 거나, 커스텀 셰이더로 블롭 섀도우를 만듭니다.

 
Cast Shadow를 비활성화하여 드로우 콜 줄이기확장

라이트맵에 조명 베이크 

GI(Global Illumination, 전역 조명)로 정적 지오메트리에 극적인 조명을 추가하세요. 오브젝트를 Contribute GI로 표시하면 라이트맵의 형태로 고품질 조명을 저장할 수 있습니다.

Contribute GI 활성화  

이제 베이크된 그림자와 조명을 런타임 시 성능 저하 없이 렌더링할 수 있습니다. 프로그레시브 CPU 및 GPU 라이트매퍼로는 전역 조명의 베이킹을 가속화할 수 있습니다.

 

 
라이트매핑 설정(Windows > Rendering > Lighting Settings)과 라이트맵 크기를 조정하여 메모리 사용량 제한확장

Unity에서 라이트매핑을 시작하는 데 도움이 필요하다면 매뉴얼 가이드 조명 최적화에 관한 이 페이지를 참고하세요.

광원 레이어 사용 

광원이 여러 개인 복잡한 씬의 경우 레이어를 사용해 오브젝트를 분리한 다음 각 광원의 영향을 특정 컬링 마스크로 한정합니다. 

 
레이어를 사용하여 광원의 영향을 특정 컬링 마스크로 제한하기확장

움직이는 오브젝트에 라이트 프로브 사용

라이트 프로브는 씬 내의 빈 공간에 대해 베이크된 조명 정보를 저장하고 직접 또는 간접적으로 고품질 조명을 제공합니다. 여기에는 동적 광원에 비해 매우 빠르게 계산하는 구면 조화(Spherical Harmonics) 함수가 사용됩니다.

 
백그라운드의 동적 오브젝트를 비추는 라이트 프로브확장

디테일 수준(LOD) 사용 

오브젝트가 멀리 이동하면 디테일 수준을 통해 단순한 메시와 머티리얼, 셰이더를 사용하도록 조정하거나 전환하여 GPU 성능을 보조할 수 있습니다.

 
LOD 그룹을 사용하는 메시의 예시확장
 
다양한 해상도로 모델링한 소스 메시확장

오클루전 컬링을 사용하여 숨겨진 오브젝트 제거 

다른 오브젝트 뒤에 숨겨진 오브젝트는 계속 렌더링되며 리소스 비용을 발생시킬 수 있습니다. 오클루전 컬링을 사용하여 이러한 오브젝트를 폐기하세요. 

카메라 뷰 바깥의 절두체 컬링은 자동인 반면 오클루전 컬링은 베이크된 과정입니다. 오브젝트를 Static Occluders 또는 Occludees로 표시한 다음 Window > Rendering > Occlusion Culling을 통해 베이크하면 됩니다. 모든 씬에 필요하지는 않지만 많은 경우에 컬링으로 성능을 향상할 수 있습니다.

자세한 내용은 오클루전 컬링 사용하기 튜토리얼을 확인하세요.

모바일 기기의 네이티브 해상도 사용 지양 

스마트폰과 태블릿이 점점 발전함에 따라 새로 출시되는 기기일수록 매우 높은 해상도를 자랑하곤 합니다. 

Screen.SetResolution(width, height, false)을 사용하여 출력 해상도를 낮추면 어느 정도의 성능을 다시 확보할 수 있습니다. 여러 해상도를 프로파일링하여 화질과 속도 사이에서 최적의 균형을 찾아보세요.

카메라 사용 제한

모든 카메라는 작업 수행에 어느 정도의 오버헤드를 유발합니다. 렌더링에 필요한 카메라 컴포넌트만 사용하세요. 저사양 모바일 플랫폼에서는 카메라당 최대 1ms의 CPU 시간을 사용할 수 있습니다.

셰이더를 단순하게 유지 

유니버설 렌더 파이프라인은 이미 모바일 플랫폼에 최적화된 경량 릿 셰이더와 언릿 셰이더를 다양하게 포함하고 있습니다. 런타임 메모리 사용량에 상당한 효과를 미칠 수 있으므로 셰이더 베리에이션을 최대한 낮게 유지하세요. 기본 URP 셰이더가 필요에 맞지 않는다면 셰이더 그래프를 사용해 머티리얼의 외관을 커스터마이징할 수 있습니다. 여기에서 셰이더 그래프를 사용해 시각적으로 셰이더를 빌드하는 방법을 알아보세요.

 

 
셰이더 그래프로 커스텀 셰이더 만들기확장

오버드로우와 알파 블렌딩의 최소화

불필요한 투명 또는 반투명 이미지를 그리지 마세요. 모바일 플랫폼은 오버드로우와 알파 블렌딩의 영향을 크게 받습니다. 거의 보이지 않는 이미지 또는 이펙트를 겹치지 마세요. RenderDoc 그래픽 디버거를 사용해 오버드로우를 확인할 수 있습니다.

포스트 프로세싱 이펙트 제한 

글로우와 같은 전체 화면 포스트 프로세싱 이펙트는 성능을 크게 떨어뜨릴 수 있습니다. 프로젝트의 아트 방향성에 따라 주의하여 사용하세요.

 
모바일 애플리케이션에서는 포스트 프로세싱 이펙트를 단순하게 유지확장

Renderer.material 유의하기 

스크립트의 Renderer.material에 액세스하면 머티리얼이 복사되고 새로운 사본에 대한 참조가 반환됩니다. 이로 인해 이미 해당 머티리얼을 포함하는 기존 배치가 손상됩니다. 배칭된 오브젝트의 머티리얼에 액세스하려면 Renderer.sharedMaterial을 대신 사용하세요.

SkinnedMeshRenderers 최적화 

스킨드 메시를 렌더링하는 데는 비용이 많이 듭니다. SkinnedMeshRenderer를 사용하는 모든 오브젝트에 사용할 필요가 있는지 확인하세요. 게임 오브젝트에 가끔 애니메이션만 필요한 경우 BakeMesh 함수를 사용하여 스킨드 메시를 정적인 포즈로 고정하고 런타임 시에는 더 단순한 MeshRenderer로 대체하세요.

반사 프로브 최소화 

반사 프로브는 사실적인 반사를 만들어 낼 수 있지만 배치의 차원에서 봤을 때 비용이 매우 높습니다. 저해상도 큐브맵, 컬링 마스크, 텍스처 압축을 사용해 런타임 성능을 높이세요.

모바일 성능 최적화에 대한 전체 가이드 다운로드

이 포스팅은 모바일 성능 최적화 시리즈의 마지막 게시물이며, 팀에서 제공하는 유용한 팁의 전체 목록을 확인하고자 하는 분들을 위해 52페이지 분량의 전자책을 출간하였으며, 여기에서 다운로드 할 수 있습니다. 

 
확장

전자책 다운로드

통합 지원 서비스에 대해 자세히 알아보고 엔지니어, 전문가 조언 및 프로젝트에 맞는 베스트 프랙티스 가이드를 이용하려면 여기에서 유니티의 Success 플랜을 확인해 보세요.

원하는 내용을 찾지 못하셨나요?

유니티는 Unity 애플리케이션이 성능을 최대한 발휘할 수 있도록 지원하고 있습니다. 자세히 알고 싶은 최적화 주제가 있다면 댓글로 알려주세요. 

2021년 8월 3일 테크놀로지 | 12 분 소요
 
 

 

[출처] https://blog.unity.com/kr/technology/optimize-your-mobile-game-performance-expert-tips-on-graphics-and-assets

 

모바일 게임 성능 최적화: 그래픽과 에셋에 관한 전문가 팁 | Unity Blog

이 포스팅은 모바일 성능 최적화 시리즈의 마지막 게시물이며, 팀에서 제공하는 유용한 팁의 전체 목록을 확인하고자 하는 분들을 위해 52페이지 분량의 전자책을 출간하였으며, 여기에서 다운

blog.unity.com

 

반응형
Posted by blueasa
, |

  [참고 사항]

- Scale 제거하면 AnimationClip(.anim) 파일 용량이 오히려 늘어남

   = 유니티 에디터의 Animation Editor에서 사용하는 정보값을 넣는다고 함(아래 링크 내용 참조)

   = 빌드 할 때는 에디터 관련 정보는 제거하고 들어감(빌드해서 확인함)

   = 애니메이션 파일을 에셋번들 빌드해도 관련 정보 제거하고 줄어드는 걸 볼 수 있음

 

- Unity Editor에서 '메모리 프로파일러' 등으로 보면 런타임 메모리도 오히려 늘어남

   = 위의 에디터용 정보가 들어간채로 로드 되는 듯 함(에디터의 프로파일러를 모두 신뢰하지 말라고 함(?) 아래 참조링크 참조)

   = 실제 런타임 메모리는 실제 사용할 디바이스(폰 등)에서 확인해야 함(폰 빌드하고 메모리 프로파일러로 런타임 메모리 줄어드는 것 확인 함)

 

 

[링크] https://mgun.tistory.com/2046

 

animation 최적화

케릭터에 붙어있는 애니메이션이 많을수록 케릭터 로딩이 느려진다. 한 스테이지에 케릭터가 10개가 나온다고 가정하고, 각 케릭터가 가져야 할 애니메이션 갯수가 영웅일 경우 20개, 적군일 경

mgun.tistory.com

 

[참조] https://forum.unity.com/threads/animationutility-seteditorcurve-makes-clip-file-size-bigger.410230/

 

AnimationUtility.SetEditorCurve makes clip file size bigger?

Hi, I jusy try to duplicate AnimationClip data from FBX file, and remove some unuse curve. Oh it's Generic Animation, not Humaroid. First, I use Ctrl...

forum.unity.com

 

반응형
Posted by blueasa
, |

[링크] https://novemberfirst.tistory.com/90

 

[Unity] Device Simulator를 Package Manager에서 찾을 수 없을 때

2020.3 버전을 다운받았다. 너무 오랜만에 켜서 이것저것 찾아보다가 Device Simulator라는 기능을 써보고 싶어 추가하려는데 난 도저히 찾을 수 없었다. 그러다가 발견했다. Edit >Project Settings > Package M

novemberfirst.tistory.com

 

[참조] https://skuld2000.tistory.com/79

 

[Unity] 유니티에 새로 추가되는 디바이스 시뮬레이터(Device Simulator) 소개

1. 유니티 디바이스 시뮬레이터 (Unity Device Simulator) 유니티 디바이스 시뮬레이터(Unity Device Simulator)는 유니티 에디터에서 개발중인 게임을 실행했을 때 Game 윈도우에서 실행되는 대신 Game XCode 나..

skuld2000.tistory.com

 

반응형
Posted by blueasa
, |

TMP에서 한글 문장 단위 자동 줄바꿈이 안될 때(영어는 잘 됨)

TMP Settings-Korean Language Options-Use Moern Line Breaking-체크

 

TMP Settings

 

[출처] 게임코디-즌성님

 

[참조]

https://gamecodi.com/6129/%EA%B2%80%EC%83%89%EC%9A%A9-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EB%A9%94%EC%8B%9C-%ED%94%84%EB%A1%9C%EC%97%90%EC%84%9C-%ED%95%9C%EA%B8%80-%EC%82%AC%EC%9A%A9%EC%8B%9C-%EB%8B%A8%EC%96%B4-%EB%8B%A8%EC%9C%84%EB%A1%9C-%EC%A4%84-%EB%B0%94%EA%BF%88-textmeshpro-word-wrapping

 

[검색용] 텍스트 메시 프로에서 한글 사용시 단어 단위로 줄 바꿈 ( TextMeshPro Word Wrapping ) - 게임

텍스트 메시 프로사용시 자동 줄 바꿈 기능을 사용할 때 글자단위로 넘어가지 않고 단어 단위로 끊어져서 넘어가게 해야 할 경우 TMP Setting 파일에서 Korean Language Options에서 Use Modem Line Breaking 을

gamecodi.com

 

반응형
Posted by blueasa
, |

꿈의집(HomeScapes)에서 위에 빨간 테두리로 보이는 것처럼 Soft Clip을 만들려고 이런저런 시도를 해보고

약간의 Trick을 포함해서 적용한 걸 간단하게 방법을 적어 놓음.

 

※ 우선은 블록들은 Sprite고, 밑에 Map이 Mesh를 사용하기 때문에 두가지 모두 Clipping 해야된다.

 

1. Unity 자체 Sprite Mask 추가(Menu-2D Object-Sprite Mask)

  [참조] https://docs.unity3d.com/kr/2020.3/Manual/class-SpriteMask.html

 

2. Sprite의 Mask Interaction을 Visible Inside Mask로 변경

3. Mesh Renderer도 Sprite Mask에 영향받도록 Shader에 아래처럼 Stencil 추가

Stencil {
		Ref 1
		Comp LEqual
    }

[참조1] https://devdata.tistory.com/166

[참조2] https://rainyrizzle.github.io/kr/AdvancedManual/AD_SpriteMask.html

------------------------------------------------------------------------------------------------

※ 여기까지 하면 Cutoff 된 상태로 Sprite, Mesh 둘 다 마스킹이 잘 된다.

   아래부터는 Soft Clip을 위해 구매한 에셋으로 시도한 Trick을 간단히 정리했다.

------------------------------------------------------------------------------------------------

4. Soft Clip을 위해 Sprite Alpha Mask 에셋 사용
   (제가 사용하기 위해 구매한 에셋이니 참조만 하시고 어떤 에셋을 사용하는지는 본인의 판단입니다.)

   [참조] https://assetstore.unity.com/packages/tools/particles-effects/sprite-alpha-mask-112704

 

5. Trick을 위해 맵의 배경 Sprite를 하나 복제해서 렌더링 순서를 아래와 같이 한다.

    (아래와 같이 배치하면 Foreground가 Map을 가려서 배경만 보이는 상태로 보인다.)

    [뒤] Background (Sprite)

    [중간] Map(Slot/Block 등) (Sprite+Mesh)

    [앞] Foreground (Sprite)

    

6. Foreground에 4.에서 산 에셋으로 Sprite Alpha Mask를 적용한다.

   (Masking 이미지는 아래 이미지를 사용하고, 9-Patch 한 후에 Sliced로 사용함)

Sprite Alpha Mask-Masking용 이미지

 

7. 6.의 Mask 크기는 1.의 Sprite Mask와 동일하게 맞춘다.

   (요약 : 앞에 배경을 하나 더 깔고 앞의 배경에 Alpha가 먹힌 구멍을 뚫어서 맵만 보이게 하려는 게 목적이다.)

 

8. 7.까지 하고나면 아래 이미지처럼 Sprite Mask의 Cutoff 영역 안쪽으로 Soft Clip처럼 보이게 된다.

   (빨간 테두리가 Sprite Mask 영역이고, 아래쪽 Sprite Mask 영역 안쪽으로 Soft Clip 처럼 적용된게 보인다)

Soft Clip Trick

 

 

 

반응형
Posted by blueasa
, |

Here are two small tricks that can help if you’re making an isometric 2D game in Unity. Ok, so not actually isometric, but that’s the term we’re used to in videogames, so we’ll go with it. These are quite basic and if you’re working on such a game you’ve probably already tackled them your own way. This is our take on it, hopefully it’s useful to someone.

Sprite Ordering

Normally in a 2D game there is no concept of depth, so if you simply place the sprites in the world, you’ll most likely have objects appearing in the wrong order than what you’d expect in an isometric game.

 

Thankfully Unity exposes Sorting Layer and Order In Layer properties for Renderers.
A quick fix is to set the value of Order in Layer to depend on the Y position of the object.

 

[ExecuteInEditMode]
[RequireComponent(typeof(Renderer))]
public class DepthSortByY : MonoBehaviour
{

    private const int IsometricRangePerYUnit = 100;

    void Update()
    {
        Renderer renderer = GetComponent();
        renderer.sortingOrder = -(int)(transform.position.y * IsometricRangePerYUnit);
    }
}

This solves the problem for the simplest case, when we assume all objects rest on the ground.

 

Let’s assume we want to have an object that is above the ground in the world, like placing a bird house on that tree. Just trying to place it in the world will treat the pivot of the object as being at ground level, with no way to both place it at a proper height and sort it correctly.

 

There are several options for this. Just to get it out of the system, the first option is to add empty space to the texture below the bird house to make sure the pivot is at ground level (in Unity, the pivot can’t be outside of the sprite). This is baaaad! This is wasting texture space, and all instances of that object will need to be at the same height in the game. There are other, less insane, options.

One is having a height property in the DepthSortByY behavior and subtract it from transform.position.y when computing the sorting order.
Another solution (which we went with) is allowing the DepthSortByY behavior to make the depth computation based on another object’s transform. This way, the objects will be considered to be at the same point in space as their target and they’ll have the same depth order, even if they’re at different Y positions in the scene. In the bird house example, the bird house uses the tree’s world position for its depth computations.
This solution works better for our game, because it allows artists to move the item freely while staying at the depth (and not have to deal with editing the “height” parameter). And mainly because all the gameplay takes place in the ground’s 2D plane anyway so all objects are guaranteed to have a root object that has the ground position. In your own game, it might be easier to just use the first option.

[ExecuteInEditMode]
[RequireComponent(typeof(Renderer))]
public class IsometricObject : MonoBehaviour
{
   private const int IsometricRangePerYUnit = 100;
   
   [Tooltip("Will use this object to compute z-order")]
    public Transform Target;
    
    [Tooltip("Use this to offset the object slightly in front or behind the Target object")]
    public int TargetOffset = 0;
    
    void Update()
    {
        if (Target == null)
            Target = transform;
        Renderer renderer = GetComponent();
        renderer.sortingOrder = -(int)(Target.position.y * IsometricRangePerYUnit) + TargetOffset;
    }
}

This is how this example is set up in Unity:

The birdhouse references the tree for its depth.

 

And this is how it behaves in practice:

 

Ground Projection

For certain visual elements and effect, we wanted them to look properly projected on the ground, but also not spend too much time on making art for them. The ‘isometric’ view of the game means that anything that is horizontally on the ground should look squashed vertically.
For simple sprites, this is quite easy. Just draw them directly with the correct perspective and place them in the game.

Things get more complicated when you need something that should be able to rotate in any direction. Like something to show the direction the character is moving in, or some visual effect sweeping the ground towards your attacking direction. Especially if these are things that are animated, drawing them manually for all possible orientations is out of the question (or so the artists claim).

Our solution is: the artists draw and animate these effects as if viewed top-down, and the programmers take care of transforming them at runtime to look as if they were projected on the ground. Without any transformation, just taken from the artists and placed in the game rotating them to match the player’s direction they look like below.

 

We need to squash them vertically. For a sprite that doesn’t rotate, just scaling on the Y dimension does the job. But for a rotating sprite this doesn’t work, and it’s even worse for animations. The first thing we tried was a custom shader that transformed the vertices in the local space to squash them vertically (naturally, we went with the most complex solution first), but this needed to break batching to work properly with all sprites and animations. Or I was just bad at writing that shader, maybe…

The final solution is absurdly simple. Just rotate the object around the X axis, and it works!
However, we also wanted to:

  • apply the rotation automatically and consistently, and not have to remember or care about setting the X component of the rotation ourselves
  • be able to set the Z component of the rotation (to make the effect rotate towards any game world direction)
  • not have to visit all ‘ground projected’ effects when changing the amount of squashing

Basically, the game should not have to know that a rotation on X axis is happening. If an object has the ProjectOnGround behavior attached, it should just draw properly without additional effort. So we do the math just before rendering, and restore the rotation to its normal value right after. This hides the rotation around the X axis from the rest of the code.

[ExecuteInEditMode]
    public class ProjectOnGround : MonoBehaviour
    {
        private Quaternion savedRotation;

        // called before rendering the object        
        void OnWillRenderObject()
        {
            savedRotation = transform.rotation;
            var eulers = transform.rotation.eulerAngles;
            transform.rotation = Quaternion.Euler(Constants.Isometric.PerspectiveAngle, eulers.y, eulers.z);
        }

        //called right after rendering the object
        void OnRenderObject()
        {
            transform.rotation = savedRotation;
        }
    }

Simple and easy. Too bad I wasted time trying to write a shader for this. The result looks good and we can simple ‘project’ any object by just adding this behavior to it.

 

 

 

[출처] https://breadcrumbsinteractive.com/two-unity-tricks-isometric-games/

 

Two Unity tricks for isometric games - Breadcrumbs

Here are two small tricks that can help if you’re making an isometric 2D game in Unity. Ok, so not actually isometric, but that’s the term we’re used to in videogames, so we’ll go with it. These are quite basic and if you’re working on such a gam

breadcrumbsinteractive.com

 

반응형
Posted by blueasa
, |