Best way to switch UI in Unity3D - unity3d

We are building a mobile app built in Unity3D, which involves a lot of UI switch. For example, from this page to the other page, it involves a lot of disabling the previous UI and activate new UI elements.
A common way to do is to set old UI inactive and new UI active. When switch back, just deactive/active again. But I read that this will cuase Rebuild problem (Canvas.SendWillRenderCanvases or BuildBatch). I wonder what is the alternative?
Will these two solutions work?
Instead of activate/deactivate UI element, apply it on the UI canvas.
Deactivae the UI element by moving it far away. Will it cause UI Rect rebuild?
Set in different layer, change its layer to invisbile layer when deactivate.

I would discourage you from using a state machine for your UI if you consider developing an application with many UI layers.
It will result in a scene hierarchy with hundreds of objects, some of them only been used when going deep down the app (like settings of a specific page) but they end up in memory at all time.
Also, it makes things harder to debug since you cannot really jump to a specific state without going through all the previous ones (except if you are already advanced prog and you defined your classes so they can work from anywhere).
The easy solution is to use scenes to separate your states, just like it is done in Android/iOS with Activity/Fragments or views.
This will clean you memory when needed, you can still keep scenes alive on the stack (like mobile OS does) using additive scene loading, since you won't have a lot of objects to create, the scene changes will seem seamless.
You can easily reuse code over scenes with inheritance and extension with scene name:
public class MyUIClassWithManyCommonCode:MonoBehaviour{}
public class FrontPage : MyUIClassWithManyCommonCode{}
public class CatalogPage : MyUIClassWithManyCommonCode{}
And finally since, you limit the amount of objects in a scene to only what should be seen, it is easy to find an object in the scene.

Related

How should I handle a multiple scenes project?

I'm trying to make this game using the approach of multiple scenes to make things more modular.
In my actual case I have an "Initialization" scene which holds some global state objects and the one to control the state machine of all the scenes in the game.
As for the other scenes, for now I divided them just in two: the base scenes (which for now contains everything besides UI) and its UI scenes (which basically have a Canvas and all the UI elements and UI-related scripts).
The confusion in my mind is simple though: as I tried to make the UI scenes as modular and independent as possible, there are a lot of points of interactions between the base scene and its UI scene.
For the sake of illustrating this question please take this problem I'm facing right now: I have camera animations that should be played as a response to user inputs to the UI (like the click of a button should trigger a specific camera animation). Thing is: that camera is not in the UI scene. The way I'm resolving this problem right now is creating a ScriptableObject which holds events for important actions triggered in the UI scene that are fired in the UI scene and subscribed in any other place. The same can occur in the opposite direction: the UI scene need to react to many actions that happens in other scenes.
Considering that the "camera animation" problem I explained above can happen with many other objects, if there is not a better way to handle that wouldn't splitting a game into multiple scenes be just too much of work just for the benefit of modularity? And by that I also asks: am I handling this problem the right way?
If you want to keep things consistent between scenes, there are a few ways to do it.
PlayerPrefs lets you keep variables consistent, I don't need to do a whole tutorial here, look it up.
DontDestroyOnLoad lets you take an object and make it consistent throughout the whole game. If you want, you can use DontDestroyOnLoad on one of your cameras and just delete the others in the other scenes if you want to keep a consistent camera.

Use one or multiple SKScenes for Level based Game

I'm making a level based game using SpriteKit. I would like to know the best practice for making level changes. I was originally using one Scene as my gameplay scene and when a level is completed, it removes all nodes in the scene and then adds the ones for the next level. I am using a background node that is persistent throughout the entire course of the game. I'm worried about memory because I don't think ARC will deallocate the nodes removed because the scene is persistent. Is this method ok or should I instantiate a new scene for when a level is changing?
The best practice is to separate game data and assets from game code. This way, you can make changes to stuff without having to recompile (and is handy if you are working with another person who doesn't code).
Here is what apple has to say about it at WWDC 2014:
When you transition between scenes, ARC will deallocate the prior scene, assuming you made no strong references to it. Since you're starting out it's unlikely you need to worry about this right now... it's mostly done with globals and closures, and you should be able to fix it if it becomes a problem (but likely won't).
You can use things like unowned self and weak var etc to ensure this doesn't happen when needed. Again this is a more advanced topic but it's good to be aware of them.
Really, making level changes is entirely up to you... if you want to make a state manager that swaps out stuff to one scene, you can certainly do that... or, you could make a bunch of scenes and transition to that. Again, the best practice here is separating game content from game code, not necessarily how you switch scenes.
Personally, I would used separate SKScenes-- because it's already built in with transitions, memory management--and you have the option of using the editor, and you get to give each scene it's own file if desired.
There is also GameplayKit which has a statemanager, in which case you could use one scene and have different states be the level.
here are some resources, buried in there are some nuggets pertaining to what you want.
https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/DesigningGameswithSpriteKit/DesigningGameswithSpriteKit.html
https://developer.apple.com/videos/play/wwdc2014/608/
https://developer.apple.com/library/content/samplecode/DemoBots/Listings/DemoBots_SceneManager_swift.html

