Feedback on Unity3D's API. What i've found in 2017

Merry Christmas and Happy New Year. Starting off with a grand ambition.

About a year in with working intensely with Unity3D I have assembled a list of things that is either, broken, bothersome or can be improved. In hopes of at least reaching the attention of UT developers i give you this.
Some are simple. I am solely a programmer so this will be mostly about the API side of U3D.
I’m marking the headers with a color ranging from green to red indicating the severity.
Let’s begin:

Vectors

Transform properties
An angel dies every time you write this:

var pos = gameObject.transform.position;
pos.y += Time.deltaTime;
gameObject.transform.position = pos;

But a simpler approach would be to write

gameObject.transform.position.y += Time.deltaTime;

newcomer scripters will not understand why this “sensible” line wont work.

Another example commonly used in 2D games

gameObject.transform.position.z = 0;

at least provide methods to set/mutate individual components of the vectors.

gameObject.transform.position.SetZ(0);
gameObject.transform.position.AddZ(Time.deltaTime);

change the position property to a field. Other properties such as scale and rotation could also be changed.
Note: eulerAngles is a computed property and wont function if changed into a field.

Vector Math Operators

public static Vector3 operator *(Vector3 a, Vector3 b);
public static Vector3 operator /(Vector3 a, Vector3 b);

I studied about this and found that there is quite a controversy about this and i see UT has chosen not to take a stance on this. The opinion of mathematicians is that vectors are cross multiplied. According to Wikipedia the X and * symbols are ambiguous to either function.

In my opinion vectors should be multiplied linearly, cross multiplying is counter intuitive.

// example of positioning an object at the bottom of a bounding box
transform.position = bounds.center + (Vector3.forward * bounds.size);

// example of keeping keeping an object grounded
transform.position *= new Vector3(1, 0, 1);

this also includes the division operator.

//example of changing 1 object scale to fit another object
transform.scale = 1 / transform.scale * transform2.scale;

and lastly. the + and - operators on primitive types. And they behave just like the scalar multiplication.

public static Vector3 operator +(Vector3 v, float scalar) => new Vector3(
    x = v.x + scalar,
    y = v.y + scalar,
    z = v.z + scalar
);

Remove implicit operators
I cannot count how many times i have screwed up and hunted for the error throughout my entire codebase just find that i wrote Vector2 instead of Vector3.

for example:

Vector3 p1 = new Vector3();
Vector2 p2 = new Vector3(1, 1, 1);

var center = p1 - (p2 - p1)/2;

or if you’re like me and use implicit variables

var p1 = new Vector3.zero;
var p2 = new Vector2.one;

var center = p1 - (p2 - p1)/2;

the expected result is a Vector3.one/2 right? Wrong!
The result for both is actually: {.5f, .5f, 0} for both.
Z turned to zero. Why? What happened is that i have accidentally written Vector2 instead of Vector3 in p2 and U3D liberally converts between them.
This is especially troublesome when you go crazy with autocomplete and you write vec{enter}.up.

Vectors aren’t interchangeable. Whether or not the programmer is converting from 2d to 3d coordinates is up to the programmer how he want to map the components.
Some want to use XY for side-scroller
Others use XZ for top down

So just remove all the implicit operators as they cause more harm than good.

Remove partial constructors in vectors
Also a bit continued on the implicit operators are the constructors. Which can also cause confusion.
The only constructors necessary are

public class Vector2{
   public Vector2();
   public Vector2(float x, float y);
}

public class Vector3{
   public Vector3();
   public Vector3(float x, float y, float z);
}

this one is pointless. again it’s up to the programmer how they handle 2d → 3d conversions

public Vector3(float x, float y);

Open for useless Syntax Sugar on Vectors

While making this list i came to realize that these are too experimental and doesn’t provide anything of substance. They a interesting though. You don’t have to read this section. There is also no color markers.

Vector IEnumerable implementation
I have this one my own Vector2 implementation but i have personally never used it.

