gbsrethsrg

Fungus is a free Unity plugin available on the Asset Store. You just need to download the plugin and import it (to save hard-drive space, uncheck the “FungusExamples” folder in the import window) to get up and running. There are three things Fungus is great for: text-based conversations, simplified level scripting, and easy animated menus. The first two are great and all, but its latent menu functionality is surprisingly simple and useful.

Because Fungus has simple functionality to move objects, and perform basic visual animation for objects and UI, it’s perfect for simple menus. For Where the Heart Is I created a basic menu with fade-in and out animation, with simple left and right movement entirely through Fungus (with a small script to connect the buttons to Fungus blocks). Each menu element is stored in a UI Panel relevant for the game’s Main, Options and Credits menus, so I only need to animate the parent panels to get the hard parts done.

To get started, we need our Fungus blocks to be executed by clicking on UI elements. We need to make a quick script that can process that functionality (I’ve added an additional function for Trigger-based execution, too). All of the crucial elements are embolden:

using [default unity stuff];
using Fungus;

public class ExecuteFungusBlock : MonoBehaviour 
{
 public Flowchart <Flowchart you will hook up from the inspector>;
 public String <The Fungus block you want to execute (input in the inspector)>;

// For menu elements
 public void OnClick()
 { 
 ExecuteFungusBlock( <The Fungus block you want to execute (input in the inspector)> );
 }

 // For Trigger Elements (requires a trigger and for the player to have a RigidBody)
 public void OnTriggerEnter(Collider other)
  { 
  ExecuteFungusBlock(<The Fungus block you want to execute (input in the inspector)>;
  }

}

(please excuse the awful formatting that WordPress can’t fix)

Use this script to activate your Fungus blocks from either UI or Trigger Volumes. You can also use the ExecuteBlock() function anywhere you need.

UI Setup

For UI scalability and consistency, we need to make sure the Canvas and our Panels are set up so that they will fill the screen appropriately.

Canvas

Setting up the Canvas in Unity is the first step to add and position the panels. I created a default Canvas, but within the Canvas Scaler component, I changed:

  • UI Scale Mode = Scale With Screen Size
  • Reference Resolution = X-1280 & Y-720
  • Screen Match Mode = Match Width or Height
  • Match = 0.5 (will scale the Canvas size to the best vertical and horizontal fit in equal measure)

canvassc

The canvas should scale with different aspect ratios comfortably, and remain the same relative size no matter the screen dimensions.

UI Panels

Now, each of the panels will be the parents of objets stored within it, effectively grouping elements into their menu groups. Each Panel requires the following customisations:

  • The alignment of the Panel will be Centre, Middle.
  • Within Rect Transform, its Pos X, Pos Y and Pos Z will be 0.
  • The panel will be 1280 pixels wide, and 720 pixels tall (matching the canvas resolution).
  • Remove the Image component
rect
What your Rect Transform component should look like

With these set up, feel free to add your UI elements, and set them as children to their corresponding parent object in Unity’s heirarchy.

Variables:

Element Positions:

Fungus has a Variable fly-out window which stores variables you can change on the fly. You can create Floats, Booleans, Integers, Strings, Animators, AudioSources, Colours, GameObjects, Materials, Objects, Sprites, Textures, Transforms, Vector2s and Vector3s. That’s a long list, so you’re spoiled for choice in the items you can manipulate and control through Fungus.

ydtg
My final Variables menu

To keep the positions of elements identical, I created three Vector3 variables called EnterPosX, StayPos and ExitPos, and their position and behaviour are:

    • When a text element enters, it can start in EnterPos- I use a Vector 3 of (80, 0, 0)
    • All text elements will move to StayPos – I use a Vector 3 of (40, 0, 0)
    • When a text element exits, it will move to the ExitPos- I use a Vector 3 of (0, 0, 0)

These three variables can be stored in a Vector3, and referenced by all of the menu elements. We will use these to move the UI panels in and out.

Booleans

A boolean is a simple true/false variable, used for handling on/off functionality. Because Fungus doesn’t support C#’s similar but more versatile Enumerators, each panel will need its own boolean to determine which is currently active. I just made a Credits, Settings, and Main Menu boolean variables.

variables
The final list of variables

Menu Behaviour

Behaviour:

With the panels positions defined, we need to lay out the rules that the menu system abides by:

    • When an element moves between positions, the player cannot interact with it
    • While an element moves to the ‘Exit’ position, it will fade out to 0% from 100% opacity.
    • When an element moves from the ‘Entry’ position, it will fade to 100% from 0% opacity
    • When an element is completely faded out, it will become inactive (effectively turning it off)
    • When the player presses “back”, the UI should go to the previous panel in the menu hierarchy while still completing its animations

Block Breakdown:

With our behaviours defines, we can start creating our blocks. I split the elements into a few distinct blocks:

“Play Game”

    • Will play the game and doesn’t lead into a menu

“Quit Game”

    • Will quit the game and doesn’t lead into a menu

“Enable Menu Elements”

