Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Some useful extension method for Unity3D
A collection of useful C# extension methods for the Unity engine.
using System;
using System.Collections;
using System.Collections.Generic;
public static class ShuffleListExtensions
{
/// <summary>
/// Shuffle the list in place using the Fisher-Yates method.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
public static void Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
/// <summary>
/// Return a random item from the list.
/// Sampling with replacement.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static T RandomItem<T>(this IList<T> list)
{
if (list.Count == 0) throw new System.IndexOutOfRangeException("Cannot select a random item from an empty list");
return list[UnityEngine.Random.Range(0, list.Count)];
}
/// <summary>
/// Removes a random item from the list, returning that item.
/// Sampling without replacement.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static T RemoveRandom<T>(this IList<T> list)
{
if (list.Count == 0) throw new System.IndexOutOfRangeException("Cannot remove a random item from an empty list");
int index = UnityEngine.Random.Range(0, list.Count);
T item = list[index];
list.RemoveAt(index);
return item;
}
}
using System;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Text;
public static class StringExtensionMethods
{
public static string Truncate(this string value, int maxLength)
{
if (string.IsNullOrEmpty(value)) return value;
return value.Length <= maxLength ? value : value.Substring(0, maxLength);
}
// Named format strings from object attributes. Eg:
// string blaStr = aPerson.ToString("My name is {FirstName} {LastName}.")
// From: http://www.hanselman.com/blog/CommentView.aspx?guid=fde45b51-9d12-46fd-b877-da6172fe1791
public static string ToString(this object anObject, string aFormat)
{
return ToString(anObject, aFormat, null);
}
public static string ToString(this object anObject, string aFormat, IFormatProvider formatProvider)
{
StringBuilder sb = new StringBuilder();
Type type = anObject.GetType();
Regex reg = new Regex(@"({)([^}]+)(})", RegexOptions.IgnoreCase);
MatchCollection mc = reg.Matches(aFormat);
int startIndex = 0;
foreach (Match m in mc)
{
Group g = m.Groups[2]; //it's second in the match between { and }
int length = g.Index - startIndex - 1;
sb.Append(aFormat.Substring(startIndex, length));
string toGet = string.Empty;
string toFormat = string.Empty;
int formatIndex = g.Value.IndexOf(":"); //formatting would be to the right of a :
if (formatIndex == -1) //no formatting, no worries
{
toGet = g.Value;
}
else //pickup the formatting
{
toGet = g.Value.Substring(0, formatIndex);
toFormat = g.Value.Substring(formatIndex + 1);
}
//first try properties
PropertyInfo retrievedProperty = type.GetProperty(toGet);
Type retrievedType = null;
object retrievedObject = null;
if (retrievedProperty != null)
{
retrievedType = retrievedProperty.PropertyType;
retrievedObject = retrievedProperty.GetValue(anObject, null);
}
else //try fields
{
FieldInfo retrievedField = type.GetField(toGet);
if (retrievedField != null)
{
retrievedType = retrievedField.FieldType;
retrievedObject = retrievedField.GetValue(anObject);
}
}
if (retrievedType != null) //Cool, we found something
{
string result = string.Empty;
if (toFormat == string.Empty) //no format info
{
result = retrievedType.InvokeMember("ToString",
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase
, null, retrievedObject, null) as string;
}
else //format info
{
result = retrievedType.InvokeMember("ToString",
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase
, null, retrievedObject, new object[] { toFormat, formatProvider }) as string;
}
sb.Append(result);
}
else //didn't find a property with that name, so be gracious and put it back
{
sb.Append("{");
sb.Append(g.Value);
sb.Append("}");
}
startIndex = g.Index + g.Length + 1;
}
if (startIndex < aFormat.Length) //include the rest (end) of the string
{
sb.Append(aFormat.Substring(startIndex));
}
return sb.ToString();
}
}
using UnityEngine;
public static class ExtensionMethods
{
public static float LinearRemap(this float value,
float valueRangeMin, float valueRangeMax,
float newRangeMin, float newRangeMax)
{
return (value - valueRangeMin) / (valueRangeMax - valueRangeMin) * (newRangeMax - newRangeMin) + newRangeMin;
}
public static int WithRandomSign(this int value, float negativeProbability = 0.5f)
{
return Random.value < negativeProbability ? -value : value;
}
}
using UnityEngine;
public static class VectorExtensionMethods {
public static Vector2 xy(this Vector3 v) {
return new Vector2(v.x, v.y);
}
public static Vector3 WithX(this Vector3 v, float x) {
return new Vector3(x, v.y, v.z);
}
public static Vector3 WithY(this Vector3 v, float y) {
return new Vector3(v.x, y, v.z);
}
public static Vector3 WithZ(this Vector3 v, float z) {
return new Vector3(v.x, v.y, z);
}
public static Vector2 WithX(this Vector2 v, float x) {
return new Vector2(x, v.y);
}
public static Vector2 WithY(this Vector2 v, float y) {
return new Vector2(v.x, y);
}
public static Vector3 WithZ(this Vector2 v, float z) {
return new Vector3(v.x, v.y, z);
}
// axisDirection - unit vector in direction of an axis (eg, defines a line that passes through zero)
// point - the point to find nearest on line for
public static Vector3 NearestPointOnAxis(this Vector3 axisDirection, Vector3 point, bool isNormalized = false)
{
if (!isNormalized) axisDirection.Normalize();
var d = Vector3.Dot(point, axisDirection);
return axisDirection * d;
}
// lineDirection - unit vector in direction of line
// pointOnLine - a point on the line (allowing us to define an actual line in space)
// point - the point to find nearest on line for
public static Vector3 NearestPointOnLine(
this Vector3 lineDirection, Vector3 point, Vector3 pointOnLine, bool isNormalized = false)
{
if (!isNormalized) lineDirection.Normalize();
var d = Vector3.Dot(point - pointOnLine, lineDirection);
return pointOnLine + (lineDirection * d);
}
}
@mollsju