public IEnumerator<float> GetEnumerator() {
   yield return x;
   yield return y;
}

IEnumerator IEnumerable.GetEnumerator() {
   return GetEnumerator();
}
Vector3 p1 = new Vector3(1, 1, 1)

var sum = p1.Sum(); // 1 + 1 + 1 == 3 using linq

IEnumerable to VectorN
an extension method.

public static Vector3 ToVector3(this IEnumerable<float> enumerator){
   var arr = enumerator as float[] ?? enumerator.Take(3).ToArray();
   return new Vector3(arr[0], arr[1], arr[2]);
}

which enables this

var vec = new float[]{ 1, 1, 1 }
var point = vec.ToVector3();

it may be useful when porting data.

Vector collection initializes
this one is pretty handy but is sadly only available inside on object initialization expressions.

public class Vector3 : IEnumerable<float>{
   private int _index;
   public void Add(float n){
       switch(_index++){
           case 0: x=n; return;
           case 1: y=n; return;
           case 2: z=n; return;
       }
   }
}

and usage would be:

public class Vectors{
   public Vector3 Pos;
   public Vector3 Rot;
   public Vector3 Size;
}

var newVecs = new Vectors{
   Pos = { 0, 0, 0 },
   Rot = { 0, 90, 0 },
   Size = { 1, 1, 1 }
};

Editor

Play mode persistence
The toy-box Playmode is a neat idea where you can try out stuff and it wont mess up your scenes while you do it. But there is grief when you’re adjusting the properties of something live. Like you’re adjusting the speed of running cycle and you must run it in Playmode. Now this is simple of course when you just need to remember 1 property value. But when you have 10 changes you need to screenshot them and spend time typing them back in. Or you simply forget and start screaming when everything resets after 30 minutes of adjustments.

There would be solutions available. For example when you exit Playmode U3D will give you a list of properties you changed and ask which you want to save.

Another solution would be the ability to firstly identify which properties has been altered. Much like Maya does when you have key-framed properties. Unity should highlight changed properties and with an ability to save with in the right click menu.

Always Online
I guess this one is gonna fall on powerless ears since this stuff is usually decided by the brass.
The U3D launcher will show a white screen until a connection can be established. Living in a 3rd world country this is quite a hassle cause with the spotty internet there quite a chance i need to restart the launcher several times until it successfully connects.
And even when i manage to actually open the project there’s a chance it will pop up again asking me for login.
I figured if i blocked it in the firewall it would revert to offline mode automatically but i need to disable the entire network adapter for that to happen. Even with the offline license installed. If the adapter is connected you must connect before using U3D.
I have a solution that works for now, I’m not gonna share it cause i have a feeling UT is making active efforts to patch these methods and keep U3D online by all means.

But why need so much license verification for a product that’s free? Dial down on the always online DRM and my life would be a bliss.

Threading

Simple static function to return back to the mainthread
I could create my own tools for this but i’d like a first class solution that doesn’t come off as an ugly hack.
I’m talking about background threads.
there is the MonoBehavior.Invoke() but it doesn’t work like you’d expect. I know U3D officially doesn’t support threading. But for those who decide to do it anyway. At least give us a way to send functions back to the main thread. Any UI framework i know of have this. BeginInvoke(Action), Dispatcher.Invoke(Action) and it’s boilerplate design when working with HTTP.

UnityWebRequest Background thread
I can’t begin to fathom the inner workings take enables unity to use the IEnumerable hack work, and it’s most likely what prevents threading from working. But nonetheless calling a WebRequest from a background thread and then Invoking back to the main thread is how we’ve done things for decades and by now should be a no-brainer.

