Skip to content

wallstop/unity-helpers

Repository files navigation

A Grab-Bag

Various Unity Helpers. Includes many deterministic, seedable random number generators.

CI/CD Status

Npm Publish

Compatibility

Platform Compatible
Unity 2021 Likely, but untested
Unity 2022
Unity 2023
Unity 6
URP
HDRP

Installation

To Install as Unity Package

  1. Open Unity Package Manager
  2. (Optional) Enable Pre-release packages to get the latest, cutting-edge builds
  3. Open the Advanced Package Settings
  4. Add an entry for a new "Scoped Registry"
    • Name: NPM
    • URL: https://registry.npmjs.org
    • Scope(s): com.wallstop-studios.unity-helpers
  5. Resolve the latest com.wallstop-studios.unity-helpers

From Source

Grab a copy of this repo (either git clone or download a zip of the source) and copy the contents to your project's Assets folder.

From Releases

Check out the latest Releases to grab the Unity Package and import to your project.

Package Contents

  • Random Number Generators
  • Spatial Trees
  • Protobuf, Binary, and JSON formatting
  • A resizable CyclicBuffer
  • Simple single-threaded thread pool
  • A LayeredImage for use with Unity's UI Toolkit
  • Geometry Helpers
  • Child/Parent/Sibling Attributes to automatically get components
  • ReadOnly attribute to disable editing of serialized properties in the inspector
  • An extensive collection of helpers
  • Simple math functions including a generic Range
  • Common buffers to reduce allocations
  • A RuntimeSingleton implementation for automatic creation/accessing of singletons
  • String helpers, like converting to PascalCase, like Unity does for variable names in the inspector
  • A randomizable PerlinNoise implementation
  • And more!

Auto Get(Parent/Sibling/Child)Component

Are you tired of constantly writing GetComponent() all over the place? Waste time no more!

public sealed class MyCoolScript : MonoBehaviour
{
    [SiblingComponent] // If it doesn't exist, will log an error
    private SpriteRenderer _spriteRenderer;

    [SiblingComponent(optional = true)] // Ok if it doesn't exist, no errors logged
    private BoxCollider2D _boxCollider;

    [ParentComponent] // Similar to GetComponentInParent<AIController>(includeInactive: true)
    private AIController _parentAIController;

    // Only include components in parents, Unity by default includes sibling components in the GetComponentsInParent call
    [ParentComponent(onlyAncestors = true)] 
    private Transform [] _allParentTransforms; // Works with arrays!

    [ParentComponent(includeInactive = false)] // Don't include inactive components
    private List<PolygonCollider2> _parentColliders; // Works with lists!

    [ChildComponent(onlyDescendents = true)] // Similar to GetComponentInChildren<EdgeCollider2D>(includeInactive: true)
    private EdgeCollider2D _childEdgeCollider;

    private void Awake()
    {
        /*
            Make sure this is called somewhere, usually in Awake, OnEnable, or Start - wherever this is called,
             values will be injected into the annotated fields and errors will be logged
        */
        this.AssignRelationalComponents();
    }
}

Random Number Generators

This package implements several high quality, seedable, and serializable random number generators. The best one (currently) is the PCG Random. This has been hidden behind the PRNG.Instance class, which is thread-safe. As the package evolves, the exact implementation of this may change.

All of these implement a custom IRandom interface with a significantly richer suite of methods than the standard .Net and Unity randoms offer.

To use:

IRandom random = PRNG.Instance;

random.NextFloat(); // Something between 0.0f and 1.0f
random.NextDouble(); // Something between 0.0d and 1.0d
random.Next(); // Something between 0 and int.MaxValue
random.NextUint(); // Something between 0 and uint.MaxValue

int [] values = {1, 2, 3};
random.NextOf(values); // 1, 2, or 3
random.NextOf(Enumerable.Range(0, 3)); // 1, 2, or 3
HashSet<int> setValues = new() {1, 2, 3};
random.NextOf(setValues); // 1, 2, or 3

random.NextGuid(); // A valid UUIDv4
random.NextGaussian(); // A value sampled from a gaussian curve around mean=0, stdDev=1 (configurable via parameters)
random.NextEnum<T>(); // A randomly selected enum of type T

int width = 100;
int height = 100;
random.NextNoiseMap(width, height); // A configurable noise map generated using random octave offsets

Implemented Random Number Generators

  • PCG
  • DotNet (uses the currently implemented .Net Random)
  • RomoDuo
  • SplitMix64
  • Squirrel
  • System (uses a port of the Windows .Net Random)
  • Unity (uses Unity's random under the hood)
  • Wy
  • XorShift
  • XorShiro

Performance (Number of Operations / Second)

Random NextBool Next NextUInt NextFloat NextDouble NextUint - Range NextInt - Range
PcgRandom 34,260,478 34,303,866 35,148,246 24,818,438 30,034,632 22,436,474 20,801,797
SystemRandom 28,698,806 30,040,782 20,435,092 24,079,399 27,284,147 20,735,769 19,861,780
SquirrelRandom 33,285,784 33,439,909 34,611,893 23,885,731 28,958,725 21,520,279 20,311,372
XorShiftRandom 34,695,989 35,147,320 35,997,718 25,248,238 31,582,991 22,679,928 21,255,319
DotNetRandom 18,097,489 18,191,042 18,783,063 14,061,444 15,730,439 13,284,050 12,596,913
WyRandom 28,490,852 29,086,052 29,724,907 20,252,065 24,542,201 18,474,790 17,404,641
SplitMix64 34,301,843 34,343,404 35,512,284 24,289,416 30,586,231 22,470,330 20,850,965
RomuDuo 32,969,889 33,413,212 34,339,227 23,755,059 29,483,136 21,671,641 20,253,479
XorShiroRandom 31,529,025 31,717,709 32,536,277 22,421,715 27,619,417 20,843,993 19,270,063
UnityRandom 24,925,268 24,830,594 26,429,283 17,864,528 21,206,384 16,376,626 15,528,972
LinearCongruentialGenerator 35,013,818 35,025,182 35,843,533 25,093,401 31,553,487 22,579,798 21,211,175

Spatial Trees

There are three implemented 2D immutable spatial trees that can store generic objects, as long as there is some resolution function that can convert them into Vector2 spatial positions.

  • QuadTree (easiest to use)
  • KDTree
  • RTree

Spatial trees, after construction, allow for O(log(n)) spatial query time instead of O(n). They are extremely useful if you need repeated spatial queries, or if you have relatively static spatial data.

Usage

GameObject [] spatialStorage = { myCoolGameObject };
QuadTree<GameObject> quadTree = new(spatialStorage, go => go.transform.position);

// Might return your object, might not
GameObject [] inBounds = quadTree.GetElementsInBounds(new Bounds(0, 0, 100, 100));

// Uses a "good-enough" nearest-neighbor approximately for cheap neighbors
List<GameObject> nearestNeighbors = new();
quadTree.GetApproximateNearestNeighbors(myCoolGameObject.transform.position, 1, nearestNeighbors);
Assert.AreEqual(1, nearestNeighbors.Count);
Assert.AreEqual(myCoolGameObject, nearestNeighbors[0]);

Note

All spatial trees expect the positional data to be immutable. It is very important that the positions do not change. If they do, you will need to reconstruct the tree.

About

Various Unity Helpers

Resources

License

MIT and 2 other licenses found

Licenses found

MIT
LICENSE
MIT
LICENSE.md
Unknown
LICENSE.meta

Stars

Watchers

Forks

Packages

No packages published

Languages