Created
May 20, 2022 11:53
-
-
Save gotmachine/c2d0f09c6eeb86a89256978a9ee7ff5e to your computer and use it in GitHub Desktop.
Extension methods for easier, faster more clear null and destroyed state checking for UnityEngine.Object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq.Expressions; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
#pragma warning disable IDE0041 // Use 'is null' check | |
namespace UnityObjectNullExtensions | |
{ | |
public static class UnityObjectNullExtensionsSafe | |
{ | |
private static Func<UnityEngine.Object, IntPtr> getNativeObjPtr; | |
static UnityObjectNullExtensionsSafe() | |
{ | |
Type unityObjectType = typeof(UnityEngine.Object); | |
FieldInfo fInfo = unityObjectType.GetField("m_CachedPtr", BindingFlags.Instance | BindingFlags.NonPublic); | |
ParameterExpression objParm = Expression.Parameter(unityObjectType, "obj"); | |
Type delegateType = typeof(Func<,>).MakeGenericType(unityObjectType, typeof(IntPtr)); | |
MemberExpression fieldExpr = Expression.Field(objParm, fInfo); | |
LambdaExpression lambda = Expression.Lambda(delegateType, fieldExpr, objParm); | |
getNativeObjPtr = (Func<UnityEngine.Object, IntPtr>)lambda.Compile(); | |
} | |
/// <summary> | |
/// True if this <paramref name="unityObject"/> instance is destroyed or not yet initialized. | |
/// </summary> | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static bool IsDestroyed(this UnityEngine.Object unityObject) | |
{ | |
return getNativeObjPtr(unityObject) == IntPtr.Zero; | |
} | |
/// <summary> | |
/// True if this <paramref name="unityObject"/> reference is <c>null</c>. | |
/// </summary> | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static bool IsNull(this UnityEngine.Object unityObject) | |
{ | |
return ReferenceEquals(unityObject, null); | |
} | |
/// <summary> | |
/// True if this <paramref name="unityObject"/> reference is <c>null</c> or if the instance is destroyed<br/> | |
/// Equivalent as testing <c><paramref name="unityObject"/> == null</c> but several times faster. | |
/// </summary> | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static bool IsNullOrDestroyed(this UnityEngine.Object unityObject) | |
{ | |
return ReferenceEquals(unityObject, null) || getNativeObjPtr(unityObject) == IntPtr.Zero; | |
} | |
/// <summary> | |
/// Return <c>null</c> when this <paramref name="unityObject"/> reference is null or destroyed, otherwise return the <paramref name="unityObject"/> instance<br/> | |
/// Allow using null conditional and null coalescing operators with UnityEngine.Object derivatives while conforming to the "a destroyed object is equal to null" Unity concept.<br/> | |
/// Example :<br/> | |
/// <c>float x = myUnityObject.DestroyedAsNull()?.myFloatField ?? 0f;</c><br/> | |
/// will evaluate to <c>0f</c> when <c>myUnityObject</c> is destroyed, instead of returning the value still available on the managed instance. | |
/// </summary> | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static T DestroyedAsNull<T>(this T unityObject) where T : UnityEngine.Object | |
{ | |
if (ReferenceEquals(unityObject, null) || getNativeObjPtr(unityObject) == IntPtr.Zero) | |
return null; | |
return unityObject; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment