Skip to content

Instantly share code, notes, and snippets.

@RiskyWilhelm
Created November 29, 2024 13:35
Show Gist options
  • Save RiskyWilhelm/b79eebea75689c5f268b48d20c55c4b3 to your computer and use it in GitHub Desktop.
Save RiskyWilhelm/b79eebea75689c5f268b48d20c55c4b3 to your computer and use it in GitHub Desktop.
Unity Extensions (C# >= 9) - My "Unity Utils" are required
using UnityEngine;
public static class BoxCollider2DExtensions
{
public static Vector2 GetRandomPoint(this BoxCollider2D a)
{
Vector2 extents = a.bounds.extents;
Vector2 localPoint = new (
Random.Range(-extents.x, extents.x),
Random.Range(-extents.y, extents.y)
);
localPoint += a.offset;
return a.transform.TransformPoint(localPoint);
}
}
using UnityEngine;
public static class BoxColliderExtensions
{
public static Vector3 GetRandomPoint(this BoxCollider a)
{
Vector3 extents = a.bounds.extents;
Vector3 localPoint = new (
Random.Range(-extents.x, extents.x),
Random.Range(-extents.y, extents.y),
Random.Range(-extents.z, extents.z)
);
localPoint += a.center;
return a.transform.TransformPoint(localPoint);
}
}
using UnityEngine;
public static class CircleCollider2DExtensions
{
public static Vector2 GetRandomPoint(this CircleCollider2D a)
{
float radAngle = Random.Range(0, Mathf.PI * 2);
float distance = a.radius * Mathf.Sqrt(Random.Range(0f, 1f)); // sqrt for even distribution
Vector2 localPoint = new (distance * Mathf.Cos(radAngle), distance * Mathf.Sin(radAngle));
localPoint += a.offset;
return a.transform.TransformPoint(localPoint);
}
}
using UnityEngine;
public static class Collider2DExtensions
{
public static Vector2 GetRandomPoint(this Collider2D a)
{
switch (a)
{
case BoxCollider2D:
return (a as BoxCollider2D).GetRandomPoint();
case CircleCollider2D:
return (a as CircleCollider2D).GetRandomPoint();
}
Debug.LogErrorFormat("Type {0} is un-supported. BoxCollider2D and CircleCollider2D is supported only", a.GetType());
return default;
}
}
using UnityEngine;
public static class ColliderExtensions
{
public static Vector3 GetRandomPoint(this Collider a)
{
switch (a)
{
case BoxCollider:
return (a as BoxCollider).GetRandomPoint();
case SphereCollider:
return (a as SphereCollider).GetRandomPoint();
}
Debug.LogErrorFormat("Type {0} is un-supported. BoxCollider and SphereCollider is supported only", a.GetType());
return default;
}
}
using System;
public static class DateTimeExtensions
{
// TODO: Count in the Year, Month and Day
/// <remarks> Assumes the time 12:00 equals North(Y+ when facing to Z+) in cardinal direction. Means, degree of zero will equal to 18:00 in a circle </remarks>
public static float ToAngleDegree(this DateTime a, sbyte offsetHour = 0)
{
float offsetHourDegree = (offsetHour + DateTimeUtils.DefaultOffsetHour) * DateTimeUtils.ExactHourDegree;
float verticallyMirroredHourDegree = 360f - (a.Hour * DateTimeUtils.ExactHourDegree); // Angle is not inverted. Mirrored the angle in a circle vertically. That way, time will grow if rotation getting negative
float hourDegree = verticallyMirroredHourDegree + offsetHourDegree;
float minuteDegree = a.Minute * DateTimeUtils.ExactMinutePoint;
float secondDegree = a.Second * DateTimeUtils.ExactSecondPoint;
return (hourDegree - minuteDegree - secondDegree) % 360f;
}
public static float ToProgress01(this DateTime a)
{
return 1f - (a.ToAngleDegree((sbyte)-DateTimeUtils.DefaultOffsetHour) / 360f);
}
}
using System;
public static class EnumExtensions
{
// TODO: Support string
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, EnumType b)
where EnumType : Enum
{
// Check for the supported enum types
return a.GetTypeCode() switch
{
// byte
TypeCode.Byte => HasAny(a, (byte)(object)b),
// sbyte
TypeCode.SByte => HasAny(a, (sbyte)(object)b),
// short
TypeCode.Int16 => HasAny(a, (short)(object)b),
// ushort
TypeCode.UInt16 => HasAny(a, (ushort)(object)b),
// int
TypeCode.Int32 => HasAny(a, (int)(object)b),
// uint
TypeCode.UInt32 => HasAny(a, (uint)(object)b),
// long
TypeCode.Int64 => HasAny(a, (long)(object)b),
// ulong
TypeCode.UInt64 => HasAny(a, (ulong)(object)b),
_ => throw new NotSupportedException("Unknown Error. This shouldn't be happened!"),
};
}
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, byte b)
where EnumType : Enum
{
EnumUtils.ValidateFlagEnum<EnumType>();
EnumUtils.ValidateUnderlyingType<EnumType, byte>();
return ((byte)(object)a & b) != 0;
}
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, sbyte b)
where EnumType : Enum
{
EnumUtils.ValidateFlagEnum<EnumType>();
EnumUtils.ValidateUnderlyingType<EnumType, sbyte>();
return ((sbyte)(object)a & b) != 0;
}
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, short b)
where EnumType : Enum
{
EnumUtils.ValidateFlagEnum<EnumType>();
EnumUtils.ValidateUnderlyingType<EnumType, short>();
return ((short)(object)a & b) != 0;
}
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, ushort b)
where EnumType : Enum
{
EnumUtils.ValidateFlagEnum<EnumType>();
EnumUtils.ValidateUnderlyingType<EnumType, ushort>();
return ((ushort)(object)a & b) != 0;
}
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, int b)
where EnumType : Enum
{
EnumUtils.ValidateFlagEnum<EnumType>();
EnumUtils.ValidateUnderlyingType<EnumType, int>();
return ((int)(object)a & b) != 0;
}
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, uint b)
where EnumType : Enum
{
EnumUtils.ValidateFlagEnum<EnumType>();
EnumUtils.ValidateUnderlyingType<EnumType, uint>();
return ((uint)(object)a & b) != 0;
}
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, long b)
where EnumType : Enum
{
EnumUtils.ValidateFlagEnum<EnumType>();
EnumUtils.ValidateUnderlyingType<EnumType, long>();
return ((long)(object)a & b) != 0;
}
/// <summary> Checks if enum 'a' contains any of the value(s) from 'b' </summary>
/// <remarks> Requires flag enum </remarks>
public static bool HasAny<EnumType>(this EnumType a, ulong b)
where EnumType : Enum
{
EnumUtils.ValidateFlagEnum<EnumType>();
EnumUtils.ValidateUnderlyingType<EnumType, ulong>();
return ((ulong)(object)a & b) != 0;
}
}
using System.Collections;
public static class IEnumeratorExtensions
{
/// <summary> Allows you to iterate through an IEnumerator </summary>
public static T GetEnumerator<T>(this T enumerator)
where T : IEnumerator
{
return enumerator;
}
}
using System;
public static class RandomExtensions
{
public static float NextFloat(this Random random, float minInclusiveValue, float maxExclusiveValue)
=> (float)random.NextDouble(minInclusiveValue, maxExclusiveValue);
public static double NextDouble(this Random random, double minInclusiveValue, double maxExclusiveValue)
{
return random.NextDouble() * (maxExclusiveValue - minInclusiveValue) + minInclusiveValue;
}
}
using System.Collections.Generic;
public static class SetExtensions
{
public static ReadOnlySet<T> AsReadOnly<T>(this ISet<T> set)
{
return new ReadOnlySet<T>(set);
}
}
using UnityEngine;
public static class SphereColliderExtensions
{
public static Vector3 GetRandomPoint(this SphereCollider a)
{
Vector3 localPoint = Random.insideUnitSphere * a.radius;
localPoint += a.center;
return a.transform.TransformPoint(localPoint);
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
public static class TransformExtensions
{
public static bool TryGetNearestTransform<TransformEnumeratorType>(this Transform relativeTo, TransformEnumeratorType transformEnumerator, out Transform nearestTransform, Predicate<Transform> predicateNearest = null)
where TransformEnumeratorType : IEnumerator<Transform>
{
nearestTransform = default;
var isFoundNearest = false;
float nearestHorizontalDistance = float.MaxValue;
float iteratedDistance;
// Check sqr distances and select nearest
foreach (var iteratedTransform in transformEnumerator)
{
iteratedDistance = (iteratedTransform.position - relativeTo.position).sqrMagnitude;
if ((iteratedDistance < nearestHorizontalDistance) && (predicateNearest == null || predicateNearest.Invoke(iteratedTransform)))
{
nearestTransform = iteratedTransform;
nearestHorizontalDistance = iteratedDistance;
isFoundNearest = true;
}
}
return isFoundNearest;
}
}
using System.Collections.Generic;
using System;
using UnityEngine;
public static class VectorExtensions
{
/// <returns> Angle in radians in PI (-180~180 Degrees) </returns>
public static float ToRadianAngle(this Vector2 a)
=> MathF.Atan2(a.y, a.x);
/// <returns> Angle in degrees in PI (-180~180) </returns>
public static float ToDegreeAngle(this Vector2 a)
=> MathF.Atan2(a.y, a.x) * Mathf.Rad2Deg;
/// <returns> Angle in radians in 2PI (0~360 Degrees) </returns>
public static float ToRadianAngle_360(this Vector2 a)
{
var radian = MathF.Atan2(a.y, a.x);
// Same as adding 360 degree to a angle in degrees
if (radian < 0f)
radian += (Mathf.PI * 2);
return radian;
}
/// <returns> Angle in degrees in 2PI (0~360) </returns>
public static float ToDegreeAngle_360(this Vector2 a)
=> ToRadianAngle_360(a) * Mathf.Rad2Deg;
/// <returns> Non-normalized rotated original vector </returns>
public static Vector2 RotateByRadianAngle(this Vector2 a, float rotateAngleInRadians)
{
return new Vector2(
a.x * MathF.Cos(rotateAngleInRadians) - a.y * MathF.Sin(rotateAngleInRadians),
a.x * MathF.Sin(rotateAngleInRadians) + a.y * MathF.Cos(rotateAngleInRadians)
);
}
/// <returns> Non-normalized rotated original vector </returns>
public static Vector2 RotateByDegreeAngle(this Vector2 a, float rotateAngleInDegrees)
=> RotateByRadianAngle(a, rotateAngleInDegrees * Mathf.Deg2Rad);
public static Vector3 RotateByDegreeAngle(this Vector3 a, float rotateAngleInDegrees, Vector3 axisToRotateAround)
=> Quaternion.AngleAxis(rotateAngleInDegrees, axisToRotateAround) * a;
/// <returns> Non-normalized rotated original vector </returns>
public static Vector3 RotateByRadianAngle(this Vector3 a, float rotateAngleInRadians, Vector3 axisToRotateAround)
=> RotateByDegreeAngle(a, rotateAngleInRadians * Mathf.Rad2Deg, axisToRotateAround);
public static bool TryGetNearestVector<VectorEnumeratorType>(this Vector4 relativeTo, VectorEnumeratorType vectorCollection, out Vector4 nearestVector, Predicate<Vector4> predicateNearest = null)
where VectorEnumeratorType : IEnumerator<Vector4>
{
nearestVector = default;
var isFoundNearest = false;
float nearestHorizontalDistance = float.MaxValue;
float iteratedDistance;
// Check sqr distances and select nearest
foreach (var iteratedVector in vectorCollection)
{
iteratedDistance = (iteratedVector - relativeTo).sqrMagnitude;
if ((iteratedDistance < nearestHorizontalDistance) && (predicateNearest == null || predicateNearest.Invoke(iteratedVector)))
{
nearestVector = iteratedVector;
nearestHorizontalDistance = iteratedDistance;
isFoundNearest = true;
}
}
return isFoundNearest;
}
public static bool TryGetNearestVector<VectorEnumeratorType>(this Vector2 relativeTo, VectorEnumeratorType vectorCollection, out Vector2 nearestVector, Predicate<Vector2> predicateNearest = null)
where VectorEnumeratorType : IEnumerator<Vector2>
{
nearestVector = default;
var isFoundNearest = false;
float nearestHorizontalDistance = float.MaxValue;
float iteratedDistance;
// Check sqr distances and select nearest
foreach (var iteratedVector in vectorCollection)
{
iteratedDistance = (iteratedVector - relativeTo).sqrMagnitude;
if ((iteratedDistance < nearestHorizontalDistance) && (predicateNearest == null || predicateNearest.Invoke(iteratedVector)))
{
nearestVector = iteratedVector;
nearestHorizontalDistance = iteratedDistance;
isFoundNearest = true;
}
}
return isFoundNearest;
}
public static bool TryGetNearestVector<VectorEnumeratorType>(this Vector3 relativeTo, VectorEnumeratorType vectorCollection, out Vector3 nearestVector, Predicate<Vector3> predicateNearest = null)
where VectorEnumeratorType : IEnumerator<Vector3>
{
nearestVector = default;
var isFoundNearest = false;
float nearestHorizontalDistance = float.MaxValue;
float iteratedDistance;
// Check sqr distances and select nearest
foreach (var iteratedVector in vectorCollection)
{
iteratedDistance = (iteratedVector - relativeTo).sqrMagnitude;
if ((iteratedDistance < nearestHorizontalDistance) && (predicateNearest == null || predicateNearest.Invoke(iteratedVector)))
{
nearestVector = iteratedVector;
nearestHorizontalDistance = iteratedDistance;
isFoundNearest = true;
}
}
return isFoundNearest;
}
public static Vector3 GetDifferenceTo(this Vector3 a, Vector3 b)
{
return (b - a);
}
public static bool IsNearTo(this Vector3 a, Vector3 b, float exceedDistance)
{
return (b - a).sqrMagnitude <= (exceedDistance * exceedDistance);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment