Skip to content

Instantly share code, notes, and snippets.

View tomkail's full-sized avatar

Tom Kail tomkail

View GitHub Profile
@tomkail
tomkail / ExtendedScriptableObjectDrawer.cs
Last active November 4, 2025 18:11
Displays the fields of a ScriptableObject in the inspector
// Developed by Tom Kail at Inkle
// Released under the MIT Licence as held at https://opensource.org/licenses/MIT
// Must be placed within a folder named "Editor"
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
@tomkail
tomkail / BeginDragImmediately.cs
Created October 23, 2024 13:33
Immediately begins a drag as soon as a mouse/finger down event occurs on a Unity UI object.
using UnityEngine;
using UnityEngine.EventSystems;
public class BeginDragImmediately : MonoBehavior, IInitializePotentialDragHandler, IBeginDragHandler, IDragHandler {
public void OnInitializePotentialDrag(PointerEventData eventData) {
eventData.pointerDrag = gameObject;
eventData.dragging = true;
eventData.useDragThreshold = false;
ExecuteEvents.ExecuteHierarchy(transform.gameObject, eventData, ExecuteEvents.beginDragHandler);
}
@tomkail
tomkail / RiveUIRenderer.cs
Last active September 27, 2024 02:28
Renders a Rive asset to Unity UI
// RiveUIRenderer.cs created by Tom Kail. This file is licensed under the MIT License.
// Renders a Rive asset to Unity UI using a RenderTexture in a similar manner to RawImage.
// Supports pointer events and masking.
using Rive;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering;
using UnityEngine.UI;
@tomkail
tomkail / InputFieldActivationRestorer.cs
Last active August 27, 2024 15:19
Workaround for Unity's inability to keep an input field selected when you click a button
// Released under MIT License
using System.Reflection;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
// Workaround for Unity's inability to keep an input field selected when you click a button.
// Call ReactivateInputField to immediately activate and restore caret position/selection.
@tomkail
tomkail / DefaultAssetEditor.cs
Last active August 21, 2024 10:41
Draws inspectors for any file type Unity doesn't draw by default
/// Used to draw custom inspectors for unrecognised file types, which Unity imports as "DefaultAsset"
/// To do this, create a new editor class extending DefaultAssetInspector
/// Return true in the IsValid function if the file extension of the file matches the type you'd like to draw.
/// The DefaultAssetEditor class will then hold a reference to the new instance of your editor class and call the appropriate methods for drawing.
/// An example can be found at the bottom of the file.
using UnityEngine;
using UnityEditor;
using System;
using System.IO;
@tomkail
tomkail / Better TextMeshPro GetRenderedValues
Last active June 14, 2024 10:48
Better GetRenderedValues for TextMeshPro that doesn't return NaN/other invalid values and allows you to test with custom text
// Applying float.MaxValue to a rectTransform can cause crashes (not sure why) so we just use a very big number instead.
const float veryLargeNumber = 10000000;
// Gets the tightest bounds for the text by updating the text and using GetRenderedValues
// Note this uses sizeDelta for sizing so won't work when using anchors.
// This is wayyyy more reliable than the actual GetRenderedValues because it won't return stupid values, as GetRenderedValues is prone to doing.
public static Vector2 GetRenderedValues (this TMP_Text textComponent, string text, float maxWidth = veryLargeNumber, float maxHeight = veryLargeNumber, bool onlyVisibleCharacters = true) {
if(string.IsNullOrEmpty(text)) return Vector2.zero;
// Setting RT size to Infinity can lead to weird results, so we use a very large number instead.
if(maxWidth > veryLargeNumber) maxWidth = veryLargeNumber;
@tomkail
tomkail / AbsoluteRectTransformController.cs
Last active April 15, 2024 14:57
Sets the rect of the attached RectTransform to a viewport space rect, regardless of the pivot, anchors, or (optionally) scale of the RectTransform.
using UnityEngine;
// Sets the rect of the attached RectTransform to a viewport space rect, regardless of the pivot, anchors, or (optionally) scale of the RectTransform.
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
public class AbsoluteRectTransformController : MonoBehaviour {
public Rect viewportRect = new Rect(0,0,1,1);
public bool ignoreScale;
static Vector3[] corners = new Vector3[4];
DrivenRectTransformTracker drivenRectTransformTracker;
@tomkail
tomkail / BetterPropertyField.cs
Last active April 15, 2024 14:07
Unity editor helper that draws a serialized property (including children) fully, even if it's an instance of a custom serializable class.
using UnityEngine;
using UnityEditor;
using System.Collections;
public static class BetterPropertyField {
/// <summary>
/// Draws a serialized property (including children) fully, even if it's an instance of a custom serializable class.
/// Supersedes EditorGUILayout.PropertyField(serializedProperty, true);
/// </summary>
/// <param name="_serializedProperty">Serialized property.</param>
@tomkail
tomkail / InkParserUtility.cs
Last active January 21, 2024 14:11
Utility for parsing lines of ink into instructions that can be executed on the game side.
// Usage example:
// using System.Collections.Generic;
// using System.Text.RegularExpressions;
// public enum AudioCategory {
// Undefined,
// Music,
// Narration,
// }
@tomkail
tomkail / PresetImportPerFolder.cs
Created September 25, 2023 14:45
Automatically applies Preset files to assets in the same directory. Also adds labels present on the Preset file to those assets.
using System.IO;
using UnityEditor;
using UnityEditor.Presets;
using System.Linq;
// This script automatically applies Presets to assets when they are imported into a folder containing a Preset.
// It also adds any labels on the Preset file to the asset.
public class PresetImportPerFolder : AssetPostprocessor {
void OnPreprocessAsset() {
// Make sure we are applying presets the first time an asset is imported.