【Unite 2017 Tokyo】Unity最適化講座 ~スペシャリストが教えるメモリとCPU使用率の負担最小化テクニック~

1.1K Views

May 08, 17

スライド概要

講演者:イアン・ダンドア(Unity Technologies)

こんな人におすすめ
・メモリ使用を削減したいプログラマー、開発者全般

受講者が得られる知見
・メモリ、GPU、CPUのリソースの無駄使いを発見し、削減するテクニック

講演動画:https://youtu.be/jHpkoJAMDGE

profile-image

リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
2.

Ian Dundore Lead Developer Relations Engineer, Unity

3.

Optimizing Unity Saving CPU & Memory, because you can.

4.

What’ll we cover today? • • • • Primary focus will be CPU optimization. Transform component Animator Physics • Finish with some tips for saving memory.

5.

Always, always profile!

6.

Transforms! Not as simple as they look.

7.

Transforms? • Every GameObject has one. • When they change, they send out messages. • C++: “OnTransformChanged” • When reparented, they send out MORE messages! • C#: “OnBeforeTransformParentChanged” • C#: “OnTransformParentChanged” • Used by many internal Unity Components. • Physics, Renderers, UnityUI…

8.

OnTransformChanged? • Sent every time a Transform changes. • Three ways to cause these messages: • Changing position, rotation or scale in C# • Moved by Animators • Moved by Physics • 1 change = 1 message!

9.

Why is this expensive? • Message is sent to all Components on Transform & all Children • Yes, ALL. • Physics components will update the Physics scene. • Renderers will recalculate their bounding boxes. • Particle systems will update their bounding boxes.

10.

void Update() { transform.position += new Vector3(1f, 1f, 1f); transform.rotation += Quaternion.Euler(45f, 45f, 45f); }

11.

X void Update() { transform.position += new Vector3(1f, 1f, 1f); transform.rotation += Quaternion.Euler(45f, 45f, 45f); }

12.

void Update() { transform.SetPositionAndRotation( transform.position + new Vector3(1f, 1f, 1f), transform.rotation + Quaternion.Euler(45f, 45f, 45f) ); }

13.

Collect your transform updates! • Many systems moving a Transform around? • Add up all the changes, apply them once. • If changing both position & rotation, use SetPositionAndRotation • New API, added in 5.6 • Eliminates duplicate messages

14.

What system has lots of moving Transforms?

16.

100 Unity-chans! • Over 15,000 Transforms! • How will it perform?

17.

Performance Test (Unity 5.6) times in ms iPad Air 2 Macbook Pro, 2017 Unoptimized 33.35 6.06 Optimized 26.96 3.37 Timings are only from Animators

18.

“Optimized”?

19.

What does it do? • Reorders animation data for better multithreading. • Eliminates extra transforms in the model’s Transform hierarchy. • Need some, but not all? Add them to the “Extra Transforms” list! • Allows Mesh Skinning to be multithreaded.

20.

“Optimized”?

21.

Physics!

22.

What affects the cost of Physics? • Two major operations that cost time: • Physics simulation • Updating Rigidbodies • Physics queries • Raycast, SphereCast, etc.

23.

Scene complexity is important! • All physics costs are affected by the complexity and density of a scene. • The type of Colliders used has a big impact on cost. • Box colliders & sphere colliders are cheapest • Mesh colliders are very expensive • Simple setup: Create some number of colliders, cast rays.

24.

Cost of 1000 Raycasts times in ms 10 Colliders 100 Colliders 1000 Colliders Sphere 0.27 0.48 1.53 Box 0.34 0.42 1.67 Mesh 0.37 0.53 2.27 Objects created in a 25-meter sphere

25.

Density is important! times in ms 10 meters 25 meters 50 meters 100 meters Sphere 2.13 1.28 1.08 0.78 1000 Raycasts through 1000 Spheres

26.

Why is complexity important? • Physics queries occur in three steps. • 1: Gather list of potential collisions, based on world-space. • 2: Cull list of potential collisions, based on layers. • 3: Test each potential collision to find actual collisions.

27.

Why is complexity important? • Physics queries occur in three steps. • 1: Gather list of potential collisions, based on world-space. • Done by PhysX (“broad phase”) • 2: Cull list of potential collisions, based on layers. • Done by Unity • 3: Test each potential collision to find actual collisions. • Done by PhysX (“midphase” & “narrow phase”) • Most expensive step

