Unity: Difference between revisions

 
(15 intermediate revisions by the same user not shown)
Line 1: Line 1:
__FORCETOC__
Unity is a game development framework and game engine. It has a shallow learning curve and is very capable, supporting most popular platforms and features including AR and VR platforms.


 
==Shaders==  
 
Unity shaders are written in [[HLSL]].
== Shaders ==  
Unity shaders are written in HLSL.
Unity supports the standard vertex, geometry, fragment shader pipeline.<br>
Unity supports the standard vertex, geometry, fragment shader pipeline.<br>
They also have their own variation of fragment shaders called surface shaders which automatically handle lighting.<br>
They also have their own variation of fragment shaders called surface shaders which automatically handle lighting.<br>
Line 10: Line 8:
Results from compute shaders can be used on the graphical shaders without being copied back to the CPU.<br>
Results from compute shaders can be used on the graphical shaders without being copied back to the CPU.<br>


 
===Compute Shaders===
=== Compute Shaders ===
To use a compute shader, add a <code>ComputeShader</code> reference to your C# script.
To use a compute shader, add a <code>ComputeShader</code> reference to your C# script.
To copy data to and from the GPU, use a <code>ComputeBuffer</code>.
To copy data to and from the GPU, use a <code>ComputeBuffer</code>.
Line 22: Line 19:
-->
-->


== Optimization ==
==Optimization==
=== Loading Files ===
===Loading Files===
All loading of streaming assets should be done in a background thread. See [https://wiki.davidl.me/view/C_Sharp#Multithreading C# Multithreading] for more details on multithreading.<br>
All loading of streaming assets should be done in a background thread. See [https://wiki.davidl.me/view/C_Sharp#Multithreading C# Multithreading] for more details on multithreading.<br>
I've found that Unity's job system doesn't perform as well as C#'s ThreadPool when stressed with thousands of small tasks so I recommend using C# APIs over Unity APIs whenever possible.<br>
I've found that Unity's job system doesn't perform as well as C#'s ThreadPool when stressed with thousands of small tasks so I recommend using C# APIs over Unity APIs whenever possible.<br>
[https://wiki.davidl.me/view/C_Sharp#Multithreading Ciela Spike's Thread Ninja] may be used to run coroutines in the background when you only need a single, but complex, task.<br>
[https://assetstore.unity.com/packages/tools/thread-ninja-multithread-coroutine-15717 Ciela Spike's Thread Ninja] may be used to run coroutines in the background when you only need a single, but complex, task.<br>
Much of Unity's API such as <code>new Mesh()</code> and <code>new Texture2D()</code> cannot be called from background threads. I suggest caching textures as <code>byte[]</code> or <code>Color32[]</code> which can then be loaded with [https://docs.unity3d.com/ScriptReference/Texture2D.LoadRawTextureData.html <code>Texture2D.LoadRawImageData()</code>]. Similarly, you can cache a Mesh by caching a struct of vertices, triangles, normals, and tangents.
Much of Unity's API for GPU assets such as <code>new Mesh()</code> and <code>new Texture2D()</code> cannot be called from background threads.
I suggest caching textures in system memory as <code>byte[]</code> or <code>Color32[]</code> which can then be loaded with [https://docs.unity3d.com/ScriptReference/Texture2D.LoadRawTextureData.html <code>Texture2D.LoadRawImageData()</code>]. Similarly, you can hold a Mesh in system memory by using a struct of vertices, triangles, normals, and tangents.
 
===Instancing===
If you need multiple instances of the same object, make sure that the material is instanced so that all objects only consume one draw call.<br>
See [https://docs.unity3d.com/Manual/GPUInstancing.html Unity: GPUInstancing].<br>
Do not attach scripts to thousands of objects. Instead use one script to control all instanced objects.<br>
 
====Merging Meshes====
If you need thousands of simple objects, one way is to use merge all of the meshes. 
For simple objects, you can create a mesh with one vertex per object and expand them in the geometry shader such that they're all drawn in a single draw call. Otherwise, merging them on the CPU is more efficient. 
Both methods will ensure all objects are drawn in a single draw call.
Be aware of the limitations of using a single draw call though; transparency can become tricky.
 
After merging a mesh, you can use a compute shader to animate and move the objects instead of using Unity scripts. 
The compute shader edits a single compute buffer which can be read by your vertex or geometry shader without passing data back to the CPU.
 
==Resources==
* [https://docs.unity3d.com/Manual/index.html Unity User Manual]
* [https://www.udemy.com/course/the-ultimate-guide-to-game-development-with-unity/ Basic Game Dev Course (Udemy, ~$12)]