This comment has been minimized.

Copy link

mollsju commented Oct 11, 2017

Theres a typo in vector extensions:
public static Vector3 WithZ(this Vector2 v, float z) { return new Vector3(v.x, v.y, z); }
Should be
public static Vector2 WithZ

and it should return a Vector2, as the Vector3.WithZ is already defined.

@david-jares

This comment has been minimized.

Copy link

david-jares commented Feb 5, 2019

@mollsju I Dont think its a typo, as that is the only function that makes sense. vector2 has no Z. So when you have a vector 2 and need to convert it to vector3, you can pass the vector2 and a zvalue as an argument.

@david-jares

This comment has been minimized.

Copy link

david-jares commented Feb 5, 2019

I personally also added
public static Vector3 WithAddX(this Vector3 v, float x)
{
return new Vector3(v.x + x, v.y, v.z);
}

public static Vector3 WithAddY(this Vector3 v, float y)
{
return new Vector3(v.x, v.y + y, v.z);
}

public static Vector3 WithAddZ(this Vector3 v, float z)
{
return new Vector3(v.x, v.y, v.z + z);
}
public static Vector2 WithAddX(this Vector2 v, float x)
{
return new Vector2(v.x + x, v.y);
}
public static Vector2 WithAddY(this Vector2 v, float y)
{
return new Vector2(v.x, v.y + y);
}

so that I can just add to the existing value

@dracolytch

This comment has been minimized.

Copy link

dracolytch commented Apr 10, 2019

Some of these are really helpful. I'm also working on a library of extension methods. Would it be OK for me to integrate some of these with my project? It's MIT license, so any of these you give me permission to integrate would become MIT license.

https://github.com/dracolytch/DracoSoftwareExtensionsForUnity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.