antfarmar / Unity-3D-Asteroids

A simple Asteroids clone. In 3D.
The Unlicense
65 stars 15 forks source link

UI Canvas: More Than 1 #28

Closed antfarmar closed 8 years ago

antfarmar commented 8 years ago

Currently there exists 2 UI canvases:

ghost commented 8 years ago

Short & simple answer

Why? Any advantage?

For simplicity.

Could this not be done with 1 Canvas?

It could have been done with 1 Canvas.

What is the overhead & resource cost per Canvas?

Extra drawcalls, if I remember correctly.

Is it significant or negligible?

Negligible in this case.

Should everything be prefabs?

Heavens, no. Only make them prefabs if the prefabs solve a problem.

Detailed answer

Why? Any advantage?

So, since I introduced the prefab, I'll shed my thoughts on why I considered a prefab.

From my point of view: If you decided to want to use my score, but my changes made hard to make scene merges, all you had to do was to ignore my scene changes and instead just plop the prefab into the scene.

For a multi-developer project it may also help if developers sit in a stable, personal scene that just has the score stuff and nothing else. That way they can develop the UI without having to worry about the state of the game scene, winning or losing etc.

I created Score Canvas out of old habit. You can mess around with the UI all you like and later just plop in the Score Canvas if you want. It is simple to work with - no need to fiddle it into an existing canvas. I tried to make it as easy as possible for you to decide if you want it or not want it. It's a "standalone" object in that you can just plop it into a scene that has an event system.

Could this not be done with 1 Canvas?

Sure it can! Just remove the Canvas from the prefab and make the score text object the prefab instead (or remove the prefab if you don't like the prefab). Then place it inside your existing canvas.

But consider what happens if both you and I had been messing around with the same canvas. It's often the case that you get merge conflicts when more than one developer works in a scene/asset. Without the standalone prefab, you'd have to carefully merge the scene/asset files (which is a pain in the famous) or recreate either your or mine work from scratch. It's hard to explain without seeing the problem first hand so if you want, we both could mess with the same scene and you get to appreciate when a prefab would been handy. Perhaps you have a better solution after some thinking, too!

Prefabs are perhaps not perfect, but they do help a lot in this regard. The score text could have been made into a prefab on its own (without the additional canvas) but then you'd have to carry the burden of positioning the score text into an appropriate child transform of your existing canvas. However, that burden doesn't have to be significant, but it is still a burden. I did it this way to remove as much burden from you as possible.

What is the overhead & resource cost per Canvas?

If I remember correctly, it'll be extra draw calls per Canvas. Try duplicating the canvas 100 times and measure the difference with the profiler before and after to see actual numbers!

Is it significant or negligible?

For this game, I suspect it to be extremely negligible. Again, looking at the difference using the profiler you'd get the full picture.

Should everything be prefabs?

If it helps.

I made it a prefab, to help you in case of merge conflicts with the pull request.

Having a modular Score Canvas reduces setup required to use it. In your current project there's just a single scene so I guess it could go in the scene. If you have a use case to use it again, it may benefit being a prefab. One example would be having multiple scenes, or having integration tests test that the score canvas updates the score after user scores. In that case it would make sense to test a reusable system (i.e. a prefab).

Since Unity still doesn't support nested prefabs, be careful of overusing prefabs. You'll probably reach a point where you want to make a UI prefab that has two or more other prefab children. However if you just plop the children prefabs into the UI prefabs, later changes to the children prefabs won't change the UI.

This is extremely annoying if you had, for example, made a cool looking button prefab and you wanted to make a prefab for a dialog box using the cool button, and then made a prefab for the main menu, also using the cool button. Now you have two prefabs that used one shared prefab. If you make changes to cool button, neither the dialog box prefab nor the main menu prefab will get updated even though both use cool button! Super duper super ultra annoying! It means you have to edit each prefab using the other prefab by removing the old instance and adding the new instance back in. Now imagine having a full application UI done this way, where changing a single button force you to make changes in dozens or hundreds of prefabs. Clearly, you'd get frustrated pretty soon - especially if you worked in a team where other people were changing completely different sub-prefabs and you both changes dozens of prefabs and had to deal with merge conflicts.

This means you have to make a tradeoff between WYSIWYG and runtime instantiation. I believe there are assets in asset store that work around this problem. If you plan on making nice and modular prefabs, have a look in the asset store, or be prepared to write a lot of Instantiate(coolButton) for your nice, modular UI :-1:

Closing words

Don't be afraid of removing the prefab. See what happens. If you find that something about the process annoys you, figure out how to deal with it. Besides, everything is stored in Git so you can always revert the change if you choose to keep it or undo actions that seem questionable.

Tip

I don't know of a simple way to un-prefab a prefab instance. Perhaps it is simple and I've overlooked it. If it isn't, consider making an editor script that creates an instance of the prefab into the scene - hopefully the link to the prefab will be lost you get a "hard copy" in the scene.

I never went back from a prefab to a single instance. This doesn't mean I think it is good practice to keep the prefab. This doesn't mean I think it's good practice to remove the prefab either. It means I never really thought of it as a problem. I guess it could make sense to remove prefabs for the sake of cleaning up a project, should the need arise.

antfarmar commented 8 years ago

Thanks for the detailed reply. Lots of good information & Unity tips! :+1:

I'll leave it as is for now, since as you point out, prefabs are quite handy in the prototyping stages. Plus I should be more focused on the code design & architecture right now. :smile:

antfarmar commented 8 years ago

A non-issue for now.