Every once in a while, you see people saying Unity must fix its engine before making new releases. And I’m curious… what exactly do you think has to be fixed?
I am not at all doubting that Unity has bugs, because I’ve seen some myself, but I’d still like to hear about it. I’m asking because in my 5 years of working with Unity, whenever I’ve heard that Unity was broken, 2 times out of 3, it was the person’s fault and not the engine’s.
As for me, the biggest “broken” thing I can think of right now is the way Monobehaviours work, with the messaging system ( more here ). But at least, we were assured that a new scripting approach is being worked on
Unity is at it’s core a game engine written in C/C++ but it has a number of modules for additional features which add complexity to the engine. Now factor in the number of target systems supported, the rendering API’s, target hardware.
And the fact that Unity have a legacy .net/mono scripting subsystem with an old and outdated garbage collection subsystem.
Unity are delivering a 2D/3D multi-threaded game engine across multiple-platforms.
And working on a IL2CP compiler to allow C# .net source to be compiled to C++ for Web and native platform compilation and Unity is a very complex game engine system.
Could you imagine writing code for a game engine that supports as many platforms, graphics api’s and needs to be able to built to a mono or compiled to native software and work.
Maybe Unity is becoming too complex for it’s own good?!
The only thing i really see as broken currently is the mobile, or it seems mainly android performance, compared to 4.x.
No matter what you do, you can’t seem to reach 60fps on older devices whereas it was easy as pie with 4.x.
Even just a single fullscreen quad with unlit mobile material and no texture doesn’t get me 60fps anymore on an Xperia Play, where i could have full game scenes run at smooth 60fps in 4.x (no GI, no sky and stuff like that in OpenGL ES 2.0).
Most of the stuff upgraded to 5.x from 4.x got me stuttering and about half fps.
And it hasn’t really improved since 5.0.
For a start, mixed lights do not work properly. They’re supposed to blend with baked shadows. THat issue has been around forever.
There’s amazing enlighten issue - the thing is a resource hog, produces inferior results to previous lightmapping engine, (AFAIK) unusable for mobiles, drops random tints on modular objects, yet beast has been replaced, there doesn’t seem to be a cheap alternative to enligthen.
Then around 5.2 release there was a wave of new bugs, including bugs in core systems, some of those were showstoppers.
In situation like that, poeple start perceiving engine as “broken”.
It’s probably just a matter of perception. If you’re one of the “new people” who came in on the Unity 5 series and working on a little mobile game it’s likely that for such a person nothing is broken.
If you didn’t switch from 4 to 5 there are probably very little problems as far as Unity being broken. If you’re not trying to push graphics to the max and compete with the best of the best in game graphics Unity is probably not broken. If you’re not trying to make a huge scale game of one kind or another Unity is probably not broken for you.
So probably for 80% or maybe more of users Unity is not seen as broken. If you’re one of the 20% waiting for bugs to be fixed from long ago or upgrading from U4 battling with framerate issues or focusing on things beyond the norm then you may well think Unity is broken.
I’m always hesitant to call Unity broken when someone brings up framerate issues. I’ve seen some pretty crazy stuff from people who were advanced Unity users. Even I have been guilty of many of these things at one point:
calling renderer.material on update instead of shared material
Using high-quality shaders on mobile
using foreach on Lists instead of for(int i …)
spawning hundreds of objects, each with their own monobehaviour attached instead of having one main object that updates all the hundred others
Using Linq at runtime
Using reflection at runtime
Using SendMessage()
Making a custom character controller that uses 10+ capsuleCasts per frame
Making every single object cast and recieve shadows
Using crazy Transform hierarchies with the intention of having your objects neatly organized “by folders”
Believing that Unity’s generic built-in solutions (navmesh system, physics engine, animation engine, etc…) are meant to be used for any game ever, and even if you’re making an MMO No Man’s Sky, you won’t ever have to make your own systems to replace those
Using any fancy graphics stuff from the asset store (volumetric lighting, fluid dynamics, reflections, image effects, etc…) without even looking at the source code
etc, etc…
Granted, Unity could do a much better job at educating its community about performance issues…
That’s only true(sometimes) on one end of the spectrum. Im working on a project with a huge procedural generation element and Unity really struggles to keep from crashing whenever you leave focus of the editor(alt-tab is insta death). Literally about 35 crashes a day, we thought it was our code but it’s been profiled endlessly looking for the issue. Started around 5.2. So yes, for some users with large projects, Unity is indeed “broken”.
Also it should be noted that Unity’s rendering engine is going through a major overhaul to allow it to work with the DirectX12 and Vulkan Graphical API’s. 5.4 should be the first version with full DirectX12 support so things should settle down after this.
As Vulkan uses a similar low level approach to DirectX 12 and therefore should be easier (in theory) to add to the engine, as the fundamental architectural changes should be in place (using a low level graphics API on multiple-threads).
I just wanted to give my two cents to that. It should be faster that way, because you’ll avoid the overhead involved in calling the Update() methods of all GameObjects after all. It should, but apparently isn’t. I put it to the test and the result was rather confusing. Here are the two scripts I tested this with:
SelfIterating.cs:
using UnityEngine;
public class SelfIterating : MonoBehaviour {
private new Transform transform;
private void Awake() {
transform = GetComponent<Transform>();
}
private void Update() {
transform.position += Vector3.right * Time.deltaTime;
}
}
Manager.cs:
using UnityEngine;
public class Manager : MonoBehaviour {
private Transform[] transforms;
private void Start() {
var tmp = FindObjectsOfType<SelfIterating>();
transforms = new Transform[tmp.Length];
for (int i = 0; i < transforms.Length; i++) {
transforms[i] = tmp[i].GetComponent<Transform>();
}
}
private void Update() {
for (int i = 0; i < transforms.Length; i++) {
transforms[i].position += Vector3.right * Time.deltaTime;
}
}
}
Of course I made sure that only either the SelfIterating instances or the Manager were active. Here are the results: As you can see, when updating the positions of 3200 GameObjects both, the average and worst case performance of the manager were worse. I see three possible reasons for that.
- I made a mistake - The way Unity handles the data on the C++ side of things introduces complexity we have no control over - Mono is phenomenally bad at managing CPU caches and produces crazy amounts of cache misses when iterating over huge arrays
1. I think that’s rather unlikely as my example is about as simple as it gets. 2. This is my best bet. 3. This is also a realistic possibility, especially when we consider how outdated the Mono version of Unity is. That being said, there is one thing that speaks for managing the objects using a central manager. Using 3200 Update() methods resulted in huge fluctuations in performance, whereas using one resulted in worse, but much more consistent performance.
I think the problem with your example is most of the work is being done locally on the objects transforms, so you are only measuring the difference in function call overhead.
Also you are re-calculating Vector3.right * Time.deltaTime within the loop e.g.
private void Update() {
Vector3 v = Vector3.right * Time.deltaTime;
for (int i = 0; i < transforms.Length; i++) {
transforms[i].position += v;
}
}
Try simplifying it to increase a counter on the objects and you should see more of a difference.
Also you might want to try different group sizes e.g. 100,200,400,800,1600,3200,6400 to see where the impacts are.
In addition the best benefits from this approach will probably be in games with massive unit counts e.g. Open World or RTS types of games.
hmmmm… correct me if I’m wrong, it’s still early in the morning, but I’m under the impression that your “with manager” approach still uses [presumably] empty Monobehaviours (SelfIterating) on each object. Even without Update() calls, empty Monobehaviours still have a secret performance cost according to Unity.
I made my own version of the test, with 10000 objects:
public class MoverInit : MonoBehaviour
{
// This is a prefab of an empty Gameobject with a "Mover" script on it
public GameObject moverPrefab;
void Awake ()
{
for (int i = 0; i < 10000; i++)
{
Instantiate(moverPrefab);
}
}
}
Test 2: Oject manager (only one Monobehaviour in the entire scene):
Test 2
public class Manager : MonoBehaviour
{
Transform[] managedObjects = new Transform[10000];
void Awake ()
{
for (int i = 0; i < managedObjects.Length; i++)
{
GameObject newObject = new GameObject("ManagedMover");
managedObjects[i] = newObject.GetComponent<Transform>();
}
}
void Update ()
{
Vector3 movement = Vector3.forward * Time.deltaTime;
for (int i = 0; i < managedObjects.Length; i++)
{
managedObjects[i].position += movement;
}
}
}
Here are the results:
Monobehaviours on everything:
Oject manager:
Here’s some results in terms of average FPS (Monobehaviours versus Manager) 10000 objects: 115 FPS versus 430 FPS on average 3200 objects: 350 FPS versus 600 FPS on average 300 objects: 800-1500 FPS versus 1800-3200 FPS (it fluctuates a lot…)
That’s… a pretty substantial gain!
Absolutely, and I’d also add cases where you have to handle lots of spawned projectiles or effects. It is very common to see some sort of “Projectile” monobehaviour on every bullet in a game, or some sort of “TimedDestructor” on every spawned particle/sound effect. Of course, with the way things are right now, you’re pretty much screwed if your projectiles require actual collision detection. Because a Monobehaviour is the only way to access collision events in Unity. I really really wish Unity would expose more of the PhysX API…
It’s sad because even if I made a Unity Feedback entry for that (and I have made several of those in the past), it’s not the kind of issue that the Unity community votes for. The Unity community is much more interested in a “Click to make MMO” button than in making Unity a truly professional engine
@PhilSA This seems reasonable to me. It’s the benefit of being a programmer and having a better understanding of what is going on behind the scenes. Makes sense that people with such a background should always be able to make a better game technically speaking (performance, low number of bugs and probably only minor bugs at that, etc).
It’d be the same in any language and framework. More experienced more skilled people will get better results (performance and perhaps stability as well). Your test is actually a great example showing this thinking “programmers are not really needed anymore for game dev” is basically just wishful thinking. Although it is true for a large number of cases… whenever you are dealing with an unusually large scale it won’t be true.