Which architecture for Unity4.6 UI implementation - c#

I'm working on a Unity project. It's a visualisation software, so most of the game mechanics are based on buttons, sliders, color-picker updating my GamesObjects.
I can't figure out how to organise my UI implementation.
Is it a good idea to apply some kind of MVC pattern to unity, any idea how to do it (I found some article about that but they weren't clear to me) ?
Currently I'm adding UI elements in the scene. An empty game objets called UIManager is holding scripts concerning the UI. Those scripts hold references to UI elements, add a listener to them and contain methods called by the event.
My approach is correct? How to improve it?
My UI Manager contain scripts like this one :
public class someMenuGUI : MonoBehaviour {
public Button enable;
public void Start()
{
enable.onClick.AddListener(Enable);
}
public voidEnable()
{
GameObject[] Objs = Object.FindObjectsOfType (typeof(GameObject)) as GameObject[];
// then do something on them
};

That's a very good question without an answer that can be considered to be universally true. However, I would like to share my approach to this.
When I write Unity code, I have two categories of users in mind: players and designers. Essentially, since almost all Unity code is contained in MonoBehaviours, and MonoBehaviours are used in the editor, you're constantly writing a tool for designers that they use to actually create a game.
Even if you don't have a designer and work alone, it's useful to think about code in this terms. This way, you have a clear separation between code space and editor space: code doesn't have to make any assumptions about what happens in the editor; instead, designer has to be able to use your components to build what they want.
So, where do you draw the line? I think that if you're going to use the MVC pattern, the separation is quite clear: the controller logic should be contained in code, but the wiring up of the actual UI elements should be in the hands of the designer. Which, finally, brings us to the code.
A great way to implement the MVC pattern is to use events instead of solid references: this way the controller and the view don't have to know each other's types, they only have to know the model. But since you want the designer to hook events up in the editor, you can't use C# delegate events. Thankfully, there's a new feature of Unity's UI system just for that: UnityEvent.
So, let's say that your script, which plays the role of the controller, has to have two-way communication with the view: from controller to the view to update the information, and from view to controller to run the user's action. Turns out, it's very simple to set up. Create a public UnityEvent (with a correct generic argument) for update of the data, public method for user action, and you're done with the code! All that designer will have to do is to set the Unity event on your script to update the UI, and to set up Unity event of UI element to call your controller's method.

Related

The opposite of events and delegates?

This might sound weird, but I am just experimenting with the thought of it. I was wondering about subscribing functions to different classes. So i have a base or static location where my method is held, and without relying on inheritance, am i able to subscribe that function to an object?
For example:
Action class has a method class SendKeys
I have three objects called Textbox and Button and Textarea
Realistically i don't want them all to have access to SendKeys function, just Textbox, and Textarea. But i also don't want to copy paste the SendKeys code over and over again.
I could create a static class that takes the data and the two objects will call that static class, but that just seems like extra work and i would be creating the function anyways in order to call an external function.
The best solution i have is to just copy paste code. but i was wondering if i could subscribe specific functions. Its like the opposite of what an event and delegate can do right? Cause the subscription requires code in the class of the subscriber. I kind of think i want partial classes? I am not sure. Thoughts?
A deeper dive into the issue:
I have a bunch of different elements to work with here are some basic ones, it goes deeper when you take into account custom elements:
Button
Textbox
Textarea
MultiSelect
SingleSelect
RadioButtons
Checkboxes
MenuItems
PasswordTextboxes
ETC
Each one of these would have their own actions that can be applied. For example they all would have the same properties like GetAttribute or GetCssValue but i don't want to be sending keys to a checkbox, so i dont want to have the ability to have that function when creating inheritance. BUT, i do want other objects to have those functions. The code is lengthy and a bunch of copy pasting code is ugly. I was hoping i can subscribe functnions to objects. So i can say something like Actions.Click(Textbox) or Textbox.Click or w.e but i cannot do Actions.SendKeys(button, "fdsaf") or Button.SendKeys("fdsaf")

How to write "When current animation finished"?

I have a model with animation controller. I set the states and parameters for transitions between them. Now I need to make the model play its animations in order I want.
I can use:
GetComponent.<Animator>().SetBool("someparameter",true);
to uncheck currently checked parameter and check another parameter after current animation finished.
How can I make a condition for when the current animation finished?
Examples I'm finding are related to animation component (not animator), or they are too complicated for me, while I need a simple way I can understand and use quickly.
unity3d supports the events and triggers within the macanim, have a look the links below
https://docs.unity3d.com/Manual/animeditor-AnimationEvents.html
http://answers.unity3d.com/questions/750785/mecanim-trigger-event-at-end-of-animation-state.html
Try this
if(this.animator.GetCurrentAnimatorStateInfo(0).IsName("YourAnimationName"))
{
// Avoid any reload.
}

Nesting anonymous delegates in C# - how to make code maintainable and readable?

I'm making a game, and it may have modal UI windows, like popover windows.
I encapsulated all the fiddling into my class and I just call one method to show such window on screen, for example a method to show a list of characters:
ShowCharactersTable(List<Character>list,
Action<Character>didSelectCharacter, Action<bool>didCancel)
Example in use:
ShowCharactersTable(someList, delegate(Character selectedCharacter) {
// code that runs after you picked a character
, delegate(bool didCancel){
// code that runs after you cancelled selection
});
This is fine. Everything is transparent and easy to use. But I get into trouble as soon as I need to nest this. For example, on character list I have few buttons on each character cell, so I need to provide delegates for that. This gets complicated. I also might need to show another modal window on top of that, with a call like this:
ShowActivitySelector(List<Activity>activitiesToShow,
Action<Activity>didSelectActivity,
Action<bool>didCancelPickingActivity);
And when I select activity I might need to show Alert if something goes wrong, like here:
ShowAlert(string alertText, Activity<bool>didAccept,
Activity<bool>didCancel);
So now, to call a simple table of characters I need to write a 3 page long method with nested delegates. Does not sound like fun. How can I modularize this and make easier/more maintainable?
I don't want to couple my interface to my model, as I will need to show those lists, selectors and alerts from many different parts of my game with different parameters.
How can this be fixed and what do I do about this?

Different functionality in a single object situationally (Xna, Menusystems, and general C#)

I've been wondering a lot how to have an object act different situationally.
To clarify what I'm wondering:
I want to make a menusystem, and I want to have a "button" class. But the button should behave different depending on what kind of button it is.
One button may close to program, another may start the game, a third may enter settings.
(I was thinking of parsing methods as arguments, but then you still have to write a lot of different methods somewhere in your code)
How do you do this with OOP in mind? I could hardcode the very basic functions of a simple menu using enums and switchcases, but I would want to know if it could be avoided.
I want to avoid things like delegates because games aren't eventbased in such fashion, and also switch-cases, large if/else statements because they are really ugly.
Is there a way to make objects behave like this?
What are other alternatives to making menus, trying to avoid the switch-cases for the commonly used enum. (Not disallowing enums)
I want to avoid things like delegates because games aren't eventbased in such fashion
Aren't they, though? A button click is an event, regardless of whether or not it's a game or a web application. It's by definition something happening that you'd like to react to, such as a button press. What happens when a button is clicked should be loosely coupled from the button in the UI, for the reasons you already encountered (large switch/if-elses are a pain) among others. A C# event field seems like the perfect fit, for this particular case anyway.
At some point, you create the settings button, somewhere, somehow. Why not wire up the event there? Something along the lines of:
class Button
{
public Button(string label) {}
public event Action Clicked;
}
class Program
{
public static void Main(string[] args)
{
var settingsButton = new Button("Settings");
settingsButton.Clicked += () =>
{
// open settings view
};
}
}
I'd avoid things like inheritance for this problem as it adds unnecessary complexity for the wrong reasons. You should (probably) use inheritance if the overriding class changes or supplements the behavior of the class it extends (a logical progression would be object extended by Component extended by Button extended by ToggleButton) but not to create a class hierarchy that's very much tied to how your UI is built up. If you change settings access to a dropdown menu instead of a button press, you don't want to be tied to a SettingsButton class; you want to be simply able to change which event triggers the desired behavior, in this case pulling down the dropdown menu.

What to do when a form's class becomes too large?

Currently my main form has a ton of event handlers because there are a lot of controls. It is very similar to a paint application. I have condensed it down quite a bit and I am sharing event handlers whenever possible but the class is still around 1,000 lines of code. I realize that may not be much to all of you but it is considerably larger than the rest of my classes.
I have refactored a lot of code to other classes but all those event handlers still increase the line count by a large amount. I also started using region blocks to separate event handlers in to groups and that is working rather well but I still would like to know SO's opinion on the matter as to best organize a large amount of form event handlers.
Edit: So I've been using partial classes and I must say, I don't really like them that much. I'm not sure what to do at this point.
I may go back to using region blocks as I'm not sure user controls will help my problem at all. Honestly I did not mind the region blocks that much. That class was the only place I used them and it organized the different sections of the code quite nicely (Menu Event Handlers, Toolstrip Event Handlers, Drag and Drop Support, et cetera).
Still, if anyone still has any other ideas or would like to elaborate upon any posted thus far I'd be more than appreciative as I am still looking for a better solution to this problem.
1000 lines of code is nothing, and that should not be the basis for refactoring your code. Refactor your code where it makes sense; not just because a class contains more lines of code than your other classes. Some classes will require more code than others, and that's perfectly okay.
That being said, if it makes sense you can divide the controls into logical sections, and put them in user controls. Make sure that there is a good justification for doing so though, because otherwise you'll only be convoluding your code base.
I must remind you again though, don't split your code up just to reduce the lines of code.
You could either split the functionality into separate classes (e.g. creating UserControls like Ed has suggested), or think about using partial classes (where one class can be split among many files). I have found partial classes handy to group together related chunks of code, when the "main" class file is getting to large. Sometimes this is the first step in refactoring those chunks of code into separate classes and/or controls.
It's hard to make a concrete recommendation without seeing the code, but those are some of your options.
If you haven't already (you don't mention it) I would split out the various individual controls into UserControls. You can handle all of the events from within the UserControl class and only expose those events that the parent form must absolutely handle. These will likely be small in number and will drastically reduce the responsibilities of your main form.
For example, each tool button could live inside of a UserControl. The canvas control can maintain and instance of the tools control and so on. You can keep creating the composite controls where each upper layer becomes less complicated and most of the actual logic is handled below it.
I would suggest of using more OOP solution. Do not add UserControls, as you add more *complexity*. Let's try to maintain complexity you already have, but make things more clear, cause this is what really you're asking for, I believe.
DI like. In practise if you need to handle a lot of events for a lot of contorls, create ControlManagers, which accepts in ctor the control and subscribes to its events.
So for every control you will have it's own manager.
Advantages:
Clear separated code in different classe, so easy recognizable in case of problems and my be more clear from architectural point of view.
You don't break down your architecture with a lot ot delegated events between tons of controls and subcribers (one subscriber per control)
Sure you will need organise, by the way, the data flow between different classes. But it's by my experience, haven't to be a big problem.
EDIT
An example pseudocode:
UserControl1 mycontrol1; UserControl2 mycontrol2;
public class MyControl1Manager {
public MyControl1ManagerFor1 (UserControl1 uc1) {
//subscribe to events of uc
// here all code to handle events
}
public MyControl1ManagerFor2 (UserControl2 uc2) {
//subscribe to events of uc
// here all code to handle events
}
}
and somewhere in code:
MyControl1ManagerFor1 controlManager1 = new MyControl1ManagerFor1 (mycontrol1);
MyControl1ManagerFor2 controlManager2 = new MyControl1ManagerFor2 (mycontrol2);
Something like this.
Hope this helps.
Once I had a form that became really big. It showed the same information in many various ways. To reduce number of code in single file I used an approach similar to UserControls. All the GUI elements were placed on the form, but their initialization and handlers were maintained by helper classes. They were equivalents of UserControls, but without GUI interface. These classes were initialized in main form's constructor:
SideViewHelper sideView = new SideViewHelper(parentForm, gridControlMaster, gridControlDetail, buttonSubmit);
All the logic that handles the gridControl events, button events are handled inside the helper class.
After the initialization the main form (parentForm) may change state of many UI items by single call of ViewHelper's method.
These classes are created for this only form and are as lightweight as possible.

Categories

Resources