A collection of modifications/additions (scripts/prefabs) which enhance [for me] the overall flow of using the Unity Engine.
A tool that is robust but minimal. Modularly modifiable with minimal cross-dependencies. Avoiding frankensteinian architecture and preferring a simpler, familiar interface and codebase.
There are some key features pan other game engines that seem to be lacking in Unity and this is a package to resolve some of those problems while adding some new ones to their already very solid game engine.
You can download the latest .unitypackage
through Releases and double-click to import it.
or
You can import it through Unity’s package manager using the url:
https://github.com/sudotman/BetterUnity.git
Installation instruction:
Click here to see general collaboration information and the star history.
Table of Contents:
Allows you to call/execute functions in your script from your inspector.
You can expose normally to the inspector in Unity and it works great. Sometimes, you would want to have a button set to call a function of your liking from the inspector and people tend to use workarounds (such as, setting a boolean and then calling a function after checking the boolean from Update) or creating your custom inspector and having a button there.
This is a much more easier and simpler addition to your existing scripts and can be called using a simple attribute.
Usage:
[CallInEditor]
void HelloGitFunction(){
....
You may want finer control over your button that appears in the inspector in the terms of the size, the label or the place it appears at. In that case, you can use the alternative attribute field described below.
Usage:
[InspectorButton("funcToBeCalled")]
public char random;
The above snippet will create a button named Random and will call funcToBeCalled
function from inside your script when pressed. The public character can be any variable type, I prefer char
for saving miniscule memory.
You can also specify the size of the button (by default, it will try to scale your button size to your text size):
[InspectorButton("funcToBeCalled",100)]
public char myButton;
You can also specify a custom text for your button (by default, it takes button name from the variable name below it [the aforementioned variable will still be required in the script regardless of if we use this]):
[InspectorButton("funcToBeCalled",100,"Custom Name Here!")]
public char myButton;
For dynamic size:
[InspectorButton("funcToBeCalled","Custom Name Here!")]
public char myButton;
*The extra step to create a character and invoke the function through specifying the name is because of trying to workaround OnGUI/OnInspectorGUI; this is the only workaround as of now due to the way Unity is built - the CallInEditor attribute relies on reflection to find the proper function, too.
Various inspector fields which can be used to output text to the Inspector without having to write a custom editor GUI for simple text labels or to have more pleasing looking headers.
Usage:
[Optional]
public int additionalPoints;
// Standard Variable
public float mainPoints;
[Label("This is a normal label")]
[BetterHeader("Main Header")]
[BetterHeader("Main Header aligned to the left", true)]
[BetterHeader("Sub Heading aligned to the left",true,true)]
[SerializeField, Layer]
int layer;
[NullCheck]
public Transform myField;
For a starting point getting familiar with the fields, check the test script out: TestScript.cs
These are attachable objects/components to GameObjects as opposed to the inspector additions which get injected into the inspector directly.
A lot of the times when developing, you have similar children which you want to be named incrementally with your desired prefix. Instead of manually going in and doing it, this module allows me to do more it quickly and effeciently, by attaching a script to the parent.
Further, when duplicating objects and creating new ones, Unity appends (x) [x being the current duplicate] and sometimes you would want the objects to be named differently. All new objects will also be renamed appropriately, automatically.
Attach ‘BetteRename’ to any game object.
Allows you to always have uniform scaling on any GameObject. Works similar to the BetterTransform component but given incase you dont wish to override default transform and just want the uniform scaling on one object.
Attach ‘BetterScale’ to any game object.
A collection of extension functions which can be called in other scripts for ease-of-use.
Scale a value from a previous range to a new range (remap it linearly).
myFloatValue.ScaleRange(0,100,10,30);
Destroy all children of a parent.
transform.DestroyChildren();
When calling the function from the editor:
transform.DestroyChildrenEditor();
Subtract one float value from x, y, z components of a Vector3.
myVector3.MinusFloatVector3(2.5f);
Add one float value to x, y, z components of a Vector3.
myVector3.PlusFloatVector3(4.2f);
Look at but rotate only across the Y axis (say, for an enemy that needs to turn to you at all times).
transform.LookAtY(player.position);
Returns distance between two vectors but its grounded. (ignoring their Y-position during calculation)
player.position.DistanceFromGround(objective.position);
Get a random item from a list
currentItem = myList.RandomItem();
Performs a Ease-In Interpolation on our specified Vector3.
myVector3.EaseInLerp(myFinalVector3,currentTime);
Performs a Ease-Out Interpolation on our specified Vector3.
myVector3.EaseOutLerp(myFinalVector3,currentTime);
Returns a smooth stepping interpolation between two floats.
HelperFunctions.SmoothStep(currentTime,startFloat,EndFloat);
Allows you to pass a Hexadecimal color string and use in the native Unity’s RGB color system.
Color myColor;
myColor = myColor.HexColor("#60c47e");
If an incorrect hex string is passed and/or it can’t be parsed, a warning is logged while a default black color is returned.
There are plenty more functions which are not mentioned here because of their usages being quite insigniicant. Look through HelperFunctions.cs for all the remaining functions, they are aptly documented.
Gives you different serializers which allows you to easily pass common Unity data structures into files and vice versa.
SerializedVector3 serializedVector3;
SerializedQuaternion serializedQuaternion;
Quick code to get started with conversion of Vector3 into Serialized JSON data:
List<SerializedVector3> anchorPositions = new List<SerializedVector3>();
List<SerializedQuaternion> anchorRotations = new List<SerializedQuaternion>();
foreach (var gameObjects in arrayOfGameObjects)
{
Vector3 currentPositionData = anchorGameObject.transform.position;
Quaternion currentRotData = anchorGameObject.transform.rotation;
anchorPositions.Add(Vector3Extensions.FromVector3(currentPositionData));
anchorRotations.Add(QuaternionExtensions.FromQuaternion(currentRotData));
}
SerializedVector3[] actualPositions = anchorPositions.ToArray();
SerializedQuaternion[] actualRotations = anchorRotations.ToArray();
string jsonPositions = JsonConvert.SerializeObject(actualPositions);
string jsonRotations = JsonConvert.SerializeObject(actualRotations);
byte[] dataPos = Encoding.ASCII.GetBytes(jsonPositions);
byte[] dataRot = Encoding.ASCII.GetBytes(jsonRotations);
UnityEngine.Windows.File.WriteAllBytes(localJSONPath, dataPos);
UnityEngine.Windows.File.WriteAllBytes(localJSONPath, dataRot);
Serializables.cs has more information about every function/class and extensions. Deserialization/Serialization is also available in the same script.
A simple one-liner to allow a better raycast function. Usually, when Raycasting, we also like to Debug and see the visual output of our raycast being hit. This encapsulates it all into one single line.
The hit is passed by reference and is updated automatically.
RaycastHit hit;
hit.BetterRaycast(startPosition, direction, raycastDistance);
Is able to parse a Vector3 from a string.
string s = "(-2.24,3.92,0.00)";
Vector3 test = s.StringToVector3();
Tools to do various functions, called by menus.
Works similar to BetterRename except its for remaining them only once. [We can attach the script, do the rename, and then remove it if we would want but this has a much cleaner UX]. Further, it allows you to rename any random [from anywhere to anywhere] selection at any place in the heirarchy.
A one click button that set-ups directories in our project folder in a standardish way.
Another wizard to select all the objects with the specified:
Often times we end up with frankenstienian structure in the heierarchy of our project. Imagine a dashboard inside of a car being setup using a canvas with various TextMeshPro’s being nested inside more Canvas Elements until there are atleast 20-30 elements inside other sub components. The normal search function (including the aforementioned BetterUnity’s select all with) ends up showing objects in the entire heirarchy during a search even if we search by type.
‘Select all with generic’ allows you to select any object type that exists below the currently selected object - allowing faster modifications of components at the same time.
Made from taking the tool by @sirgru as the base of it. Allows you to combine multiple meshes into one in one easy click. Allows the generation of Secondary Meshes too if needed. Combines mesh renderer and the mesh filter together of any two meshes into one also making it into prefab.
A collection of additions to various context menus throughout Unity.
Right click on any two GameObjects in the heirarchy and move the objects to each other as needed.
Right click on any GameObject in the heirarchy to “Resolve Import Issues”. A lot of times when importing 3D models, we tend to get empty objects, cameras, lights etc [usually dependent on the way the modeller exports them] and hence this button gets rid of them in one-go.
Rigidbody: I find myself wanting to freeze X, Z rotation and turn interpolation on and also make sure it’s not kinematic. Right click and pressing this button does it all for me.
AudioSource: One key feature missing from inspecting an AudioSource is the ability to play, pause and stop it at will. Right click and pressing this does the aforementioned.
Some small tools to allow for more effecient debugging.
BD (BetterDebug) is a bunch of extensions to the default Debug class which allows greater control over Debugging/Logging.
BD.Log("Test");
int testCounter = 0;
float testTimer = 0.6f;
BD.Log2(testCounter,testVar);
Unity has a great Debug system but lacks in outputting it while full-screened/inside VR and hence this is an Unreal-Inpsired simple way to display all Debug Log messages on the screen. All messages fade away after a while and also start replacing old logs if too many are outputted quickly.
How to use: Add LogToScreen as a component to any GameObject in your scene. And, every log subsequently called using ‘Debug.Log’ will be automatically outputted to both the console and the screen.
A very simple skeletal frames-per-second counter. Inverses unscaled delta time to output fps on the screen.
An extension of the existing Transform component to include some ease-to-use features.
Maintain the ratio of the scaling in an object’s axes when scaling a GameObject up/down. Gives a slider with an option to configure the ceiling value for the slider.
Reset the position, rotation and scale of any GameObject locally/globally individually.
Sometimes you would want to only disable the Mesh Renderers and not Disable the object so that the scripts/components on them still execute. This disables all the Mesh Renderers in this GameObject and all the children renderers.
For a lot of use-cases in Unity [wanting to have a unit scale or have positioning, rotation start from zero], we tend to create new objects and then assign it as a parent. This button does that.
Unreal offers a way in the scene to set “camera” position/rotation as bookmarks with “Ctrl+1/Ctrl+2/Ctrl+3” to set the bookmarks and then “1,2,3” respectively to jump to those bookmarks. [This shortcut might already be bound to something else. Resolve any conflicts as you please]
We need to visualize normals plenty of times for multiple of reasons when working in 3D. This simple click will start visualizing the normals in the sceneview on the currently selected object.
You can define ‘normal length’ to define the size with which normals are displayed.
One of the most essential information is the number of vertices/triangles in our current scene or in our current object. Unity’s ‘Stats’ window displays only the vertices visible in the current POV and not the entire number of vertices/triangles currently existing.
The global information is cached to save performance - whenever new object is deleted/added and you want the change to instantly reflect, press the ‘Refresh Scene Vertices’ button to reflect that change in the global stats.
A few extensions to the hierarchy window that aids in the better usage of it.
An all encompassing Header/Folder system.
To create a header/folder, right click and click on ‘Create Header’ or rename any empty game object to have a prefix of "= "
so for example, the name could be "= My Header"
.
A header is essentially just an empty game object drawn differently. You could also use it as a folder and put objects in the child of this ‘folder’.
A lot of times, there is a need to quickly enable disable objects directly from the hierarchy - this helps in that. Adds a toggle button next to every element in the hierarchy.
Ending up with heavily nested hierarchies is very common. This tool simplifies one pain point of wanting to select the parent object without disturbing the heirarchy - as the LArrow Key closes the hierarchy while selecting the parent.
A bunch of world settings inspired by the same-name Unreal settings which have a bunch of functionalites missing in Unity.
The value of KillY dictates the Y-Position threshold of any object below which it gets automatically destroyed.
Useful scripts that aid in my VR development.
Make an object always align with our headset’s level.
Mainly derived from MRTK’s head aligning script with some extra small modifications to the whole script that best suits my (and hopefully, other developers’) needs.
Various basic controller templates, such as FPS, VR.
A NPC walking/navigation system which is modular and fully configurable.
Demo:
You can reconfigure individual points/characters after using the Master Creator or you can choose to attach scripts individually and configure settings manually - both would work, and that would also work in conjunction to both approaches.
Import the sample from the package manager to get a preconfigured scene if needed.
Doing it manually: Group all the points you wish to navigate into one parent and drop the parent into the points prefab and configure everything accordingly. You can keep the PointParnet’s children messy and maybe use BetterRename to organize them (wink, wink).
Individual scripts:
A quick guiding GIF on a quick setup is given below:
General Information:
Navigation System working as it should:
A lot of times, there is a need to script events linearly (usually to follow a particular storyboard in a particular order). This scripts entails having multiple variables, multiple functions and in general just a very messy frankensteinian codebase.
This hopes to alleviate some of those messyness - trying to make a more generic flow controller which allows for triggering of events with ease also eliminating the need to do this everytime.
Also, has a Custom Inspector GUI that streamlines it some more.
General outline:
The script would look this with sample data of a storyboard:
Generate a pull request for whatever change you feel is necessary and I will be happy to review and add them.
The project should be good to go as is on most modern Unity versions. Prefer to not update any dependencies or any other prompts auto-detected by Unity.
Add a more robust documentation/screenshots accompanying the parent script/individual scripts and the working of it. // sorta done for now but will remove this after some consideration.