28.

Reduce number of potential collisions! • PhysX has an internal world-space partitioning system. • Divides world into smaller regions, which track contents. • Longer rays may require querying more regions in the world. • Benefit of limiting ray length depends on scene density! • Use maxDistance parameter of Raycast! • Limits the world-space involved in a query. • Physics.Raycast(myRay, 10f);

29.

Control maxDistance! times in ms 10 meters 25 meters 50 meters 100 meters 1 meter 1.85 1.02 0.49 0.50 10 meters 2.10 1.19 0.91 0.53 100 meters 2.11 1.36 1.07 0.77 Infinite 2.13 1.28 1.08 0.78 1000 Raycasts through 1000 Spheres

30.

Edit the physics layers! • Consider making special layers for special types of entities in your game • Help the system cull unwanted results.

31.

Trade accuracy for performance • Reduce the physics time-step. • Running at 30FPS? Don’t run physics at 50FPS! • Reduces accuracy of collisions, so test changes carefully. • Most games can accept timesteps of 0.04 or 0.08

32.

[RequireComponent(typeof(Rigidbody))] class MyMonoBehaviour : MonoBehaviour { void Update() { transform.SetPositionAndRotation(…); } }

33.

X [RequireComponent(typeof(Rigidbody))] class MyMonoBehaviour : MonoBehaviour { void Update() { transform.SetPositionAndRotation(…); } }

34.
[beta]
[RequireComponent(typeof(Rigidbody))]
class MyMonoBehaviour : MonoBehaviour
{
Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
rb.MovePosition(…);
rb.MoveRotation(…);
}
}

35.

Common errors: Rigidbody movement • Do not move GameObjects with Rigidbodies via their Transform • Use Rigidbody.MovePosition, Rigidbody.MoveRotation 500 objects MovePosition & MoveRotation Transform SetPositionAndRotation FixedUpdate 0.45 0.90

36.

Memory time!

37.

IL2CPP Platforms: Memory Profiler • Available on Bitbucket • https://bitbucket.org/Unity-Technologies/memoryprofiler • Requires IL2CPP to get accurate information. • Shows all UnityEngine.Objects and C# objects in memory. • Includes native allocations, such as the shadowmap

38.

Examining a memory snapshot

39.

Examining a memory snapshot

40.

Examining a memory snapshot ?!

41.

Examining a memory snapshot

42.

This is a shadowmap… do we need one?

43.

Look at the HideFlags

44.

HideAndDontSave? • Value in the HideFlags enum. • Includes 3 values: • HideInHierarchy • DontSave • DontUnloadUnusedAsset • Mistake: Setting in-game assets to use this HideFlag. • Assets loaded with HideAndDontSave flag will never be unloaded!

45.

Examining a memory snapshot

46.

Examining a memory snapshot

47.

Examining a memory snapshot

48.

Check your assets! • Common for artists to add assets in very high resolutions. • Does Unity-chan’s hair really need three 1024x1024 textures? • Reduce size? Achieve the same effect some other way?

49.

Beware of Asset Duplication • Common problem when placing Assets into Asset Bundles • Assets in Resources & an Asset Bundle will be included in both • Will be seen as separate Assets in Unity • Separate copies will be loaded into memory • Also happens when Asset Dependencies are not declared properly

50.

Asset Dependencies Material A Shader A Material B Texture (shared) Shader B

51.

Asset Dependencies Material A Shader A Material B Texture (shared) Shader B

52.

Asset Dependencies Material A Shader A Material B Texture (shared) Shader B

53.

Asset Dependencies Material A Shader A Material B Texture (shared) Texture (shared) Shader B

54.

Asset Dependencies Material A Shader A Material B Texture (shared) Shader B

55.

Runtime texture creation • Creating textures procedurally, or downloading via the web? • Make sure your textures are non-readable! • Read-write textures use twice as much memory! • Use UnityWebRequest — defaults to non-readable textures • Use WWW.textureNonReadable instead of WWW.texture

56.

Marking textures non-readable • Pass nonReadable as true when calling Texture2D.LoadImage • Texture2D.LoadImage(“/path/to/image”, true); • Call Texture2D.Apply when updates are done • Texture2D.Apply(true, true); • Updates mipmaps & marks as non-readable • Texture2D.Apply(false, true); • Does not update mipmaps, but does mark as non-readable

57.

Thank you!