Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Inserts one array into another array at the specified index.
/// </summary>
/// <typeparam name="T">Specifies the generic type of the array.</typeparam>
/// <param name="array">The destination array.</param>
/// <param name="index">The index in the destination array where insertion takes place.</param>
/// <param name="sourceArray">The source array that will be inserted.</param>
/// <returns>Returns the resized and updated destination array.</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// If 'index' is out of bounds of the destination array.
/// </exception>
public static T[] Insert<T>(this T[] array, int index, T[] sourceArray)
{
    if (array == null || sourceArray == null || sourceArray.Length == 0)
    {
        return array;
    }

    if (index < 0)
    {
        throw new ArgumentOutOfRangeException("index");
    }

    if (index > array.Length + 1)
    {
        throw new ArgumentOutOfRangeException("index");
    }

    Array.Resize(ref array, array.Length + sourceArray.Length);
    Array.Copy(array, index, array, index + sourceArray.Length, array.Length - sourceArray.Length - index);
    sourceArray.CopyTo(array, index);
    return array;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Removes a depth from the three dimensional sequence.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array whose values are to be removed.</param>
/// <param name="width">The width of the three dimensional sequence.</param>
/// <param name="height">The height of the three dimensional sequence.</param>
/// <param name="depth">The depth of to be removed from the three dimensional sequence.</param>
/// <returns>Returns the updated three dimensional sequence.</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// width or height is less then 1. Or depth is less then 0 or greater then the depth of the three dimensional sequence.
/// </exception>
public static T[] Remove3DDepth<T>(this T[] array, int width, int height, int depth)
{
    if (width < 1)
    {
        throw new ArgumentOutOfRangeException("width");
    }

    if (height < 1)
    {
        throw new ArgumentOutOfRangeException("height");
    }

    var length = width * height;
    if (depth < 0 || depth > (array.Length / length))
    {
        throw new ArgumentOutOfRangeException("depth");
    }

    return array.RemoveRange(depth * length, length);
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Gets the depth of the three dimensional sequence.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array whose value is to be retrieves.</param>
/// <param name="width">The width of the three dimensional sequence.</param>
/// <param name="height">The height of the three dimensional sequence.</param>
/// <returns>Returns the depth of the three dimensional sequence.</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// width or height is less then 1.
/// </exception>
public static int Get3DDepth<T>(this T[] array, int width, int height)
{
    if (width < 1)
    {
        throw new ArgumentOutOfRangeException("width");
    }

    if (height < 1)
    {
        throw new ArgumentOutOfRangeException("height");
    }

    return array.Length / (width * height);
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Inserts a source array into the three dimensional sequence.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array whose value is to be retrieves.</param>
/// <param name="width">The width of the three dimensional sequence.</param>
/// <param name="height">The height of the three dimensional sequence.</param>
/// <param name="destinationArray">The destination array.</param>
/// <param name="depth">The depth of the three dimensional sequence where insertion takes place.</param>
/// <param name="sourceArray">The source array to be inserted.</param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException">
/// width or height is less then 1. Or depth is less then 0.
/// </exception>
/// <exception cref="ArgumentException">'sourceArray' must not be larger then '(width * height)'.</exception>
/// <remarks>The length of the 'sourceArray' parameter cannot be larger then '(width * height)' otherwise the data it contains would overwrite any data
/// stored at a deeper depth.</remarks>
/// <returns>Returns the updated 'destinationArray'.</returns>
public static T[] Insert3D<T>(this T[] destinationArray, int width, int height, int depth, T[] sourceArray)
{
    if (width < 1)
    {
        throw new ArgumentOutOfRangeException("width");
    }

    if (height < 1)
    {
        throw new ArgumentOutOfRangeException("height");
    }

    if (depth < 0)
    {
        throw new ArgumentOutOfRangeException("depth");
    }

    if (sourceArray == null || sourceArray.Length == 0)
    {
        return destinationArray;
    }

    // ensure source array is no greater then width * height
    if (sourceArray.Length > (width * height))
    {
        throw new ArgumentException("'sourceArray' must not be larger then '(width * height)'", "sourceArray");
    }

    if (sourceArray.Length < (width * height))
    {
        Array.Resize(ref sourceArray, width * height);
    }

    destinationArray = destinationArray.Insert(depth * (width * height), sourceArray);

    // return the updated array
    return destinationArray;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Sets the depth of the three dimensional sequence.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array whose value is to be retrieves.</param>
/// <param name="width">The width of the three dimensional sequence.</param>
/// <param name="height">The height of the three dimensional sequence.</param>
/// <param name="value">The new depth of the three dimensional sequence.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// width or height is less then 1.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">'value' must be greater then 0.</exception>
public static T[] Set3DDepth<T>(this T[] array, int width, int height, int value)
{
    if (width < 1)
    {
        throw new ArgumentOutOfRangeException("width");
    }

    if (height < 1)
    {
        throw new ArgumentOutOfRangeException("height");
    }

    if (value < 1)
    {
        throw new ArgumentOutOfRangeException("value");
    }

    // resize the array preserving contents
    Array.Resize(ref array, value * (width * height));

    return array;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Gets the value in a single dimensional array that represents a three dimensional sequence.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array whose value is to be retrieves.</param>
/// <param name="width">The width of the three dimensional sequence.</param>
/// <param name="height">The height of the three dimensional sequence.</param>
/// <param name="x">The x index (0 to width - 1).</param>
/// <param name="y">The y index (0 to height - 1).</param>
/// <param name="z">The z index (0 to depth - 1).</param>
/// <returns>Returns the value stored in the array.</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// width or height is less then 1.
/// </exception>
/// <remarks>
/// <p>This method provides an alternative to working with three dimensional arrays "var value = new int[3,3,3];" by operating 
/// on a single dimensional array using a math formula to determine the index into the array.</p>
/// <p>Think of a multi-layered image. Each image layer consists of a grid of cells defined by width * height.</p>
/// <p>We can use the formula "layer * (width * height)" to get the starting index of the layer in the array. 
/// To get the index in the image we can use the formula "(y * width) + x". 
/// Combining these two formulas we can access any grid cell of any layer in the array like so "(layer * (width * height)) + ((y * width) + x)".</p>
/// <p>This method does not perform range checking and will throw index out of range exceptions if invalid arguments are specified.</p></remarks>
public static T Get3D<T>(this T[] array, int width, int height, int x, int y, int z)
{
    if (width < 1)
    {
        throw new ArgumentOutOfRangeException("width");
    }

    if (height < 1)
    {
        throw new ArgumentOutOfRangeException("height");
    }

    return array[(z * (width * height)) + ((y * width) + x)];
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Sets the value in a single dimensional array that represents a three dimensional sequence.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array whose value is to be set.</param>
/// <param name="width">The width of the three dimensional sequence.</param>
/// <param name="height">The height of the three dimensional sequence.</param>
/// <param name="x">The x index (0 to width - 1).</param>
/// <param name="y">The y index (0 to height - 1).</param>
/// <param name="z">The z index (0 to depth - 1).</param>
/// <param name="value">The value to set.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// width or height is less then 1.
/// </exception>
/// <remarks>
/// <p>This method provides an alternative to working with three dimensional arrays "var value = new int[3,3,3];" by operating
/// on a single dimensional array using a math formula to determine the index into the array.</p>
/// <p>Think of a multi-layered image. Each image layer consists of a grid of cells defined by width * height.</p>
/// <p>We can use the formula "layer * (width * height)" to get the starting index of the layer in the array.
/// To get the index in the image we can use the formula "(y * width) + x".
/// Combining these two formulas we can access any grid cell of any layer in the array like so "(layer * (width * height)) + ((y * width) + x)".</p>
/// <p>This method does not perform range checking and will throw index out of range exceptions if invalid arguments are specified.</p>
/// </remarks>
public static void Set3D<T>(this T[] array, int width, int height, int x, int y, int z, T value)
{
    if (width < 1)
    {
        throw new ArgumentOutOfRangeException("width");
    }

    if (height < 1)
    {
        throw new ArgumentOutOfRangeException("height");
    }

    array[(z * (width * height)) + ((y * width) + x)] = value;
}

Takes in an array of floats representing pixels ordered left to right top to bottom. Width & height arguments specify the image dimensions.

        /// <summary>
        /// Smoothens out the image.
        /// </summary>
        /// <param name="image">The source image.</param>
        /// <exception cref="ArgumentNullException"><paramref name="getPixel"/> or <paramref name="setPixel"/> is <see langword="null" />.</exception>
        public static void Smoothen(this float[] image, int width, int height, Func<int, int, float> getPixel, Action<int, int, float> setPixel, float smoothinValue = 9f)
        {
            if (getPixel == null)
            {
                throw new ArgumentNullException("getPixel");
            }

            if (setPixel == null)
            {
                throw new ArgumentNullException("setPixel");
            }

            for (var x = 1; x < width - 1; ++x)
            {
                for (var y = 1; y < height - 1; ++y)
                {
                    var total = 0f;
                    for (var u = -1; u <= 1; u++)
                    {
                        for (var v = -1; v <= 1; v++)
                        {
                            total += getPixel(x + u, y + v);
                        }
                    }

                    setPixel(x, y, total / smoothinValue);
                }
            }
        }

The fallowing script allows you to control fog settings on a per camera basis, allowing you to use say green fog for one camera but red fog for another camera.

Unity 5 package demo is available here CameraFog.unitypackage (46.66 kb)

Camera Fog Screen Shot

CameraFog.cs script

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CameraFog.cs" company="Codefarts">
//   Copyright (c) 2012 Codefarts
//   All rights reserved.
//   contact@codefarts.com
//   http://www.codefarts.com
// </copyright>   
// --------------------------------------------------------------------------------------------------------------------

// Per-camera fog
// This is a simple class that, when added to a GameObject with a camera, allows you to control the fog settings for that camera separately from the global ones. 
// I'd love to hear from you if you do anything cool with this or have any suggestions :)
// Original author: http://wiki.unity3d.com/index.php/User:Tenebrous
// Author website as of 2015: www.tenebrous.co.uk
// Source: http://wiki.unity3d.com/index.php/CameraFog

namespace Codefarts.GeneralTools.Scripts.Camera
{
    using UnityEngine;

    /// <summary>
    /// Modifies a camera to allows you to control the fog settings for that camera separately from the global scene fog or other cameras. 
    /// </summary>
    [RequireComponent(typeof(Camera))]
    [ExecuteInEditMode]
    public class CameraFog : MonoBehaviour
    {
        /// <summary>
        /// The enabled state weather or not fog will be visible.
        /// </summary>
        public bool Enabled;

        /// <summary>
        /// The start distance from the camera where the fog will be drawn.
        /// </summary>
        public float StartDistance;

        /// <summary>
        /// The end distance from the camera where the fog will be drawn.
        /// </summary>
        public float EndDistance;

        /// <summary>
        /// The fog mode that controls how the fog is rendered.
        /// </summary>
        public FogMode Mode;

        /// <summary>
        /// The density of the fog that is rendered.
        /// </summary>
        public float Density;

        /// <summary>
        /// The fog color.
        /// </summary>
        public Color Color;

        /// <summary>
        /// Stores the pre-render state of the start distance.
        /// </summary>
        private float _startDistance;

        /// <summary>
        /// Stores the pre-render state of the end  distance.
        /// </summary>
        private float _endDistance;

        /// <summary>
        /// Stores the pre-render state of the fog mode.
        /// </summary>
        private FogMode _mode;

        /// <summary>
        /// Stores the pre-render state of the density.
        /// </summary>
        private float _density;

        /// <summary>
        /// Stores the pre-render state of the fog color.
        /// </summary>
        private Color _color;
        
        /// <summary>
        /// Stores the pre-render state wheather or not the fog is enabled.
        /// </summary>
        private bool _enabled;

        /// <summary>
        /// Event that is fired before any camera starts rendering.
        /// </summary>
        private void OnPreRender()
        {
            this._startDistance = RenderSettings.fogStartDistance;
            this._endDistance = RenderSettings.fogEndDistance;
            this._mode = RenderSettings.fogMode;
            this._density = RenderSettings.fogDensity;
            this._color = RenderSettings.fogColor;
            this._enabled = RenderSettings.fog;

            RenderSettings.fog = this.Enabled;
            RenderSettings.fogStartDistance = this.StartDistance;
            RenderSettings.fogEndDistance = this.EndDistance;
            RenderSettings.fogMode = this.Mode;
            RenderSettings.fogDensity = this.Density;
            RenderSettings.fogColor = this.Color;
        }

        /// <summary>
        /// Event that is fired after any camera finishes rendering.
        /// </summary>
        private void OnPostRender()
        {
            RenderSettings.fog = this._enabled;
            RenderSettings.fogStartDistance = this._startDistance;
            RenderSettings.fogEndDistance = this._endDistance;
            RenderSettings.fogMode = this._mode;
            RenderSettings.fogDensity = this._density;
            RenderSettings.fogColor = this._color;
        }
    }
}

With the introduction to Unity 5 there comes some api changes. Specifically this foot note was interesting “[2] in Unity5 we also cache the transform component on the c# side, so there should no longer be a performance reason to cache the transform component yourself.

I decided to test it out by writing a few performance test scripts and comparing performance numbers. Below is a screen shot of my results along with the scripts used.

As you can see caching a reference to the transform component in the Start method then using that reference is still faster then calling “this.transform” directly albeit only slightly by about 10-20 ticks. And calling “this.GetComponent<Transform>()” is almost twice as slow.

Unity5TransformPerformance

The code for the PerformanceTesting class is availible here.

TransformCachedGetComponentPerformance script

    using UnityEngine;

    public class TransformCachedGetComponentPerformance : MonoBehaviour
    {
        private Transform reference;

        /// <summary>
        /// Awake is called when the script instance is being loaded.
        /// </summary>
        public void Awake()
        {
#if PERFORMANCE
            var perf = PerformanceTesting.PerformanceTesting<string>.Instance;
            perf.Create("UnityTesting/TransformCachedGetComponentPerformance/Update");
#endif
        }

        /// <summary>
        /// Start is called just before any of the Update methods is called the first time.
        /// </summary>
        public void Start()
        {
            this.reference = this.GetComponent<Transform>();
        }

        /// <summary>
        /// Update is called every frame, if the MonoBehaviour is enabled.
        /// </summary>
        public void Update()
        {
#if PERFORMANCE
            var perf = PerformanceTesting.PerformanceTesting<string>.Instance;
            perf.Start("UnityTesting/TransformCachedGetComponentPerformance/Update");      
#endif

            var rnd = new System.Random();
            this.reference.localPosition = new Vector3(rnd.Next(-3, 3), rnd.Next(-3, 3), rnd.Next(-3, 3));

#if PERFORMANCE
            perf.Stop("UnityTesting/TransformCachedGetComponentPerformance/Update");
#endif
        }
    }

TransformGetComponentPerformance script

    using UnityEngine;

    public class TransformGetComponentPerformance : MonoBehaviour
    {
        /// <summary>
        /// Awake is called when the script instance is being loaded.
        /// </summary>
        public void Awake()
        {
#if PERFORMANCE
            var perf = PerformanceTesting.PerformanceTesting<string>.Instance;
            perf.Create("UnityTesting/TransformGetComponentPerformance/Update");
#endif
        }
        
        /// <summary>
        /// Update is called every frame, if the MonoBehaviour is enabled.
        /// </summary>
        public void Update()
        {
#if PERFORMANCE
            var perf = PerformanceTesting.PerformanceTesting<string>.Instance;
            perf.Start("UnityTesting/TransformGetComponentPerformance/Update");
#endif

            var rnd = new System.Random();
            this.GetComponent<Transform>().localPosition = new Vector3(rnd.Next(-3, 3), rnd.Next(-3, 3), rnd.Next(-3, 3));

#if PERFORMANCE
            perf.Stop("UnityTesting/TransformGetComponentPerformance/Update");
#endif
        }
    }

TransformFieldPerformance script

    using UnityEngine;

    public class TransformFieldPerformance : MonoBehaviour
    {
        /// <summary>
        /// Awake is called when the script instance is being loaded.
        /// </summary>
        public void Awake()
        {
#if PERFORMANCE
            var perf = PerformanceTesting.PerformanceTesting<string>.Instance;
            perf.Create("UnityTesting/TransformFieldPerformance/Update");
#endif
        }

        /// <summary>
        /// Update is called every frame, if the MonoBehaviour is enabled.
        /// </summary>
        public void Update()
        {
#if PERFORMANCE
            var perf = PerformanceTesting.PerformanceTesting<string>.Instance;
            perf.Start("UnityTesting/TransformFieldPerformance/Update");
#endif

            var rnd = new System.Random();
            this.transform.localPosition = new Vector3(rnd.Next(-3, 3), rnd.Next(-3, 3), rnd.Next(-3, 3));

#if PERFORMANCE
            perf.Stop("UnityTesting/TransformFieldPerformance/Update");
#endif
        }
    }

Created by: X

Just another personal website in this crazy online world

Name of author Dean Lunz (aka Created by: X)
Computer programming nerd, and tech geek.
About Me -- Resume