Skip to content

Instantly share code, notes, and snippets.

@ayamflow
Last active October 18, 2020 17:10
Show Gist options
  • Save ayamflow/e5b024d27f8745d38b7090228eb9fbe7 to your computer and use it in GitHub Desktop.
Save ayamflow/e5b024d27f8745d38b7090228eb9fbe7 to your computer and use it in GitHub Desktop.
Unity gotchas

I'm learning unity by redoing old projects or scenes of videogames (coming from a webGL background), and documenting things I get stuck on, as well as findings.

OpenUPM (and other UPM)

Basically npm for Unity. Just need to add dependencies and scopedRegistries to Packages/manifest.json, Unity will detect the change and install the package.

Importing upm packages in a shader (ShaderLab)

Add this line in CGPROGRAM, after #include "UnityCG.cginc":

#include "Packages/jp.keijiro.noiseshader/Shader/SimplexNoise2D.hlsl"

Accessing ShaderGraph properties (from Blackboard) through scripts

Just make sure the "Reference" name is what you need it to be, when unfolding the property in the ShaderGraph blackboard panel. By default, it will get a generated name like Texture2D_F36GI.

OnGUI allows to draw debug stuff like RenderTexture on top of the screen

For instance GUI.DrawTexture(new Rect(0, 0, 256, 256), _texture, ScaleMode.ScaleToFit, false, 1);

Single transform properties (like transform.position.z or rotation.y) cannot be set, they need to be overwritten

This will work:

transform.position.Set(....);
transform.position = new Vector4(....);
transform.position += new Vector4(....);

GameObject.transform.position returns a copy, not the actual reference!

Thus position.Set(...) will not work, you need to assign a new Vector, i.e: object.transform.position = new Vector4(...);

Drawing into RenderTarget is done via Graphics.Blit with a drawing material

Graphics.Blit(_rt, temp);
Graphics.Blit(temp, _rt, _drawMaterial);

The material can for instance render the content of the previous RenderTexture and add something on top of it. Ideal for drawing or fading a texture (equivalent of autoClear none).

Temp RenderTarget can be created (and released) at any time

RenderTexture temp = RenderTexture.GetTemporary(_splatMap.width, _splatMap.height, 0, RenderTextureFormat.ARGBFloat);
// ...
// then:
RenderTexture.ReleaseTemporary(temp); // Important!

Start is only called only for enabled scripts

Awake will run regardless (and always before Start)

Use collider.Raycast(ray, out hit, distance) instead of Physics.Raycast to target a single object

You can also use layers but this is more cumbersome, unless you want to raycast a few different objects. Here's a raycast example:

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (collider.Raycast(ray, out hit, Mathf.Infinity)) {
// do something with hit.point, hit.textureCoordinates, etc

ShaderGraph shortcuts

Somehow they are now shown anywhere? This is on mac:

  • Delete selected node or connection: Cmd+Delete
  • Option+Drag: Drag around
  • Scroll: Zoom

You can hide the preview & the blackboard by clicking the buttons in the top right - saves a lot of space

You can copy the code of a ShaderGraph node, or the whole graph

Right Click > Show Generated Code

Useful if you never remember how to write annoying functions like world to local ;)

ShaderGraph connections have colors indicating their type

If it refuses to connect 2 nodes (by instead offering to create a new node), check your types

Shaders will hot reload in play mode!!

So you can keep tweaking without having to restart. Really awesome feature.

Unity scale is x100 Blender's scale

So you will need to scale & apply your meshes. /!\ Keep in mind most of blender's primitives are 2 units large by default (cube, plane go from -1 to 1).

Import & Animate a rigged model

Right Click > Create Animator Controller, then drag & drop the geometry. It should automatically find the animation. To make it loop, make sure in your 3D software the timeline doesn't have any blanks. In Unity, select the Geometry, and choose the "Animation" panel from the Inspector and make sure "Loop time" is checked.

Access material (and other nested components) of a Prefab

Can be somewhat expensive so do this in Start() rather than in a loop!

GameObject mesh = gameObject.transform.Find("Object_Name").gameObject;
Material material = mesh.GetComponent<Renderer>().material;

Debug.DrawLine (and other Debug.Draw methods) don't clear and will create vertices over time

Prefer Handles.DrawLine instead for 2D shapes, (with using UnityEditor), or Gizmos.DrawWireSphere (and others) for 3D shapes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment