Click or drag to resize

Demo Project: Maniac Manfred

Maniac Manfred Title

The "Maniac Manfred" demo project, is a full articy:draft project we were shipping with articy:draft together for some time now and even reference it in our online help and in some of our product videos. For the release of the ArticyImporter plugin, we updated it and created an unity game project forming together a complete playable Point & Click Adventure. Both projects (articy and unity) are a good way to show you how you can create a full game using articy:draft and bringing it to life in unity using the ArticyImporter plugin. This guide will give you an overview over both projects and explain some of the design choices.

Please understand that this is not an introductory tutorial for unity or adventure game creation in general. This guide expects you to have a good understanding of unity and a basic understanding of articy:draft and its template system. This is also not meant to explain every detail, instead explain the bigger picture and give you a good idea where to start digging into both projects. Especially the unity script code is fully documented and should give you a good idea whats going on.

Setup and Installation

Before we can start you need to make sure you have all the necessary applications and projects downloaded:

  • articy:draft X
  • Unity 2021.3 or higher.
  • The "Maniac Manfred" articy:draft demo project, which you can get here.
  • The "Maniac Manfred" unity demo project, which you can get here.

You only need the articy:draft Maniac Manfred project, if you want to make changes to the project and export them to see how the unity project and the plugin behaves.

Overview

The main goal of "Maniac Manfred" is to show you how you can use articy:drafts feature for planing, designing and creating a game and then use Unity and the ArticyImporter Plugin to bring it to life.

But it should be noted that "Maniac Manfred" is by no means a final game, or the one and only way how you could create an adventure. In fact the code misses a lot of performance optimization for the sake easier understanding. For a different game, even for a different adventure a complete different design in articy and unity would probably make more sense.

"Maniac Manfred" features:

  • Simple Point and Click game
  • Inventory System with item combination
  • Interactive branching dialogue system
  • Multiple scenes
  • Moral system and different endings
  • Localization support

"Maniac Manfred" was not build to win any prizes or awards. It lacks a lot of polishing, and is better to be considered a prototyp or proof of concept. But we still hope you have some fun playing it and while learning it and digging through the projects you get some ideas how to create your games!

Locations and Clickable Zones
Maniac Manfred Editor Location Cell

Lets start with the locations, as this is probably the first thing you will see. For Maniac Manfred, every location represents a single scene . In the first scene, Manfred(our Protagonist) finds himself inside a cell of what appears to be an asylum.

Each scene is build in articy using a Location, and every clickable element in it is created using Zones. The designer also placed some Links in the scene to easily jump to the referenced object for example the Corridor location is linked on the Door. While not used in the unity project, those links are a good way for the designer to keep track and make navigation quicker. The location also contains Image Objects for non static elements in the scene. For example the Therapist might not be in the cell all the time.

While this setup is nothing special yet, lets look at the custom template that is used on every clickable zone

Maniac Manfred Editor Template Therapist
Template Data for the Therapist Zone

In a nutshell: The template for our clickable zones contain all the game logic and information that allows the player to interact with the zone, therefore we called the template "InteractionZone".

This might look intimidating at first, so lets look at it piece by piece:

  • Click Condition: A script that is called to test "Is the player allowed to click on this zone?" If it returns false, the player cannot interact with this zone at all.
  • On click instruction: A script that just contains code that needs to be executed once the player clicked on this zone.
  • If condition is true: A reference slot, containing an articy object, like a dialogue.
  • If condition is false: A reference slot, similar to the one above. Used when the user is not allowed to interact with the zone, but we want to trigger something, for example to let the protagonist say that the door is closed and he needs a key.
  • Cursor if condition is true/false: Two similar enumerations, describing which Mouse Cursor should be used while the cursor hovers over the zone.
  • Item to interact with: A reference slot containing an optional item that can be used with this zone.
  • Interaction condition: Before the player can use the beforementioned item on this zone, this script must be true.
  • Link if item is valid/invalid: Called when the user used the correct/invalid item with the zone, usually a dialogue telling that the combination worked/failed.
  • Instruction if item is valid: A script that is called when the user used the correct item on the zone.

As you can see the template ends up pretty straight forward. The player can interact with a zone using the mouse or an item, and depending on if he is allowed to do it, we have fields that represent triggered code or articy objects. And the object could be a dialogue, that would trigger a new dialogue; a Location, that would trigger a scene change or even an Item that would trigger the acquisition of the item.

Now that we have seen how the template looks, how do we use it in unity?

Without going to much into detail how the scene was created (don't worry we look at it later) lets see how this zone looks in unity:

Maniac Manfred Unity Game Object Therapist

Two noteworthy components are here, the first is the polygon collider otherwise we could not click this zone and the second is a custom script called "ClickableZone".

This script contains the logic that takes all the fields inside the zones template, and bring it to life, lets see a small excerpt from the actual Pointer Click event.

C#
public void OnPointerClick(PointerEventData eventData)
{
    // [...] stripped Item logic to make this example easier to read

    ArticyObject outcomeObject = null;

    // lets check if we can click, and then we follow depending on the outcome
    var result = articyZone.Template.ZoneCondition.ClickCondition.CallScript();
    if (result)
    {
        // we were allowed to click it, so we call its click instruction
        articyZone.Template.ZoneCondition.OnClickInstruction.CallScript(sceneHandler);
        // and get its target outcome object
        outcomeObject = articyZone.Template.ZoneCondition.IfConditionTrue;
    }
    else
    {
        // so the condition was valid, so we can start the dialog or move to the given scene
        outcomeObject = articyZone.Template.ZoneCondition.IfConditionFalse;
    }
    // if we have an outcomeObject we pass it to the scene handler
    if(outcomeObject != null)
        sceneHandler.ContinueFlow(outcomeObject);
}

As you can see, we call the condition script once the player clicked, gather the outcome object and pass it to the scene handler, that takes care of starting a new dialogue or changing the scene.

Dialogues and Scene Transition
Maniac Manfred Unity Canvas

For the dialogues we use a simple unity UI using panels and text. This whole "Dialog Widget" can be toggled to be hidden when currently no dialogue is displayed. Besides the text and the speaker image, it contains an area that is used to host the different choices in a branching dialogue.

Lets look again at the Pointer Click script in the previous chapter. The Script calls a method on the SceneHandler which is another custom script on one of our game objects, that looks something like this:

C#
public void ContinueFlow(IArticyObject aObject)
{
    // if the object is a location, we load a new level
    if (aObject is ILocation)
    {
        var loc = aObject as ArticyObject;
        // we want to leave, so we trigger our transition effect
        transition.TransitionOut();
        // the new scene name is the same as the technical name of the supplied location
        // we start a coroutine because we want to delay the loading of the level a bit for the transition to finish
        StartCoroutine(LoadNextLevel(loc.TechnicalName));
    }
    else if(aObject is IEntity)
    {
        // if the object is an item, that usually means that the item is given to the player.
        var item = aObject as Item;
        if(aObject is Item)
        {
            ArticyDatabase.DefaultGlobalVariables.SetVariableByString(item.Template.VariableBinding.VariableName.RawScript, true);
        }
    }
    else if (aObject != null)
    {
        // if we are about to open a new dialog, we better stop the user from using any items
        inventory.StopUsingItem();
        // we enable the dialog ui
        dialogShown = true;
        dialogWidget.SetActive(dialogShown);
        // and we assign the object as the start node
        flowPlayer.StartOn = aObject;
    }
}

Depending on the type of the object, we load a new level, add an item or let the ArticyFlowPlayer try to deal with it.

Branches

Maniac Manfred Unity Branch

As mentioned before we use a vertical list of buttons for every dialog option. Every dialog option is a button stored in a prefab called dialogBranch. This button is made out of a Text hosting the dialogue fragments MenuText and an image for a potential icon for an item. Also attached to it is a custom script called BranchChoice.cs with the main purpose of storing all information about the represented branch; initializing the visualization (like the text and the image) and also implementing the Click handler that just passes the stored branch back into the ArticyFlowPlayers Play(Branch) method.

Everytime the flow player will display a new dialogue fragment, it will call OnBranchesUpdated(IListBranch) to tell us about new branches. The SceneHandler.cs contains the implementation of those FlowPlayer callbacks. Inside the OnBranchesUpdated() method we clear the list of any current buttons and create a new button from the dialogBranch prefab. We also have a Close button, used once we see that no branch points to a dialogue fragment, indicating a finished dialogue.

Inventory management
Maniac Manfred Editor Items

For Maniac Manfred we needed a simple inventory system, that was also capable of combining items with each other and using items with zones. For the simple act of posessing an item, we used global variables. So every item has a global variable:

Maniac Manfred Editor Variables Inventory

This makes it very easy to check in scripts if a user has an item or not, but what about combining items? Now every Item is also an entity with a specialized template called Item lets see how that looks:

Maniac Manfred Editor Template Banana
  • Variable: The variable that represents this item
  • Valid Combination: An object that can be combined with this item.
  • Combination result: The object that is created when combined with the Valid Combination.
  • Link if success/failure: A reference to an object to start a dialogue for example.

The inventory itself is managed in the game object called Inventory and the script Inventory.cs. It adds a listener to the inventory global variables and creates a new UI element for the inventory when the player gets an item aka the variable is set to true. It also manages "grabbing" or using an item, effectively attaching it to the pointer, until used (or right clicked). The "attaching" of the item is done using an image that follows the pointer while an item is used.

In the UI the inventory is just a horizontal list of instantiated prefabs of simple controls. Each item in the UI has a script called ItemUI.cs attached to it. This script contains the logik of using and combining items:

C#
public void OnPointerClick(PointerEventData eventData)
{    
    if (!inventorySystem.IsUsingItem)
    {
        // if we weren't using an item already, we now want to use the clicked item
        inventorySystem.StartUsingItem(this);
    }
    else
    {
        // lets see if we can combine items

        // first we get the item the user is currently holding
        var heldItem = inventorySystem.CurrentlyUsedItem;

        // and then we ask its template if the clicked item is a valid combination
        if (heldItem.Template.ItemCombination.ValidCombintation == this.RepresentedItem)
        {
            // combination is allowed and usually ends in a new item
            var result = heldItem.Template.ItemCombination.CombinationResult;
            if (result != null)
            {
                var item = result as Item;
                // now we rely on the inventory system to work properly: We set the global variable, representing the new item that resulted from combining
                // the two items, to true. Effectively this will get the listener called inside the Inventory and that will take care of adding the new item
                ArticyDatabase.DefaultGlobalVariables.SetVariableByString(item.Template.VariableBinding.VariableName.RawScript, true);

                // both old items must now be removed, because we consumed them to create the new item
                inventorySystem.RemoveItem(heldItem);
                inventorySystem.RemoveItem(thisRepresentedItem);

                // finally, if we have a potential new dialog, we tell the scene handler about it
                sceneHandler.ContinueFlow(heldItem.Template.ItemCombination.LinkIfSuccess);
            }
        }
        else
        {
            // sometimes trying to combine items trigger a "That won't work" dialogue.
            sceneHandler.ContinueFlow(heldItem.Template.ItemCombination.LinkIfFailure);
        }
        // no matter what, we stop using the item
        inventorySystem.StopUsingItem();
    }
}
Image Elements
Maniac Manfred Editor Template Crowbar Image

While every scene has at least one big screen filling Background Image it could also contain smaller images that are dynamically enabled depending on different game states. As usual we have a template for those image objects, containing a script that tests if this image should be shown or hidden. And our game object in unity representing those contains a very simple custom script called SceneImageElement.cs, which calls the condition on the template and sets the sprite renderer accordingly.

C#
spriteRenderer.enabled = imageObject.Template.DisplayCondition.ShowMeIf.CallScript();
Advanced: Creating Scenes from Locations
Maniac Manfred Unity Scene

You might be wondering how those scenes can contain references to the articy objects; how their polygon colliders are exactly placed like the zone polygon inside the articy:draft location. Of course you could recreate the scenes by hand in the unity editor. But for maniac manfred we wanted to show a very different use case that is also possible using the ArticyImporter plugin. All your data is available right after the import which allows us to write code that is run in the editor that uses the data. In this case we created a LocationCreator for our scenes, first lets see where to find it and how to use it:

Maniac Manfred Unity Select Scene

First select the scene object inside the GameManager game object in your scene.

Maniac Manfred Unity Create Location

You just select a Location using the browse button and then hit the big button. And your new scene will automatically be created and is ready to go.(Hint: you might have to zoom to the scene game object by double clicking it in the hierarchy)

When you click the button the location creator takes the location you have set and creates new game objects for every object inside the location. Depending on the type of the object in the location (zone, image, link) the location creator will attach different unity components to those created game objects (polygon collider, sprite renderer, articy references).

See Also