A personal collection of Unity Engine tools, extensions, and helpers.
This package is available on the OpenUPM registry. Add the package via the openupm-cli:
openupm add com.mygamedevtools.extensions
Installing from Git (requires Git installed and added to the PATH)
- Open
Edit/Project Settings/Package Manager
. - Click +.
- Select
Add package from git URL...
. - Paste
com.mygamedevtools.extensions
into the name. - Click
Add
.
This package is focused on 3 main areas: Extensions, Tooling, and Attributes. The purpose of these tools, is to improve the overall Unity Editor experience with simple, reliable, and maintainable solutions.
We have a total of 3 attributes available:
The [ReadOnly]
attribute prevents changing the field's value in the Unity Inspector
public class MyClass : MonoBehaviour
{
[SerializeField, ReadOnly]
float myValue = 5.5f;
}
The [LabeledArray]
attribute allows you to specify names for array elements, instead of the default Element #n
. You can
either use a string array or an Enum to provide the names. If the array element count passes the provided names count, the following
element names will fall to the default naming
public class MyClass : MonoBehaviour
{
[SerializeField, LabeledArray(new string[]{ "First", "Second", "Third" })]
float[] myValueArray;
}
The [SceneField]
attribute allows you to drag scene assets to fields in the inspector. You can only use this attribute on int fields
since it will store the scene's build index. It does not have any relation with the scene itself, so if you change the build settings it will
not update its value and will reference a different scene. You can add the scene to the build settings via the inspector after dragging the
scene to the field if it hasn't been yet
public class MyClass : MonoBehaviour
{
[SerializeField, SceneField]
int mySceneIndex;
}
We have two tools available:
Simply press Ctrl + G to group the selected game objects. It creates a parent game object in the center of the selected objects.
You can use the ScriptingDefineSymbolsHelper
to easily add or remove scripting define symbols to your project. For example:
using MyGameDevTools.Extensions;
using UnityEditor;
public static class CheatsEnabler
{
const string _cheatsDefine = "ENABLE_CHEATS";
[MenuItem("Tools/Add Cheats")]
public static void AddCheats()
{
ScriptingDefineSymbolsHelper.AddScriptingDefineSymbol(_cheatsDefine);
}
[MenuItem("Tools/Add Cheats", validate = true)]
public static bool AddCheatsValidate()
{
return !ScriptingDefineSymbolsHelper.HasScriptingDefineSymbol(_cheatsDefine);
}
[MenuItem("Tools/Remove Cheats")]
public static void RemoveCheats()
{
ScriptingDefineSymbolsHelper.RemoveScriptingDefineSymbol(_cheatsDefine);
}
[MenuItem("Tools/Remove Cheats", validate = true)]
public static bool RemoveCheatsValidate()
{
return ScriptingDefineSymbolsHelper.HasScriptingDefineSymbol(_cheatsDefine);
}
}
We have a total of 3 extensions available:
Allows debugging collections and jagged arrays.
public class MyClass : MonoBehaviour
{
// Can also be a List or any IEnumerable type
[SerializeField]
int[] myValueArray;
int[][] myJaggedArray = new int[5][];
void Start()
{
for (int i = 0; i < myJaggedArray.Length; i++)
myJaggedArray[i] = new int[5];
DebugExtensions.LogJaggedArray(myJaggedArray);
DebugExtensions.LogCollection(myValueArray);
}
}
A collection of some helpful game object operations
Sets all game objects in the given transform's hierarchy to the provided layer
public class MyClass : MonoBehaviour
{
void Start()
{
transform.SetChildrenLayerRecursively(LayerMask.NameToLayer("MyLayer"));
}
}
Destroys the given component type instances in a UnityEngine.GameObject
or its children.
public class MyClass : MonoBehaviour
{
[SerializeField]
GameObject[] myObjectsToDestroy;
void Start()
{
gameObject.DestroyAllComponentsOfType<BoxCollider>();
gameObject.DestroyAllChildrenComponentsOfType<SphereCollider>();
}
}
Gets the root game objects of a scene, or optionally all scenes.
public class MyClass : MonoBehaviour
{
void Start()
{
List<GameObject> allRootObjects = GameObjectExtensions.GetRootGameObjects(true);
}
}
Checks if a LayerMask
contains the given layer index. Useful for physics validations.
public class MyClass : MonoBehaviour
{
[SerializeField]
LayerMask _mask;
void Start()
{
Debug.Log(_mask.HasLayer(gameObject.layer));
}
}
Delays an Action after a given amount of time. You can delay in seconds, frames, or physics (fixed) frames.
public class MyClass : MonoBehaviour
{
void Start()
{
Debug.Log("Hello there");
// In seconds
DelayCall(6, MyAction);
// In frames
DelayCallInFrames(6, MyAction);
// In physics frammes
DelayCallInPhysicsFrames(6, MyAction);
}
void MyAction()
{
Debug.Log("General Kenobi")
}
}
Destroy a given array of UnityEngine.Object
, which could be GameObjects, Components, MonoBehaviours, and any type that inherits from UnityEngine.Object
. Keep in mind that the object is destroyed between the end of the current frame and the beginning of the next one.
public class MyClass : MonoBehaviour
{
[SerializeField]
Object[] _objectsToDestroy;
void Start()
{
ObjectExtensions.DestroyObjects(_objectsToDestroy);
}
}
This is meant to find interface
implementations. It works like a FindObjectOfType
, but for interface
. You can also use the TryFindImplementationOfType
to return a bool. Keep in mind that the interface
implementation will also need to inherit from MonoBehaviour
to be found since it will be searched within GameObject's components.
public interface IActionable {}
public class MyAction : MonoBehaviour, IActionable {}
public class MyClass : MonoBehaviour
{
void Start()
{
// Common usage
IActionable implementation = this.FindImplementationOfType<IActionable>();
// Explicit usage
IActionable implementation = ObjectExtensions.FindImplementationOfType<IActionable>();
// Try usage
bool implementationExists = ObjectExtensions.TryFindImplementationOfType<IActionable>(out IActionable implementation);
// For multiple implementations
List<IActionable> implementations = ObjectExtensions.FindImplementationsOfType<IActionable>();
}
}
Don't hesitate to create issues for suggestions and bugs. Have fun!