Quick Unity Tips
Image Click Area
When creating image buttons, it’s sometimes desirable to make the clickable area bigger than the image. One common approach to achieve this is adding an additional GameObject + Image component, setting the desired clickable area size, and making it completely transparent. But we actually don’t need those extra objects. Instead, utilize the Raycast Padding property of the Image component. The editor conveniently shows the bounds via Gizmo (the white square surrounding the image).

C# 9 init keyword
C# 9 introduced the init keyword which can be applied to properties and indexers. This means the value can only be set during object initialization (unlike set). Unity supports C# 9 since 2021.2, but you’ll notice the init keyword doesn’t work right out of the box.

The compiler complains about missing something called IsExternalInit. If you search online, you’ll find a small snippet of code that you can add to your project to fill in the missing piece.

Of course, MonoBehaviours can’t benefit from this feature, but still a lot of use cases. Immutable properties ftw!

##
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class CallerArgumentExpressionAttribute : Attribute
{
public CallerArgumentExpressionAttribute(string parameterName) => ParameterName = parameterName;
public string ParameterName { get; }
}
asdf
public static void NotNull([NotNull] object? obj, [CallerArgumentExpression("obj")] string paramName = "")
{
if (obj == null)
{
throw new ArgumentNullException(paramName);
}
}
Visual Studio Tracepoints
You know those fleeting logs you scatter around when trying to debug an issue? A couple downsides are
- compilation time every time you need to add or modify a log
- have to remember to remove them when finished (unless they’re useful enough to keep around)

Well, instead of putting those logs in the code, try moving them to a special kind of breakpoint known as a Tracepoint. Its primary use case is printing text to the Visual Studio console, but it also allows us to execute methods by putting the invocation inside a pair of curly braces. We can utilize this by calling Unity’s Debug.Log:
{Debug.Log("value: " + transform.name)}

Unity Collection Pools API
Unity 2021.1 introduced a convenient pooling API which includes the following classes
- CollectionPool<T0,T1>
- DictionaryPool<T0,T1>
- GenericPool
- HashSetPool
- LinkedPool
- ListPool
- ObjectPool
- UnsafeGenericPool
Just bringing it up because I used it recently. Here’s an example of normal usage:
private void OnEnable()
{
_myClass = GenericPool<MyClass>.Get();
}
private int OnDisable()
{
GenericPool<MyClass>.Release(_myClass);
}
But if you only need it with a single method, you can use the overload that returns the item back to the pool automatically after disposal.
public int DoSomeWork()
{
using var _ = ListPool<Vector2>.Get(out List<Vector3> vertices);
// Do some work
...
return result;
}
Custom Script Templates
You may already know about the script templates folder in the installation directory, but did you also know that “ScriptTemplates” is a special folder name in a Unity project?

You can include custom templates per project.

Without templates, one of the first things I do for many new scripts is remove the default Start and Update methods, along with the comments. In the attached screenshots I use an interface template and a “classes sealed by default” template.

Comments