Search Unity

UI Graph – A Menu System For Unity (formerly Canvas Flow)

Discussion in 'Assets and Asset Store' started by Pelican_7, Aug 30, 2019.

  1. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    ui-graph-banner.png

    UI Graph – A Menu System For Unity
    UI Graph is a powerful menu system for Unity that lets you easily create complete user-interfaces by building them visually in a flow graph.
    • Build each screen of your user-interface using native Unity UI.
    • Visually create the flow of your user-interface in a node-based editor.
    • Construct complex multi-screen layouts by nesting screens.
    • Customize the transitions between screens using an extensible animation system.
    https://uigraph.xyz

    Trailer

    Screenshots
    Screenshot 1.png
    Screenshot 2.png
    Screenshot 3.png
    Screenshot 4.png

    Available now on the Asset Store. Online documentation is available at https://uigraph.xyz.

    Feel free to post feedback, suggestions, or support requests in this thread. Alternatively, you can email support@pelican7.com.

    -andy.
    Pelican 7.
     
    Last edited: Sep 4, 2019
    Gekigengar, ikemen_blueD and Jos-Yule like this.
  2. kennyd-itp

    kennyd-itp

    Joined:
    Jan 13, 2014
    Posts:
    30
    This looks tremendous! Being able to manage and present (mobile) UI in a decent way is important in a lot of the apps we make, and we've had to write quite a bit of code to support it. This looks like it could be a great addition to our tooling, will check it out asap.
     
  3. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Thanks a lot @kennyd-itp! Don't hesitate to get in touch if you have any questions.
     
  4. f1chris

    f1chris

    Joined:
    Sep 21, 2013
    Posts:
    289
    Do you support joysticks or gamepad ?
     
  5. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Not quite by default. The standard container view controllers (and your own view controllers) use native Unity UI components, which can be used with joysticks and gamepads but you'll need to configure that yourself. This can just be a case of setting your UI components' Navigation field to Automatic, depending on your set up.

    For example, in the Assassin demo the Options screen's buttons each have their Navigation field set to Automatic, allowing them to be navigated with a controller. In the video below I'm using a Playstation controller to move through the options.

    https://drive.google.com/file/d/1E6GkzYcK6KhLR_c0C0VHr_C0ZLcP_fnH/view?usp=sharing
     
    Jos-Yule and f1chris like this.
  6. JeBuSBrian

    JeBuSBrian

    Joined:
    Mar 3, 2013
    Posts:
    14
    Is there any drag 'n' drop functionality available in this system?
     
  7. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Not by default. UI Graph is a menu system for creating the flow of your user-interface. Each individual screen is built with native Unity UI, so if you have a drag and drop system implemented in Unity UI, you can use it in your menu.
     
  8. boysenberry

    boysenberry

    Joined:
    Jul 28, 2014
    Posts:
    347
    In the quick start instructions after the point where the Tab Bar Canvas Controller is added I notice the labels read Blue and Yellow. Mine read: BlueCanvasController and YellowCanvasController. How do I change the labeling for the tabs? I did not see anything in the instructions.

    Thank you, great system so far!
    Boysenberry
     
  9. boysenberry

    boysenberry

    Joined:
    Jul 28, 2014
    Posts:
    347
    I figured it out and adjusted the canvas controller titles.
    Great product!
     
  10. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Thanks a lot @boysenberry!

    Yep, you can adjust each canvas controller's title in its inspector (select the Scriptable Object), as you found. By default the Tab Bar Canvas Controller uses the canvas controller's title for its corresponding item label.

    Edit: Added a note to the Quick Start regarding the title labels.
     
    Last edited: Nov 4, 2019
    boysenberry likes this.
  11. sinzer0

    sinzer0

    Joined:
    Aug 29, 2013
    Posts:
    148
  12. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Hi @sinzer0,

    I've not worked a massive amount with Curved UI but I have had another user asking about Curved UI and UI Graph together, and as far as I have tested, yes it does.

    UI Graph's UI Canvas workflow still uses a Canvas component as before so you can still use Curved UI with that. As with Canvas Flow, I believe Curved UI still requires that when instantiating children (presenting screens in our case), you call its AddEffectToChildren() method. UI Graph, however, doesn't have the same hooks as Canvas Flow, so invoking this method will be slightly different. Whereas before we could call AddEffectToChildren()in the storyboard callbacks, we now need to call it on a per canvas controller basis.

    Now, I think the best and most performant solution would be to add the CurvedUIVertexEffect component to each game object that requires it in the canvas controller's view prefab itself (i.e. at build time), if Curved UI allows this. That way, at runtime you aren't having to do any work in finding and adding the component to the relevant objects upon instantiation (which AddEffectToChildren() is doing). You could perhaps write an editor script that does something similar to AddEffectToChildren() in the editor to automate this for yourself.

    Alternatively, if you want to do it at runtime, similar to before, you could call AddEffectToChildren() in the canvas controller's ViewWillAppear method. You'd need to get a reference to the CurvedUISettings object, which would be placed on the canvas window. One way of doing this could look something like:

    Code (CSharp):
    1. public class CurvedCanvasController : CanvasController
    2. {
    3.     protected override void ViewWillAppear()
    4.     {
    5.         base.ViewWillAppear();
    6.         CurvedUI.CurvedUISettings settings = View.GetComponentInParent<CurvedUI.CurvedUISettings>();
    7.         settings.AddEffectToChildren();
    8.     }
    9. }
    (You could make your other canvas controller's inherit from CurvedCanvasController so you don't have to write this in each of them individually.)

    Hope that helps!
    Andy.
     
    sinzer0 likes this.
  13. boysenberry

    boysenberry

    Joined:
    Jul 28, 2014
    Posts:
    347
    Hello,

    I am having trouble getting my initial Canvas Controller (on the graph) to transition off when a new canvas is presented. Any canvases after the first are getting the dismiss transition, but not the initial canvas.

    Is there a way to have the initial canvas use an animation transition?
    Right now I have 2 Sequence presenters, one for my initial canvas linked in it's scriptable object that is a fade in/out for present/dismiss setup as to/from respectively and a second on the secondary canvases that does a slide/fade in and out.
    The secondary animation transitions work just fine, but the initial canvas never seems to be dismissed.

    Thank you,
    Boysenberry Payne
     
  14. f1chris

    f1chris

    Joined:
    Sep 21, 2013
    Posts:
    289
    How do you save selected values to playerprefs ( by example a bunch of On/Off ) ?

    Any mechanism built-in to set them to their previous state when you re-enter the menu ?

    Thx
     
  15. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Hi @boysenberry. When presenting a second canvas controller, your initial canvas controller isn't 'dismissed' as such. It is simply hidden by its 'presented view controller'. If you ensure the second canvas controller's opaque flag is selected, UI Graph will hide the second canvas controller's 'presenting view controller' (the initial canvas controller) after presentation.

    When dismissing, you can't dismiss the window's root view controller, but if you wish to do this you can dismiss the entire window with its dismiss method - https://uigraph.xyz/api/Pelican7.UI...sWindow_Dismiss_System_Boolean_System_Action_.

    I hope that helps!
     
    boysenberry likes this.
  16. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Hi @f1chris. There is no built-in mechanism but you can use the canvas controller's ViewDidLoad method to set your switches to the desired value stored in PlayerPrefs.
     
  17. Carpe-Denius

    Carpe-Denius

    Joined:
    May 17, 2013
    Posts:
    812
    Somehow, in 2019.3 (both old and new project), I need to uncheck "ignore reversed graphics" on every GraphicRaycaster to get input.
     
  18. sinzer0

    sinzer0

    Joined:
    Aug 29, 2013
    Posts:
    148
    I noticed there were no scripts for container view controllers generated when creating the container asset, for example the stack controller.

    Is that by design?

    Basically what i am trying to do is have an empty canvas controller with a script that watches for an event such as the player selects a unit then the script calls the correct transition. I dont want the empty canvas controller to disable when it transitions and thus I was thinking a stack controller would work but now I don't see how to have its own script like the normal canvas controller.
     
  19. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    That's odd... Thanks for the heads up.
    Yes, this is by design. You create instances of the built-in containers and use them as-is. You are of course free to create your own custom container canvas controllers (a container canvas controller is simply defined as any canvas controller that embeds child canvas controllers).
    Hmm, could you simply have a normal Monobehaviour script that does this? You can then place this script on a game object in your stack canvas controller's view. As you pointed out, being in a parent canvas controller view, this script would not be disabled.

    On receiving a game event, such as "select unit", your script can invoke the relevant transition, such as "Push Canvas Controller X". This tutorial - https://uigraph.xyz/manual/guides/canvas-controller-reference-from-mono-behaviour.html - may be of interest to you. It explains how you can configure a MonoBehaviour in your view to reference the owning canvas controller (your Stack Controller). For example, something like this:

    Code (CSharp):
    1. public class ListenForGameEvents : MonoBehaviour
    2. {
    3.     private StackCanvasController stackCanvasController;
    4.  
    5.     // Add this method to the Canvas View Owner Bindings' On Bound To Owner event in your stack controller's view prefab.
    6.     public void Configure(CanvasController canvasController)
    7.     {
    8.         stackCanvasController = canvasController as StackCanvasController;
    9.     }
    10.  
    11.     // e.g. Invoked by your 'player selected unit' event.
    12.     public void OnPlayerSelectedUnitEvent()
    13.     {
    14.         stackCanvasController.PerformGraphTransitionWithIdentifier("Push Select Unit Canvas Controller");
    15.     }
    16. }
     
    sinzer0 likes this.
  20. sinzer0

    sinzer0

    Joined:
    Aug 29, 2013
    Posts:
    148
    Sorry in advance if this is not a ui graph issue, I am probably missing something obvious.

    I cant get unity to play nice with the rendering order of ui elements with ui graph like it normally does and I have an issue with a background image covering anything dynamically added via ui graph stackviewcontroller.

    I have a gamecontainer controller and the first game object is a background image. After that I have empty game object with a graphable embeed component. In the graph I have configured a StackViewController to go into that gameobject. Its worth noting this appears to not be an issue with a normal canvascontroller only the stackviewcontroller.

    So the problem is the background image covers anything added into the stackviewcontroller even though the image is at the top of the hierarchy and rendered first.

    Here is a screenshot of my prefab https://www.dropbox.com/s/ksvnm1nfntk4ywi/Screen1.PNG?dl=0

    Any idea what I am doing wrong? I'm on latest unity 2019.2.16
     
  21. Carpe-Denius

    Carpe-Denius

    Joined:
    May 17, 2013
    Posts:
    812
    stackcontroller.Pop (true, () => { controller.PerformGraphTransitionWithIdentifier ("Transition", this); });

    results in a message that a transition is currently active. How do I pop something from stack and push something else after that?
     
  22. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Hi @sinzer0.

    Hmm, so the StackController is embedded into the SelectedItem transform... It should be on top of the BackgroundImage in that screenshot as the stack controller will be placed inside this transform. I'm not sure what the issue could be here. For context, when using an embed component, UI Graph will simply place the loaded canvas controller under the embed's transform and then resize the canvas controller to fit its parent.

    Is it possible for something else to be the issue here? For example, could the SelectedItem transform be being resized incorrectly causing it to not appear? Or perhaps there is something on the background image affecting the drawing order, such as a canvas group with a modified sorting order or a custom shader?

    Hi @Carpe-Denius. I would expect you to be able to do that so I believe this is a bug.

    To free you up in the meantime, you can resolve this issue by moving a line in the source code. In the file ViewController.cs (UI Graph\Runtime\View Controller System\Generic Core\View Controller), move line 584 to before the callbacks are invoked on line 581. For example, this code...
    Code (CSharp):
    1. var context = t.Context;
    2. OnTransitionDidFinish?.Invoke(t, completed);
    3. context.OwnerViewController.DidPerformChildTransition(t, completed);
    4. context.OwnerViewController.OnDidPerformChildTransition.Invoke(t, completed);
    5. context.OwnerViewController.childTransitions.Remove(context.Identifier);
    Becomes:
    Code (CSharp):
    1. var context = t.Context;
    2. context.OwnerViewController.childTransitions.Remove(context.Identifier);
    3. OnTransitionDidFinish?.Invoke(t, completed);
    4. context.OwnerViewController.DidPerformChildTransition(t, completed);
    5. context.OwnerViewController.OnDidPerformChildTransition.Invoke(t, completed);
    I have reproduced the issue in a test project and verified that the above fix allows me to perform Push/Pop in the completion handlers.

    Hope that helps!
     
  23. Meatloaf4

    Meatloaf4

    Joined:
    Jul 30, 2013
    Posts:
    67
    Hey just wanted to pop in and say I finally had a chance to really take a hard look at UIGraph. Haven't exactly put it through it's paces just yet but hot damn it looks to be a really well thought out next step to CanvasFlow.

    Just wanted to say great work! Can't wait for any additions and updates to to the framework! If it wasn't for the requirement on 2019 I would have already pulled it into some of my projects.
     
  24. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Awesome, thanks a lot @Meatloaf4! :)
     
  25. Jos-Yule

    Jos-Yule

    Joined:
    Sep 17, 2012
    Posts:
    285
    Was playing in 2019.3.x, with the New Input system, and trying to get UI Graph to work with it. Changing the Event input to use the new input solved all the errors, but clicking on items didn't trigger any actions. I didn't spend much more time on investigations, but was wondering if/when "new input system" support would be added, and/or if there is a "quick fix" -- not looking for either, just wondering if/where on the timeline this stuff would be. Thanks!
     
  26. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Hi @Jos-Yule. I haven't had a chance to try the new input system yet, so thank you for the heads up.

    My expectation though is that once a UI Canvas is configured to use the new input system, Unity UI should "just work" with it, so I'm surprised that didn't trigger any actions. Did you replace the StandaloneInputModule in the scene with the InputSystemUIInputModule (https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/UISupport.html)? That was the only step that I was expecting to be required.

    You could actually change the default Canvas Window to a prefab of your own (in the settings), which could have a different input module on it, if you wished. That way, anytime you created a new Canvas Window, you'd get one configured for using the new input system (assuming that's the only change required).

    -andy.
     
  27. sinzer0

    sinzer0

    Joined:
    Aug 29, 2013
    Posts:
    148
    Not sure if this is a bug or if there is another way to get around this, but I ran into an issue using the SceneTransitionCanvasController.

    The problem was the scene being loaded was running but it was not marked active so I found that anything I dynamically instantiated in the newly loaded scene (using Instantiate) ended up in the temporary loading ui scene since it was marked active. I changed the LoadSceneAndMakeActive to mark the newly loaded scene active right away after load and the problem no longer occurs. Using unity 2019.3.1



    Code (CSharp):
    1.  private IEnumerator LoadSceneAndMakeActive(string sceneName)
    2.         {
    3.             // Load the new scene.
    4.             AsyncOperation loadOperation = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
    5.             yield return loadOperation;
    6.  
    7.             Scene loadedScene = SceneManager.GetSceneByName(sceneName);
    8.  
    9.             // Make the newly loaded scene the active scene.
    10.             SceneManager.SetActiveScene(loadedScene); // changed to set active scene right after load
    11.  
    12.             // Allow derived classes to perform any additional loading requirements.
    13.             yield return PrepareLoadedScene(loadedScene);
    14.  
    15.             // Make the newly loaded scene the active scene.
    16.             //SceneManager.SetActiveScene(loadedScene);
    17.         }
     
    Last edited: Feb 25, 2020
  28. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Thanks a lot for the bug report @sinzer0 :)
     
  29. tsggp

    tsggp

    Joined:
    Mar 27, 2018
    Posts:
    2
    Hello, is there a way to get to the same node but from 2 different nodes? Like if there's node A where you can go to B and C depending on something the player does and then both B and C go to a 4th node, D but without duplicating it. I don't think it's clear how to make something like this work.

    Kinda like this:
    A(starting point)
    B(screen if player state is something)
    C(screen if player state is something else)
    D(screen where the player has to go to after B or C)

    so it would be something like
    A->B
    A->C
    B->D
    C->D
    where -> represents a transition
     
  30. Pelican_7

    Pelican_7

    Joined:
    Nov 25, 2014
    Posts:
    189
    Hi @tsggp. Apologies for the delay in responding. Hope you're well at this troubled time.

    Generically speaking, you cannot create multiple logical flows to the same screen. What this means in this instance is that two separate screens cannot both hold a Present transition to the same screen in the graph. The reason for this is that it can become ambiguous when creating upstream (dismissal) transitions back up this multi-path flow.

    Therefore the simple solution I'd suggest is to have two instances of screen D in the graph and connect to the first from screen B, and the second from screen C.

    Alternatively, if you need just one instance of screen D in the graph (perhaps it has a large number of screens extending from it that you only want to set up once), you should be able to setup screen D and onwards in a separate graph. Then from screens B and C you can do the following to instantiate and present the second graph:

    Code (CSharp):
    1. public class CanvasControllerB : CanvasController
    2. {
    3.     // Drop a reference to the graph in the inspector.
    4.     public GraphResource graphResource;
    5.  
    6.     public void OnSomeEvent()
    7.     {
    8.         // Instantiate an instance of the graph.
    9.         var graph = new CanvasGraph(graphResource);
    10.  
    11.         // Instantiate the graph's initial view controller - this would be CanvasControllerD in your case.
    12.         CanvasController initialViewController = graph.InstantiateInitialViewController();
    13.  
    14.         // Present it.
    15.         Present(initialViewController);
    16.     }
    17. }
    -andy.
     
  31. Arkuni

    Arkuni

    Joined:
    May 30, 2013
    Posts:
    13
    I bought the asset, read every single word of the documentation and played around with the assassin demo.

    Amazing work on the documentation. Great use of native built components. Non-intrusive and flexible.

    For future releases, I hope to see a more refined graph editor. Especially...

    * Rest zoom button
    * Non-blur text after zooming
    * Multi-select
    * Moving parent will also move children
    * Smaller nodes that shows a fixed "properties" pane when selected (check out NodeCanvas on great compact design)

    A big complaint right now is that the demo scenes are constantly crashing the unity editor. I am running 2019.3.7 and I can only fiddle around with the assassin demo for a few minutes before unity asks me to send a crash report. It makes me afraid to implement the system into my game.

    Question: How do I get data from my scene outside of the canvas flow? Let's imagine that I have a inventory canvas controller, and I want it to pull its data from my player character who is a MonoBehaviour doing God knows what somewhere in my scene. In the documentation, it seems that data is pulled from other assets, but since my data is sitting on top of some silly Monobehaviour that can't be referenced by the canvas controller, how would I solve my problem?
     
    Last edited: Mar 30, 2020
unityunity