Same GUI multiple scenes in Unity game - prefab of Canvas?

My problem is how to share same GUI in multiple scenes.
For example:
I have Inventory GUI on Farm scene and I need this GUI on other scenes like Castle, Dungeon etc.
It's good idea to make prefab of Canvas? Or design again the GUI? What about mixing "shared GUI" and individual GUI like Dialogs etc.?
Thanks for any answer.
You can certainly make a prefab of a canvas for each screen you need although if you have to destroy it and respawn it a lot it could cause a performance hit. An alternative is to create a single canvas with all the screens as children, all disabled, and enable each as necessary. This has the advantage of not doing lots of computation at once but on the downside there's some overhead for keeping it all in memory. For a small game I would recommend the latter and if you need to scale it up you can mix the two: have canvases with more than one related screen, ideally screens grouped in such a way that they are only accessible in certain situations, letting you keep as few canvases in the scene as possible.
Besides GUI itself you will need some scripts to handle each element and property separately.
Take a look at singleton codes; it shows how to create persistent object, which stays across different scenes.
http://wiki.unity3d.com/index.php/Singleton
It's good practice to script GUI which needs to be visible on different levels with this design pattern.

Understanding scenes in Unity3d

I have some confusion with scenes in Unity3d and I was not able to find any resources about them.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
Can one overlay scenes?
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
How does one send data between scenes/interface between scenes?
I understand that this is a broad topic, but I didn't want to spam with multiple questions.
When should scenes be used? For example in a platformer would every
level have to be a different scene? Would the main menu be a scene?
There are no general rules about that. In theory you may have just one scene for the whole game.
How you organize your scenes is entirely up to you and often depends on the type of game you are creating.
I think that there are at least 3 features to be considered of using scenes:
they are a logical container for all pre-instantiated objects that might be useful to divide your game into multiple levels/sections.
You can serialize cross references between GameObjects and Components inside a scene (if GO A needs a ref to GO B, and they belong to the same scene, the reference can be serialized and you no longer need to find the referenced object at runtime)
When you load (not in an additive way) another scene, the resources already loaded into memory are automatically released
Can one overlay scenes?
Yes you can using LoadAdditive. Unfortunately, once 2 scenes are both loaded into memory there is no automatic way of distinguish objects belonging to one or the other. So if you load additive a second level environment, it's up to you to keep track of the previous environment and explicitly destroy it if you need to.
How do assets work between scenes? Are they attached to each
individual scene and have to be reloaded every time. Can one specify
when an asset is no longer needed?
As defaults every GameObject of a scene will be destroyed once the new scene is loaded (unless you use an additive scene loading). A way to make a GameObject survive across scenes is to mark it using DontDestroyOnLoad.
If you need to share a particular "configuration" of a GameObject, you can store it as a prefab, and reference it across scenes (but remember that once in a scene it's a prefab instance, so the GO shares with the prefab the initial serialized and not overriden properties, but 2 instances of the same prefab are different objects).
How does one send data between scenes/interface between scenes?
Several ways, depending on what kind of persistent data you want to share.
For a particular GameObject instance let the object survive using DontDestroyOnLoad.
If you have some configuration data that doesn't need to be attached to a specific GameObject you can consider storing a ScriptableObject inside the AssetDatabase and reference it.
If you have data that must persist across different game sessions you can consider storing them into PlayerPrefs.
There are 2 other ways that I don't like, but just to cite them:
Using a static field can sometimes help you in doing that, but it has several problems from my point of view
Save and load from disk (could be useful in several situations, but often it's a platform dependent way and you can have some trouble especially on different mobile platforms)
This is a broad topic btw, I hope this answer can be a quite decent overview.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
There is no rule as to how many scenes you need to have in your game. However, scenes allow you to logically separate out parts of your game from the rest of it. You have to have a minimum of one scene.
By main menu, if you are referring to a canvas with your UI elements, it will be IN a scene and not a scene itself. Canvas is just another GameObject, that we mostly happen to use for showing game menus. I mostly create a Canvas GameObject, put a script by the name of "UIManager" and put DontDestroyOnLoad on it, so I have access to it in all scenes. Make it Singleton and I ensure that it is not duplicated.
Can one overlay scenes?
Yes, there is no restriction as to how many scenes you can load at a time. What purpose do you plan to overlay scenes though? Maybe there is a better way than loading additively.
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
Assets are what you see in your 'project' hierarchy. I think you meant "GameObject"s in the scene, and if so, think of your gameobjects as entities with components (Entity-Component System). All entities in a scene get destroyed when its parent scene is destroyed until explicitly stated not to, using DontDestroyOnLoad in some component (a monobehavior in case of unity). The destroyed ones will get garbage collected.
So how they are loaded (or reloaded) depends on your implementation, on whether you are instantiating/destroying them time an again or if you put their instantiated prefabs in a cached object and retrieving later from it.
How does one send data between scenes/interface between scenes?
Heisen covered the ones I could think of. Just to add a little bit to it, it also depends on how you want to the architect your project. So if you had an underlying data structure to e.g. hold Commands, you are free to use it in any part of your project
Most games would be organised to have scenes for every level(including the main menu) but that is entirely up to you.
You can use the data from one scene to another if you save it in a text file or binary. There are a lot of tutorials on how to do this. I find documentation helps a lot.
Assets are universal in a project.
You can not overlay scenes.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
When to use a scene is up to you. If you are just starting I would recommend using a different scene for each section of your game.
Can one overlay scenes?
Yes, using LoadSceneMode.Additive(). (LoadAdditive() is obsolete)
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
By default, assets are deleted when using SceneManager.LoadScene(). However, if you use DontDestroyOnLoad(), the object will not be destroyed when entering new scenes. If you want to only keep an object through a few scenes instead of all, use Destroy() with some boolean logic.
How does one send data between scenes/interface between scenes? I understand that this is a broad topic, but I didn't want to spam with multiple questions.
You can send data through scenes by using the aforementioned DontDestroyOnLoad(), referencing the data on different scripts, using ScriptableObjects, using JSON Serialization, using StreamWriter(), using PlayerPrefs (Don't use for important information), the list goes on. I would personally recommend using ScriptableObjects for their accessibility, and StreamWriter() for it's encryption capabilities.

RPG Game loop and class structure (cocos2D for iPhone)

I'm looking to make an RPG with Cocos2D on the iPhone. I've done a fair bit of research, and I really like the model Cocos2D uses for scenes. I can instantiate a scene, set up my characters etc. and it all works really nicely... what I have problems with is structuring a game loop and separating the code from the scenes.
For example, where do I put my code that will maintain the state of the game across multiple scenes? and do I put the code for events that get fired in a scene in that scene's class? or do I have some other class that separates the init code from the logic?
Also, I've read a lot of tutorials that mention changing scenes, but I've read none that talk about updating a scene - taking input from the user and updating the display based on that. Does that happen in the scene object, or in a separate display engine type class.
Thanks in advance!
It sounds like you might do well to read up on the Model-View-Controller pattern. You don't have to adhere slavishly to it (for example, in some contexts it makes sense to allow some overlap between Model and View), but having a good understanding of it will help you to build any program that has lots of graphical objects and logic controlling them, and the need to broadcast state or persist it to disc (game save), etc.
You also have to realize that cocos2d provides a good system for structuring the graphical scene graph and rendering it efficiently, but it doesn't provide a complete infrastructure for programming games. In that sense it's more of a graphics engine than a game engine. If you try to fit your game's architecture into the structure of cocos2d, you might not end up with the most maintainable result. Instead, you should treat cocos2d as what it is: a great tool to take care of your display and animation needs.
You should definitely have an object other than the scenes that maintain the game state, because otherwise where will all the state go when you switch between scenes? And within scenes/levels, you should simply try to use good Object Oriented design to have state distributed over objects of various classes. Each character object remembers its own state etc. Here you can see where MVC becomes useful: when you save the game to disc, you want to remember each character's health level, but probably not which exact frame index the sprite animation was showing. So you need to distinguish between the sprite and the character (model) itself. That said, as I mentioned before, for game objects that don't have a lot of logic attached to them, or which don't need to be saved, it might be ok to just fuse the Model and View together into one class (basically by subclassing CCSprite).
To pull off MVC the way it's supposed to be, you should also learn the basics of Key-Value Observing. (And you'd do well to use this replacement for Apple's interface.) In more intensely real-time games, techniques like this might be too slow, but since you're making a RPG (good choice for starting out) you could probably sacrifice performance for a more maintainable architecture.
The game scene (which is just another cocos2d sprite) plays the role of Controller, in terms of the MVC pattern. It doesn't draw anything itself, but tells everything else to draw itself based on inputs and state. It's tempting to put all kinds of logic and functionality into the game scene, but when you notice that it swells, you should ask yourself how you could separate that functionality into other classes. Analyze which type of functionality you're implementing. Is it to do with data and state (Model)? Or is it about animation and rendering (View)? Or is it about connecting logic with rendering (in which case you should try to make the View observe the Model directly)?
The game scene/Controller is basically a dispatch center, which takes input events (from the user or from sprites reporting that they've hit something, for example) and decides what to do with them: it might tell one or several of the Model objects to update themselves in some way, or it might just trigger an animation in some other sprites, for example.
In a real-time game, you'd have a "tick" or "step" method in the scene which tells all objects to update themselves. This method (the game loop) is the heart of the program and is run every time a new frame is drawn. (In modern game engines there's a lot of multi-threading but let's not think about that.) But in your case, you might want to create a module that can "play the game" completely separate from the game scene. Imagine creating a program that can play chess through the terminal, using only text input. If you create the whole game system in that manner, and then connect it to the graphics engine through a small and clean interface, you'll have a really maintainable app with lots of reusable code for future projects!
Some good rules of thumb: the model (data) shouldn't know anything about sprites or display states; the view (sprites) shouldn't contain any of the game's actual logic (the game rules) but only know how to do simple things like moving and bouncing and reporting to the scene if something complicated happens. Whenever possible, the view should react to changes in the model directly, without the controller having to interfere.