    • One of these is needed for each of the panels. This block will turn on each of the elements in a menu individually (unfortunately you can’t use “Set Intractable” for a panel, just each UI element with a “Button” component). This block will be used when turning on menu elements after the panel’s animation is finished

“Disable Menu Elements”

    • One of these is needed for each of the panels. This block will turn off each of the elements in a menu individually (Like before, you can’t use “Set Intractable” for a panel, just each UI element with a “Button” component). This block will be used when turning off menu elements before animating them

“Enter Menu Element”

    • One of these is needed for each of the panels. This block will house the logic for moving  and fading the panel into the view, as well as enabling or disabling it, and calling relevant functions in other objects

“Dismiss Menu Element”

    • One of these is needed for each of the panels. This block will house the logic for moving and fading panels out of the view, setting its active state, and calling relevant functions in other objects

“Back”

    • Only one of these is needed in the Flowchart. The block will check which of the panels is currently active, and execute the “back” functionality for the corresponding panel

Block Scripting:

“Enable Menu Elements”

    • For every element with a Button component, set UI/Set Intractable to True.

dbvfhdh

“Disable Menu Elements”

    • For every element with a Button component, set UI/Set Intractable to False

ybdrtydh

“Enter Menu Element” 

  1. Prepare the panel: (to ensure that no errors will prevent the panel from being in the right position, let’s reset them anyway)
    1. Use UI/Fade UI to set the Panel’s opacity to 0%, with a Linear curve.
    2. Use iTween/Move To  to move the Panel’s position to EntryPosition in 0-sec with a Linear Curve
    3. Set this panel’s corresponding boolean to true.
  2. Animate the panel
    1. If this menu panel transitions from a previous panel (ie: going from the main menu to an options menu) then use Flow/Call to call that Panel’s Exit Menu Elements block so it will exit at the same time as the current enters. Ensure that the panel’s Call Mode is set to Continue finishing its current block instead of Stopping or Waiting Until Finished.
    2. use iTween/Move To to move the object to StayPosition in 1-sec with a Quad-in Quad-out curve, with Wait Until Finished set to False.
    3. use UI/Fade UI to fade the panel to 100% opacity in 1 second, using a Quad-in Quad-out curve.
  3. Enable the menu
    1. Use Flow/Call to call the Enable Menu Elements block (thereby enabling the user to interact with the menu

 

svgrtshrth
What your Enter Menu block may look like

“Dismiss Menu Element” 

Dismiss Menu Element is called by a Block which is currently entering the Canvas.

  1. Prepare the panel:
    1. Set this panel’s corresponding boolean to false.
    2. Use Flow/Call to call the Disable Menu Elements block
  1. Animate the panel
    1. Use iTween/Move To to move the object to ExitPosition in 1-sec with a Ease in out Quad curve, with Wait Until Finished set to False.
    2. use UI/Fade UI to fade the panel to 0% opacity in 1 second, using a Ease in out Quad curve.
srtnryjntdynsfdbt
What your Dismiss Menu block may look like. This one is from my Dismiss Settings Menu block

When everything is hooked up in the Flowchart window and the inspector

“Go Back” 

This one is easy – check which of the bools is true, and call the right Dismiss block:

goback

How do I Pause and Unpause the game?

This one is a little tricky. Because you need animations to work for the menu to make sense, you can’t just set Time.timeScale to 0 and freeze time. Instead, you should think about exactly what behaviour is important for your game. For Where the Heart Is, we don’t need to “pause” the game per-se, we only need to disable the player’s movement and looking functionality, and prevent any scripts from triggering based on input.

So, we added a Script to the player which Fungus invokes, that disables all interactive Functionality:

dngfbasdfgvfv
Separate functions for pausing and unpausing
dsfhsdfdbfv
use this within functions to ignore any input after return;

Then, you can invoke whichever function by using Invoke Method:

thrge
You can also input method parameters as well. Being able to invoke functions is seriously useful
full
What your final group of functions may look like. I have a few other blocks that these are connected to, hence the lines off-screen.

Benefits:

  • Easier diagnosis of scripting errors, you can see which blocks are running in the Flowchart Window, and which command in the inspector
  • Easy to see and understand event sequences and logic as opposed to the abstract raw code it runs off.
  • For me at least, fungus is way faster than coding by hand (abstract concepts like programming can be a challenge when only focusing on the lower-level logic) so for some tasks Fungus is a godsend

Limitations

Weird issues:

  • Some errors are hard to diagnose – like only a particular number of tweens can be in effect at any given time, but this isn’t communicated clearly beforehand
  • Fungus should yell at you for having two flowcharts in the scene, or the error that an object can’t be found should actually tell you: “The block <block> in Flowchart <Flowchart> cannot be found”. I make dumb mistakes, okay?

Feature limitations:

  • You can’t create more variable “types” or substitute valuables on the fly, so I can’t use one block for a variety of the similar objects – each object requires the same logic
  • The breadth of scripting ability within fungus is limited, and the user can’t use more advanced C# operations to perform the tasks they need (but the user can still invoke functions in other scripts, so you can’t switch entirely to Fungus for your scripting (and maybe that’s a good thing!))

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s