It’s only a matter of time before i implement a new web request using Sockets and callbacks. (And C# async once they roll that out.)

Exceptions
Ok this is probably my own fault for doing threads even though they discouraged it. I had a parallel program and i was getting tons of errors but not in the obvious places. I had an an Out Of Range exception when i accessed an array. Or actually i didn’t, but after testing and debugging for hours i realized it, U3D had not thrown the error in the console and as such the threads just silently failed. This may be harder to fix but. It’s a bug nonetheless.

Other

Debug Gizmos
Debug.DrawWireSphere()
Debug.DrawWireCube()
Debug.DrawMeshCube()
Debug.DrawIcon()
etc…

I think it’s not for fair that the best of the debugging utilities are locked away in OnDrawGizmos(). Copy these members into the Debug class too and make them static so we can access them anywhere. As usual i had to create yet another wrapper.

You could implement it by either:

  1. Pass the message to the Gizmo class
  2. Build the lines using the Debug.DrawLine()

JSON
In any JSON system out in the wild that is not U3D, commonly it is agreed that we use Properties not Fields.
I get that the JSON serializer were built to work as an implementation of the existing system using the [Serializable] attribute. But Jesus it’s inflexible. If i add a new complex field i always needed to set the attributes for every single data-model we had. And the collections? The way of using List<> and Dictionary<,> raw pain when you spell it out. The List and Dictionary classes does not have the[Serializable]attribute. So you would have to subclass it and add the attribute on that class.

After working with the JSON system for a month or so i gave up. The need for a better serializer was so prevalent that i had to delay my project for a week developing a new object serializer/deserializer. Tons of others have done the same. It’s not hard to make one and UT really did a shabby job on this.

Det´ en ommer!

Multipart formdata
Another one that did not follow the standard as usual and is causing problems on my webserver.

According to the RFC1341 standard (Which i had study while trying to fix it)

Section 7.2.1 states that the boundary is formatted like “–gc0p4Jq0M2Yt08jU534c0p\r\n” not length sensitive. But definitely does not contain an extra pair of “\r\n”

if you briefly search the internet “unity3d multipart formdata boundary” you will find that I’m not the only one who came across this issue.

the solution i used was building the boundary by myself and setting the header. Then using the UploadHandlerRaw class on the WWWForm.data. I can’t remember why that worked since i made it about 8 months ago, but it’s has been running without issues so far. Except from the threading of course.

Answers and Documentation that leads to packages
This happens most frequently when working with Shaders but also happens when people reference example projects.
When i look for an answer an i see someone says “Oh you can find this implementation in the Particles/Multiply in the Standard Shaders package” why not just paste the lines of code? Or even better link to an online Repo where i can read the code immediately, In the browser. Instead of referencing a package you can reference an online api like.
code.unity.com/StandardShaders/Particles%2FMultiply?lineFrom=120&lineTo=140
this would open a page where code is highlighed for me. Github already has this functionality.

Although aside from that API there isn’t much to be done here, it’s entirely up to the community how they choose to articulate themselves.

Show in explorer
Currently when you click “Show in Explorer” it will open the containing folder with the selected item highlighted.
Well I’d like to add another condition. If the selection is a folder don’t highlight it, Open it.

Console Exceptions
Has this always been broken or is it just recently?
I find my consoles errors is thrown somewhere in List.cs:457 or something. Code that is part of the framework. If you can’t clean the shown stack in a performant at least let the double click search upwards in the stack until it hits user code.

Auto detect normal
some sugar for the users.
Normal maps have this distinct blue color.
Well simply Average(pixes).B == ~127. Or vector lengths == ~1.
It does require throughout analysis of the picture which is quite consuming in an already slow process.

Text Asset Preview
Currently it uses 8 space tabs.
Change to 4 spaces. Like VisualStudio and MonoDevelop.

And Lastly

Mathf.Tau = Mathf.PI*2;

Because why not?

All done! If you survived. Please come again!
If you have any comments please share. Otherwise I’ll just drift back into the shadows. Good luck in 2018.

A lot of the issues you outline are somewhat alleviated by extension methods.

Not “a lot of”. Just the first one can be extension methods.

gameObject.transform.position.AddZ(Time.deltaTime);

Which i also have in my codebase. But it’s just bandaid.