a visual modelling environment for statecharts and...

104
MASTERS THESIS A visual modelling environment for Statecharts and Class Diagrams in Unity Author: Glenn DE J ONGHE Promotor: Prof. Dr. Hans V ANGHELUWE A thesis submitted in fulfilment of the requirements for the degree of Master of Science: Computer Science in the Modelling, Simulation and Design Lab Department of Mathematics and Computer Science June 1, 2015

Upload: others

Post on 16-May-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

MASTER’S THESIS

A visual modelling environment forStatecharts and Class Diagrams in Unity

Author:

Glenn DE JONGHE

Promotor:

Prof. Dr. Hans VANGHELUWE

A thesis submitted in fulfilment of the requirementsfor the degree of Master of Science: Computer Science

in theModelling, Simulation and Design Lab

Department of Mathematics and Computer Science

June 1, 2015

Page 2: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Abstract

So far the usefulness of the visual modelling formalism Statecharts and Class Diagrams (SCCD) hasonly been shown in academic settings. The goal of this thesis is to demonstrate the practicality ofthe formalism to the software industry. As artificial intelligence in games are an interesting field toexperiment with, we decided to use the formalism to model the behaviour of Non-Player Characters(NPCs) in the commercial game engine Unity.

Since visual modelling works best in combination with a modelling environment, we also createa visual editor as development tool inside Unity. To develop this, we again make use of SCCDand simultaneously show that the formalism can be used for multiple purposes ranging from singlefeatures to entire applications.

1

Page 3: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Samenvatting

Tot zover werd de bruikbaarheid van het visueel modelleer formalisme Statecharts and Class Dia-grams (SCCD) alleen nog maar getoond in academische contexten. Het doel van deze thesis is om denuttigheid van het formalisme aan te tonen aan de software industrie. Omdat artificiële intelligentiein games een interessant gebied is om met te experimenteren, hebben we besloten het formalisme tegebruiken om het gedrag van Non-Player Characters (NPCs) te modelleren in de commerciële gameengine Unity.

Omdat visueel modelleren het beste werkt in combinatie met een modelleer omgeving, creëren we ookeen bewerkingsprogramma als ontwikkelingstool in Unity. Om deze tool te ontwikkelen maken weopnieuw gebruik van SCCD en tonen daar tegelijk mee aan dat het formalisme gebruikt kan wordenvoor meerdere doeleinden gaande van kleine functionaliteiten tot volledige applicaties.

2

Page 4: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Contents

1 Introduction 10

1.1 Environment Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.1.1 A Custom Build Architecture . . . . . . . . . . . . . . . . . . . . . . . . . 11

1.1.2 AI Competition Architectures . . . . . . . . . . . . . . . . . . . . . . . . . 11

1.1.3 Commercial Game Engines . . . . . . . . . . . . . . . . . . . . . . . . . . 12

1.2 Outline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

1.3 Unity Game Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

1.3.1 Behaviour Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

1.3.2 User Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

1.4 Unity Editor Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

1.4.1 Editor Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

1.4.2 Custom Inspectors and Property Drawers . . . . . . . . . . . . . . . . . . . 16

1.4.3 OnGUI and GUI Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.4.4 Editor Code Management . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2 The SCCD Formalism 20

2.1 Constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.1.1 Basic State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.1.2 Transition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.1.3 Composite State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.1.4 Parallel State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.1.5 History State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.1.6 Enter and Exit Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.1.7 Class Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

3

Page 5: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

2.2 Concrete Syntax: SCCDXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

2.2.1 Class Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

2.2.2 Statechart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

2.2.3 Executable Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

2.2.4 State Referencing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

2.3 Runtime Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

2.3.1 Object Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

2.3.2 Association Referencing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

2.3.3 Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

2.3.4 Game Loop Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

2.3.5 OutputListener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3 Visual Editor 36

3.1 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

3.1.1 Class Diagram Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3.1.2 Statechart Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3.2 Risk Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3.3 Iteration 0: Model Everything . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

3.4 Iteration 1: The First Step to a Middle Layer . . . . . . . . . . . . . . . . . . . . . . 43

3.5 Iteration 2: Rendering Elements Independently of the Model . . . . . . . . . . . . . 48

3.5.1 Drag and Drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

3.5.2 Modal Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

3.6 Iteration 3: Extended Middle Layer . . . . . . . . . . . . . . . . . . . . . . . . . . 58

3.6.1 Widget Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

3.6.2 Group Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

3.6.3 Modal Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

3.6.4 Editor Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

3.6.5 Event Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

3.7 Iteration 4: Proper Event Generation . . . . . . . . . . . . . . . . . . . . . . . . . . 69

3.8 Iteration 5: Final result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

3.8.1 Model Generation, Compilation and Saving . . . . . . . . . . . . . . . . . . 71

3.8.2 The Modelling of Transitions . . . . . . . . . . . . . . . . . . . . . . . . . 72

4

Page 6: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

4 Example Case : Tank Wars 86

4.1 User-Controlled Tank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

4.2 Computer-Controlled Tank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

5 Conclusion 97

5.1 SCCD improvements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

5.1.1 Conditional Action Statements . . . . . . . . . . . . . . . . . . . . . . . . . 98

5.1.2 Else Target . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

5.1.3 Exiting a Parallel State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

5.1.4 Association Mappings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

5.1.5 Private Ports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

Bibliography 103

5

Page 7: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

List of Figures

1.1 The menu displaying a custom entry to open the editor window implemented in CodeSample 1.2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2 The editor window implemented in Code Sample 1.2 after its only button got clicked. 16

1.3 The inspector of a game object which has a script of type SCCDScript defining itsbehaviour. The custom inspector for SCCDScript shows the attached model file pathand a button to open the SCCD editor. . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.1 Two basic states connected by a transition originating from the initial state on the left. 21

2.2 On the right we can see the composite state B encapsulating the two basic states C

and D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.3 A parallel state Y with two orthogonal regions A and B. Upon initialization both innerstates K and D become active. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.4 When the transition to the history state is fired, the state of A will be restored to itslast recorded state. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.5 This figure illustrates the relation between classes in a class diagram and the state-charts that describe their behaviour. . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.6 Illustrating the use of the conflict attribute of a state. When state A is active and eventi is cast, the attribute will decide which transition needs to be fired. . . . . . . . . . . 28

2.7 Diagram illustrating the different simulation methods. . . . . . . . . . . . . . . . . 34

3.1 The modal window shown upon dropping a state onto multiple other states. . . . . . 57

3.2 The complete class hierarchy of SGUI widgets that got created during the creation ofthe visual editor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

3.3 An example model created in the SCCD editor defining just two classes and one as-sociation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

6

Page 8: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

3.4 The statechart editor window with at the top a toolbar, on the right the properties paneland on the left the actual canvas with all the available types of states displayed. . . . 72

3.5 The visual representation of the Transition class’ statechart. . . . . . . . . . . . . . . 79

4.1 A screenshot of the demo game. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

4.2 The class diagram of the model defining the user-controlled tank’s behaviour. . . . . 89

4.3 The statechart of the Tank class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

4.4 The statechart of the Turret class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

4.5 The layered architecture used to model the tank NPC. . . . . . . . . . . . . . . . . . 91

4.6 The statechart of the Radar class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

4.7 The statechart of the EnemyTracker class. . . . . . . . . . . . . . . . . . . . . . . . 92

4.8 The statechart of the PilotStrategy class. . . . . . . . . . . . . . . . . . . . . . . . . 93

4.9 The statechart of the AttackPlanner class. . . . . . . . . . . . . . . . . . . . . . . . 93

4.10 The statechart of the PathFinder class. . . . . . . . . . . . . . . . . . . . . . . . . . 94

4.11 The statechart of the TurretSteering class. . . . . . . . . . . . . . . . . . . . . . . . 95

4.12 The statechart of the TurretControl class. . . . . . . . . . . . . . . . . . . . . . . . . 96

7

Page 9: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

List of Code Samples

1.1 Example implementation of custom behaviour for a game object. . . . . . . . . . . . 141.2 An implementation of an editor window with a label and a clickable button. . . . . . 151.3 The implementation of the custom inspector of SCCDScript. . . . . . . . . . . . . . 172.1 The SCCDXML concrete syntax of Figure 2.1 . . . . . . . . . . . . . . . . . . . . . 282.2 The SCCDXML concrete syntax of Figure 2.2 . . . . . . . . . . . . . . . . . . . . . 282.3 The SCCDXML concrete syntax of Figure 2.3 . . . . . . . . . . . . . . . . . . . . . 292.4 The SCCDXML concrete syntax of Figure 2.4 . . . . . . . . . . . . . . . . . . . . . 293.1 The detection of which element is being focused without the use of software modelling. 393.2 The part of the SCCD model defining the Element class for iteration 0. . . . . . . . . 393.3 Updated version of the Element class where the update event is used to display visual

representations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413.4 A non-modelling approach for determining which element in a hierarchy gets clicked. 423.5 Iteration 1 implementation of the StateChartEditorWindow class. . . . . . . . . . . . 433.6 The SCCD editor model during iteration 1. . . . . . . . . . . . . . . . . . . . . . . . 453.7 The catchClick() method of the CanvasItem class. . . . . . . . . . . . . . . . . . . 483.8 The public interface of EditorCanvas. . . . . . . . . . . . . . . . . . . . . . . . . . 493.9 The partial implementation of StateChartEditorWindow during iteration 2. . . . . . . 493.10 The calculateContainer() method used to calculate a rectangle for an element that

encompasses all its children. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513.11 The main model file defining the statechart editor in the final result. . . . . . . . . . 513.12 The transition in the statechart of the State class that gets triggered when the state

should connect with a new parent. . . . . . . . . . . . . . . . . . . . . . . . . . . . 523.13 The transition in the statechart of the Canvas class acting on the disconnect_child event. 533.14 The transition in the statechart of the Canvas class that connects a state to a new parent. 533.15 The functions that take care of the creation, rendering and closing of a modal window. 543.16 The middle layer class ModalWindow used to display a modal window. . . . . . . . . 553.17 The delegate function used to display the modal window for dropped states. . . . . . 57

8

Page 10: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

3.18 The doOnGUI() method of SGUIWidget which will call OnGUI() if the widget isenabled. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

3.19 The OnGUI() method of the SGUIVerticalGroup class. . . . . . . . . . . . . . . . . 613.20 The drawModalWindow() method which constructs the same modal window as in

Code Sample 3.17 but by using SGUI. . . . . . . . . . . . . . . . . . . . . . . . . . 613.21 The state that is active during the time the state drop modal window is presented to

the user. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623.22 The final version of SGUIEditorWindow’s OnGUI() method. . . . . . . . . . . . . . 643.23 Iteration 3 implementation of SGUIButton’s OnGUI() method. . . . . . . . . . . . . 653.24 The doLeftMouseDown() method of SGUIWidget which simply generates a correct

SCCD event. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663.25 The part of the SCCD model defining the Button class for iteration 3. . . . . . . . . . 673.26 The implementation for SGUICheckbox’s OnGUI() method. . . . . . . . . . . . . . 683.27 The implemtation of the SGUIEvent class. . . . . . . . . . . . . . . . . . . . . . . . 693.28 The implementation of catchMouseDefault() providing a default way of catching

mouse events. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693.29 The final implementation of SGUIButton’s OnGUI() function. . . . . . . . . . . . . 703.30 The file generated by the SCCD editor upon saving the model shown in Figure 3.3. . 713.31 The part of the Canvas constructor that determines which states and transitions need

to be loaded. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 733.32 The state that actually creates the Transition instances that need to be loaded. . . . . 743.33 The state entered by the Canvas instance when a transition is being created. . . . . . 753.34 The state entered by State instances when a transition is being created. . . . . . . . . 783.35 The Transition class of the SCCD model for the statechart editor. . . . . . . . . . . . 794.1 The script that enables SCCD modelled behaviour when attached to a game object. . 875.1 The transition from the statechart editor that is responsible for removing a state from

the canvas. It makes use of a hack to only raise an event if a certain condition holds. . 985.2 A possible syntax we suggest for supporting conditional transition targets. . . . . . . 995.3 Example statechart showing the error currently present in the simulation of parallel

states. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

9

Page 11: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

1Introduction

In previous research[Jon14] the general purpose visual modelling formalism SCCD was created com-bining Harel Statecharts[Har87] and UML Class Diagrams[OMG05]. Moreover, a concrete textualsyntax SCCDXML was defined and a compiler was developed that generates executable code fromSCCDXML models for different platforms. In this thesis our goal is to show what the formalismis capable of and how it could be further improved in the context of modelling the behaviour ofautonomous entities in modern computer games.

As in [Wuy12][JK07][DKVV11] we believe that games, and more specifically the behaviour of Non-Player Characters(NPCs), are an interesting field to experiment with visual modelling. For this reasonwe will create a similar tank game as in [Wuy12] and use SCCD to model the behaviour of both theNPC tank and the player tank. In order to do this we first look for an ideal environment to develop thisgame in and whether it is feasible to incorporate compiled SCCD models. Furthermore to facilitatethe design of SCCD models we will also build a visual editor environment for the formalism. Asapplications that heavily rely on user interactions are also a good use case for visual modelling, thevisual editor will be developed using SCCD as well.

1.1 Environment Selection

For the development and evaluation of game AI there are roughly three different types of environ-ments/architectures that can be used:

10

Page 12: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

• A custom built game engine.• The architecture provided by an AI competition.• An existing game engine.

1.1.1 A Custom Build Architecture

The first option has already been explored several times in for example [Jon14] and [Wuy12]. It isprobably the easiest option as the structure of the compiled models can be kept in mind during thedevelopment process of the game environment allowing for smooth integration. A major drawbackhowever, is that it is hard to convince the game industry that visual modelling is a feasible approachfor the development of NPCs. This is because even though the results might be positive for a custombuilt architecture, there is no guarantee that it will work properly with commercial games.

1.1.2 AI Competition Architectures

The second option, where the tools provided by an AI competition are used, is very interesting as theperformance of the resulting models can be evaluated against the many submissions by other contes-tants. Another advantage of an AI competition is that the architecture provided is usually designedspecifically to plug in custom AIs, so this might make the integration fairly easy. Furthermore, de-pending on the background of the competition, a good end result might draw the attention of the gameindustry.

The hardest part is actually finding an announced contest of which the final submission deadline hasnot yet passed. Unfortunately we did not find such a competition so we had to look into alreadyfinished ones of which the architecture is still available together with the best submissions to possiblytest our AI against. A list of the competitions we looked into:

• Tank Wars (EA) [Art05]• AI Challenge Ants (Google) [Goo11]• Capture The Flag (Guerilla Games) [AIG13]

In [JK07] Statecharts modelling was used to compete against the submissions of the Tank Wars com-petition of EA. They managed to beat the winner of the contest with their modelled NPC, but as theydid not compete in the competition itself (too late) they had access to the implementation of the win-ner and could tweak their model as much as needed. This would not have been the case if they enteredthe contest before the deadline and thus it is not guaranteed that they would have won. We would havethe same problem with our models and therefore the competition architecture does not seem to be thebest option to showcase SCCD’s capabilities.

11

Page 13: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

1.1.3 Commercial Game Engines

The third and final option is to make use of a commercial game engine. We believe that convincingthe game industry will work best by showing working examples in a widely used commercial gameengine. The engines we took into consideration are:

• Source (Valve) [Cor]• Unity (Unity Technologies) [Teca]• CryEngine (CryTek) [Cry]• Unreal Engine (Epic Games) [Inc]• Panda3D (Disney/Carnegie Mellon University) [Uni]

Unity and Panda3D are the most suitable with regard to integrating compiled models into the engine.However if we take into account commercial success and popularity, Unity is a clear winner. Further-more Unity has the option to extend the game editor interface with tools to improve the developmentprocess. This is ideal as we can build a SCCD editor environment right into Unity which makes thestep from pure textual programming to visual modelling a lot less difficult for people already familiarwith the Unity editor and its work-flow.

1.2 Outline

The remainder of this thesis will be as follows: This section will continue with a brief introductionto Unity game development in section 1.3 with specific attention to scripting and user input. Wethen finish the introductory section with an overview of the different methods Unity provides to builddeveloper tools in section 1.4.

Section 2 describes the visual modelling formalism SCCD that we will use to develop the visualeditor and to model the behaviour of NPCs. In section 2.1 the different constructs that the formalismoffers are explained using simple visual representations. section 2.2 then gives a detailed overviewof the concrete textual syntax SCCDXML and further explains this by recreating the visual examplesfrom the previous section using the concrete syntax. The section ends with highlighting the maincomponents of the SCCD runtime library as they are crucial for the interaction between differentclasses in the model and integration with the final application.

In section 3 the entire development process of the SCCD editor is described. It starts of with listingall the requirements followed by several risk analyses to see if the desired result is feasible to achievewith the Unity platform. The section finishes with the different iterations the application went throughto obtain the final result.

In section 4 a demo game is created where we actually make use of the SCCD editor to model both theuser-controlled character as well as the NPCs. We will look at how the SCCD editor integrates with

12

Page 14: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

an actual game and at how visual modelling can be used to create complex behaviour in an intuitiveway.

Finally, section 5 gives the conclusion of this thesis, contains suggestions on how to further improvethe SCCD formalism and shows possible directions for future work.

1.3 Unity Game Development

To give an idea of how developing a game in Unity works, we will look into the average (but sim-plified) work flow needed to create a game. When creating a new project, game developers normallystart out with just an empty scene. The first step is to then place a number of game objects into thisscene. These game objects usually contain meshes defining the shape of the object. This can rangefrom a simple cube to a complex mesh created in an external 3D modelling tool. Next, extra compo-nents should be added to the game objects specifying their visual appearance and how they interactwith the environment because at this point everything in the world is just static with a neutral look.Components that get commonly added include physics materials, textures, colliders but also sounds orother graphical elements such as lights. The type of component we are interested in the most howeverare behaviour scripts.

1.3.1 Behaviour Scripts

Scripts allow custom behaviour to be added to game objects. The way one modifies behaviour inUnity is by changing how objects react to certain game events. As Unity calls a specific method foreach event, one has to simply implement the function that corresponds to the event the object shouldreact to. For instance, Update() is the most commonly used function to implement any kind of gamebehaviour. This Update() function is called every single frame and is normally used to handle (amongother things) the user input which we will look into further in section 1.3.2.

Another popular function is the Start() function which gets called after the creation of the game objectand can be used for any form of custom initialization. One last example of the game events availableis OnCollisionEnter(). This function will get called when the game object collides with another gameobject, of which we will make use in the demo game in chapter 4. A complete list of all availableevents/functions can be found in the documentation of the MonoBehaviour class[Tecc] which is thebase class used to implement any behaviour for game objects.

1.3.2 User Input

Important to any game is the interaction of the user with the application. When executing a gamethe Unity engine does not generate any specific user input events, instead the application has to pollthe values of the specific user control of which the state is needed. For instance when a certainaction should be performed on pressing down the key "Y", the application should call the function

13

Page 15: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Input.GetKeyDown() every frame. This function will always return false, unless the specific key waspressed down in the period since the last frame. In Code Sample 1.1 we see what a script implementingthis behaviour looks like. The class inherits from MonoBehaviour and the Update() is implementedto access the state of the "Y" key in every frame.

using UnityEngine;

public class MyGameObjectBehaviour : MonoBehaviour {

void Start () {

//Used for any initialization.

}

void Update () {

if (Input.GetKeyDown(KeyCode.Y)) {

//Executed when ’Y’ is pressed down.

}

}

}

Code Sample 1.1: Example implementation of custom behaviour for a game object.

1.4 Unity Editor Extension

One of the main reasons we chose Unity as a platform is because of the ability to develop the wholeSCCD visual editor right inside Unity as a developer tool that integrates perfectly with the gameeditor. The benefits of this integration are that developers who want to use SCCD modelling for theirgames, do not have to install extra software and that they will already be familiar with a major part ofthe work flow. There are three[Tecb] different ways for developers to extend the Unity editor whichwe will highlight in the following subsections.

1.4.1 Editor Windows

The first method, editor windows are essentially custom windows that behave like any other userinterface element already present in the Unity editor. This means that the developer does not haveto take care of the positioning of the window and that the user can organize the components to hisliking. For instance the user could dock a custom editor window next to the scene view (as shownin Figure 1.2), so that only one of the two is visible at once and that the tabs can be used to changewhich window is visible. The user can also simply choose to have the window float around alone.

To create such a window, a class should be instantiated that inherits from the EditorWindow class.

14

Page 16: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

To then actually display items in the window the OnGUI() function should be implemented. Thisfunction works in a similar way to MonoBehaviour’s Update() function and gets called at least twiceevery frame.

using UnityEngine;

using UnityEditor;

public class MyWindow : EditorWindow {

[MenuItem("Window/My Window")]

public static void Init()

{

MyWindow window = (MyWindow) EditorWindow.GetWindow(typeof(MyWindow),

false);

window.title = "My Window";

}

public void OnGUI(){

if (GUI.Button (new Rect (10,10,100,20), "Click me"))

Debug.Log("I got clicked.");

GUI.Label (new Rect (10,40,100,20), "Label Text");

}

}

Code Sample 1.2: An implementation of an editor window with a label and a clickable button.

Important to note here is that Unity’s editor GUI makes use of a system called Immediate ModeGraphical User Interface[Kom]. In IMGUI a single widget function call performs everything thewidget would be expected to do at any single time, including the rendering of the visible widget andhandling user input. This is in contrast with the traditional method of Retained Mode GUI, wherewidgets are created in an initialization phase. From there they get displayed by the GUI engine andshould be queried to get any information out of them. Likewise messages and data need to be sent tothose widgets and when they are no longer needed they need to be cleaned up.

Unity’s GUI system works rather differently as a very small example in Code Sample 1.2 shows.Every frame a new call needs to be made to the Button function with the wanted position, dimensionsand label for the button as parameters. When the button is clicked, the function will return true andin our example this will result in a message being displayed in the debug console. The example endswith the creation of a simple label in the exact same way as the button was created. In Figure 1.2the window can be seen with on the right the console immediately after the "Click me" button wasclicked.

15

Page 17: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 1.1: The menu displaying a custom entry to open the editor window implemented in CodeSample 1.2.

Figure 1.2: The editor window implemented in Code Sample 1.2 after its only button got clicked.

The actual opening or instantiation of the editor window can simply be attached to for example a menuitem as is the case in the example in Code Sample 1.2 and pictured in Figure 1.1. Another option isto open the window upon clicking a specific button in a custom inspector, which brings us to the nexteditor extension method.

1.4.2 Custom Inspectors and Property Drawers

As Unity defines it in its documentation [Tecb], the inspector is an entity that displays detailed infor-mation about the currently selected game object, including all attached components and their proper-ties. Its main purpose is to define the functionality of any game object present in the scene.

Each property that is displayed in the inspector can be directly modified. Also the values of publicscript variables can be changed there without having to modify the script itself. The inspector caneven be used to change those values at runtime to experiment and find the best game play. In a script,if a public variable is defined of an object type like GameObject or Transform, any game object canbe dragged and dropped into the inspector to make the assignment.

In Figure 1.3 we see the inspector with as selected game object the player tank from our demo game ofchapter 4. Several components can be seen including a script. This script, called SCCDScript, is whatshould be added to any game object in order to make use of modelled behaviour. The inspector for thisscript shows a button to open the SCCD editor. This is what Unity calls a Custom Inspector as it allowscustom controls and functionality to be added to the inspector. Code Sample 1.3 shows how this is

16

Page 18: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 1.3: The inspector of a game object which has a script of type SCCDScript defining its be-haviour. The custom inspector for SCCDScript shows the attached model file path and a button toopen the SCCD editor.

implemented. All that is needed is a class inheriting from Editor, a CustomEditor attribute specifyingto which script this custom inspector belongs to, and finally an overridden OnInspectorGUI() methoddefining the controls to be drawn and its functionality.

using UnityEngine;

using UnityEditor;

[CustomEditor(typeof(SCCDScript))]

public class SCCDInspector : Editor {

public override void OnInspectorGUI()

{

SCCDScript target_script = (SCCDScript)this.target;

EditorGUILayout.LabelField("Model File:");

EditorGUILayout.SelectableLabel(target_script.xml_file);

if (GUILayout.Button("Open SCCD Editor"))

17

Page 19: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

SCCDEditor.ClassDiagramEditorWindow.open(target_script);

}

}

Code Sample 1.3: The implementation of the custom inspector of SCCDScript.

The last method of extending the editor is by defining property drawers. Instead of customizing acomplete inspector, these can be used to modify the look of just certain properties in the inspector. Acustom property drawer can be obtained by simply using attributes on scripts or by controlling whata specific serializable class should like. As we will not make use of this feature we will not go in tofurther detail about this.

1.4.3 OnGUI and GUI Events

The OnGUI() function of editor windows and custom inspectors does not get called just once ev-ery frame like Update(), but instead it gets called for every single event that occurred since the lastOnGUI() call, including a layout and paint event. The event currently being processed by OnGUI() isstored as an instance of Event in its only static member current. The GUI functions (like Button() andLabel()) will execute different code depending on the EventType of the current event, which is storedin the type property of the Event class. The most important types of events are the following:

• Layout : This is a special event that is sent prior to all other events and can be used to performany form of initialization. Furthermore Unity will use this event to determine the size andposition for controls that make use of the automatic layout features of the GUILayout class.This class contains the same functions as the GUI class we saw before, but without the needto pass a rectangle for the position and dimensions of the widget as Unity will calculate these.If one does not make use of the automatic layout features then this event can be disabled forperformance reasons.

• Repaint : This event is responsible for actually drawing all the controls on the screen.• Used : When Event.Use() is called, the type of the current event will be changed to Used so

that every control will ignore the event. This is useful if a control has processed a certain eventand does not want others to catch it.

• Mouse events : There are several types of mouse events that can occur: MouseMove, Mouse-

Drag, MouseDown, MouseUp and ScrollWheel. The index of the mouse button that actuallycaused the event is stored in the button property event. In case of a MouseMove, MouseDrag orScrollWheel event, the event property delta will contain how much the mouse or scroll wheelhas moved.

• Key events : When a key is being pressed or released the event type will be set to KeyDown orKeyUp respectively. The actual key being pressed or released is stored in the keyCode property

18

Page 20: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

of the event.

Other event properties include mousePosition and modifiers. The first will simply contain the positionof the mouse at the time of the event, while the latter will inform which modifier keys (such as theAlt, Ctrl and Shift keys) were pressed at the moment the event occurred.

1.4.4 Editor Code Management

All the code related to extending the editor should be placed in the Editor folder of the project as thiscode gets handled differently than the game code. Once a change to this code is detected, Unity willtry to compile and deploy the code. Any changes to the user interface will go into effect immediately.If a different developer wants to make use of the extensions, he simply has to place all the editorscripts in the Editor folder of the project he wants to use the tools for.

19

Page 21: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

2The SCCD Formalism

In this section the Statecharts and Class Diagram (SCCD) formalism is described. Large parts of thissection are taken from [Jon14] in which the formalism was first defined. In section 2.1 the differentavailable constructs are first explained using a neutral visual representation. This is followed by adetailed overview of SCCDXML, a concrete textual syntax for SCCD which we will use to design thevisual editor with, in section 2.2. Finally, in section 2.3 the main components of the SCCD runtimelibrary are highlighted as they are crucial for the interaction between different classes in the modeland integration with the final application.

2.1 Constructs

In this section the semantics of the different constructs that make up the formalism are discussed. Wecan split the constructs into two categories, namely those that make up a statechart and those thatencapsulate those statecharts into a class and ultimately into a class diagram.

The statechart constructs are based on the Statecharts formalism, first introduced by David Harel[Har87] in 1987. Statecharts is a visual modelling language that represents finite state automata withadded hierarchy, parallelism, history and broadcast communication. Harel created the formalism tobe able to describe large and reactive systems, as he believed such method was not available at thattime. We use the visual representation as proposed by Harel in his original paper [Har87], but keep inmind that this can slightly differ across different statechart editors.

20

Page 22: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

2.1.1 Basic State

The basic state acts as the main building block of a statechart and is represented as a labelled (rounded)rectangle. This can be seen in Figure 2.1 where two basic states are depicted. A statechart consistingsolely of basic states has to have exactly one default/initial state, this is represented by an incomingedge without source node.

Figure 2.1: Two basic states connected by a transition originating from the initial state on the left.

2.1.2 Transition

The two states are connected by a transition originating from the initial state on the left, with a labelof the form event[guard]/action. This means that upon reception of the trigger event c, the statechartwill transition from the initial state A to the state B if and only if the guard condition P evaluates totrue. Upon firing the transition, the action will be executed which in this case is the broadcast of the d

event. All three parts of the label are optional and thus it is for example possible to have a transitionwithout trigger event or guard condition (which is called an unconditional transition) or a transitionwith only a guard and no action.

2.1.3 Composite State

Composite states add a notion of hierarchy to Statecharts. They allow multiple substates to be groupedinto a single composite state. The composite state is also called the XOR state because when such astate is active, exactly one of its substates must be active. Each composite state should have exactlyone initial substate and transitions can occur at and between every level of the state hierarchy.

To illustrate this we look at the example in Figure 2.2. At initialization time only the state A isactive. Upon reception of the event h, the composite state B will be entered and consequently itsinitial substate C as well. At this point an event k can bring the statechart in the state configurationwhere B and its substate D are active, while an event f would bring the statechart back to its initialconfiguration where only state A is active.

2.1.4 Parallel State

Besides the XOR decomposition achieved by a composite state, also AND decomposition is availablein the Statecharts formalism. These are better known as parallel or orthogonal states and allow for

21

Page 23: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 2.2: On the right we can see the composite state B encapsulating the two basic states C and D.

parallelism to be modelled. Upon entering a parallel state, each of the orthogonal regions (substates)will become active. These substates are always non-atomic states that can in turn contain a statehierarchy.

Figure 2.3: A parallel state Y with two orthogonal regions A and B. Upon initialization both innerstates K and D become active.

A parallel state is represented the same way as a composite state, however its substates are depicted

22

Page 24: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

by dashed rectangles expressing that they are active at the same time. We see such a state in Figure 2.3labelled Y. Since this is the default state at the top level, this will directly be entered upon initialization.Consequently both substates A and B will be entered, which ultimately results in both inner states K

and D being active at the same time. When the transition of K to L is triggered by the event x, state D

will still remain active.

2.1.5 History State

A history state, which is depicted by a circle with the label H, adds memory to a component. Uponleaving a composite state, a possibly present history state will first save the current pseudo-state beforeadapting it. When afterwards that composite state gets re-entered through the history state, the statewill restore the retained state instead of using the default state.

Figure 2.4: When the transition to the history state is fired, the state of A will be restored to its lastrecorded state.

To illustrate this we see in Figure 2.4 a composite state A that has a history state and two sub-statesof which K is the default one. If an event x is received after initialization, the composite state willreside in sub-state L (i.e., L is now active). Upon firing the transition to state M, which is enabledby the event y, the current sub-state of A is recorded first. When this is followed by an event z, thetransition to the history state is taken resulting in A being reactivated and thus having the saved state,where sub-state L is active, restored.

Statecharts offers two types of history. The default shallow type only saves one layer of state in acomponent while the deep type saves all descendants of the component. The latter is represented byadding an ∗ to the state label giving H∗.

23

Page 25: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

2.1.6 Enter and Exit Hierarchy

With Statecharts it is possible to define actions that should be executed on either entering or exitinga specific state. When multiple layers of hierarchy are traversed on firing a transition, these actionsare executed in the intuitive way. The exit actions are executed first, from the deepest level up to thefirst shared parent between the source and target states. This is then followed by executing the enteractions in the opposite direction up to the target states.

2.1.7 Class Diagram

The top level of a SCCD model resembles a UML[OMG05] class diagram connecting different classesby associations. Each class can have methods and attributes just like in UML, but on top of that theformalism defines the reactive, possible timed behaviour of a class using a statechart. In Figure 2.5 wesee the class diagram from the perspective of a single class ClassD. We see that the class is associatedwith the classes ClassE and ClassF by named unidirectional associations and that a dashed edge withlabel «behaviour» is used to link the class to a statechart.

Figure 2.5: This figure illustrates the relation between classes in a class diagram and the statechartsthat describe their behaviour.

In the traditional Statecharts formalism, when casting an event, it was obvious that the scope of anevent was local to the statechart. Now with the addition of the class diagram, different levels of scopeare added. First of all the local scope naturally remains, i.e., when an event is raised with local scopeonly the source statechart will be able to act on it. Next we have a global scope that will make eventsvisible for all currently instantiated statecharts. Besides that an event can also be directly sent to astatechart using the narrow scope. Similar to the latter a special class diagram scope is present thatis used for management events like the creation of new instances (more about this type of eventsin section 2.3). Lastly there is also an output scope for attaching events to output ports in order tocommunicate with components outside of the model.

24

Page 26: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

2.2 Concrete Syntax: SCCDXML

SCCDXML is a concrete syntax for the SCCD formalism and is based on SCXML, which is a Stat-echarts variant developed by the W3C and is described in a working draft specification [BAA+13].SCXML specifies a textual syntax for Statecharts based on the eXtensible Markup Language (XML).SCCDXML adopts most of the SCXML specification and combines it with a simple XML represen-tation to describe class diagram constructs.

We will first look into the syntactic structures and corresponding XML tags, together with the avail-able attributes and children. We do this for the class diagram and statechart structures separately insubsection 2.2.1 and subsection 2.2.2 respectively. Next the different executable components avail-able are discussed in subsection 2.2.3. This is then followed by an explanation of the syntax forstate-referencing in subsection 2.2.4. Note that when talking about the context component (e.g., con-text statechart, context state) in the explanation of a certain tag, it refers to the component that certaintag belongs to.

2.2.1 Class Diagram

<diagram>

The outermost container element <diagram> represents a class diagram and should only occur oncein a model. It has two optional attributes name and author, both giving straightforward extra informa-tion about the diagram. The children nodes allowed for a diagram are :

• <description> : An optional child element enclosing the description of the model.• <class> : Defines a class as part of the diagram which should occur at least once.• <inport> and <outport> : Respectively defines an input port or output port for the diagram.

A port has as mandatory attribute name, which should uniquely identify the port. The ports canoccur zero or more times.

• <top> : An optional section for imports and definitions that need to be at the top of the gener-ated document and can be referenced anywhere in the diagram.

<class>

The <class> tag defines a class as part of a class diagram. It has a single flag attribute default whichdefines whether the class is the default class of the diagram or not. As a logical consequence one andonly one <class> in a single <diagram> should have a positive evaluating default attribute unless<diagram> contains only one <class> child. If the latter is the case then the single <class> will beused as default. The default class will be instantiated once when the diagram is created. The differentchildren available for a class are <relationships>, <method>, <attribute> and <scxml>. The latterrepresents the dynamic behaviour of the containing class in the form of a statechart.

25

Page 27: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<method>

The <method> tag defines a method as part of a class. The mandatory attributes for a method arename and type, defining the identifier and the return type respectively. The optional access attributedefines the access level of the method with as default value private. A method needs to have a <body>

child containing the code that should be evaluated when the method is called. For proper functioningthis code should match the target language of the compiler. Optional formal parameters can be definedwith the <parameter> tag and have the following attributes :

• name : The identifier of the parameter.• type : The type of the parameter.• default : The optional default value for the parameter.

Constructors and destructors are defined using the <constructor> and <destructor> tag respectively.They have the exact same attributes as methods aside from the type attribute.

<attribute>

The <attribute> tag defines a member attribute of a class. The mandatory XML attributes for theelement are name and type, which can be supplemented with the optional init-value attribute thatdefines an initial value of the attribute.

<relationships>

To define the different relations between the different classes in the diagram the <relationships> tagshould be used. To set up an association between one class and another (note the uni-direction of theassociation) the <association> tag should be used inside the source class with the target class set asvalue for the class attribute. Both the minimum and maximum cardinality of the association can beset using the min and max attributes respectively. The minimum defaults to zero while the maximumhas N as its default value meaning that any number of instantiations of this association is possible. Aname for the association should be defined using the name attribute. This name will be used whenaccessing associated instances as explained in subsection 2.3.2.

The <inheritance> tag defines a super class for the context class, from which it inherits. The classname of the super class should be set as the class attribute and a priority can be set using the pri-

ority attribute. In case of multiple inheritance the super class with highest priority will be inheritedfrom first. Naturally this priority attribute is only available for target languages that support multipleinheritance.

26

Page 28: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

2.2.2 Statechart

In this subsection we zoom in on the elements that construct statecharts. They are illustrated inCode Sample 2.1 to Code Sample 2.4 as the SCCDXML variants of the examples we saw in sec-tion 2.1. Note that the diagram information is skipped and thus the resulting XML segments are notSCCDXML compliant on their own. They should be added as child of a <class> element as we sawin subsection 2.2.1.

<scxml>

The <scxml> tag defines (the root of) a statechart and is simply a top level composite state sharingthe allowed children and attributes of the <state> discussed below. Only the id attribute is omittedfor the root element.

<state>

The <state> tag simply represents a state. This can either be a basic state or a composite statedepending on its position in the hierarchy. Each state should have an id that is unique at sibling levelso that each state in the statechart can be uniquely accessed XPath-like[CD99] using a sequence ofstate identifiers (see subsection 2.2.4 for a detailed explanation). For composite states, meaning thatthe <state> encloses other states, two other attributes are available.

First there is initial, which should be set to the identifier of the initial child state. Second there is theconflict attribute, defining how a transition conflict should be resolved. The possible values for thisattribute are :

• inner : The inner-most enabled transition will be fired.• outer : The outer-most enabled transition will be fired.• inherit : The conflict value of the parent will be used. Consequently this is an invalid value for

the root node.

The attribute defaults to inherit unless the context state is the root, then outer will be used. As thissetting is not available in most formalisms based on Statecharts (including SCXML), we will illustratethe behaviour of the attribute using Figure 2.6.

When state A is active and an event i is broadcast, both the transitions to B and Z become enabledbut only one transition is allowed to be fired. Since randomly picking a transition would result innon-determinism, either consistent behaviour could be enforced (which restricts the possibilities) orletting the modeller define what should happen in such a case. Because the latter is preferred, theconflict attribute has been added. If in the example that attribute of the root element would be set toinner, the transition to B would be fired. In case of the default outer, the transition to Z would befired.

27

Page 29: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 2.6: Illustrating the use of the conflict attribute of a state. When state A is active and event i iscast, the attribute will decide which transition needs to be fired.

The optional <onentry> and <onexit> children of a state hold executable content to be run uponrespectively entering and exiting the state. The elements that count as executable are discussedin subsection 2.2.3. Other allowed children for a state are <state>, <parallel>, <history> and<transition>.

<scxml initial="A">

<state id="A">

<transition event="c" cond="P" target="../B">

<raise event="d"/>

</transition >

</state >

<state id="B"/>

</scxml >

Code Sample 2.1: The SCCDXML concrete syntax of Figure 2.1

<scxml initial="A">

<state id="A">

<transition event="h" target="../B"/>

</state >

<state id="B" initial="C">

<state id="C">

<transition event="k" target="../D"/>

</state >

28

Page 30: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<state id="D"/>

<transition event="j" target="../A"/>

</state >

</scxml >

Code Sample 2.2: The SCCDXML concrete syntax of Figure 2.2

<parallel>

The <parallel> tag models parallel states and has the same children and attributes as the <state>

node, except for the initial attribute. This is logical since all substates become active, instead of justone, upon entering the context state.

<scxml >

<parallel id="Y">

<state id="A" initial="K">

<state id="K">

<transition event="x" target="../L"/>

</state >

<state id="L"/>

</state >

<state id="B" initial="D">

<state id="D">

<transition event="z" target="."/>

</state >

</state >

</parallel >

</scxml >

Code Sample 2.3: The SCCDXML concrete syntax of Figure 2.3

<history>

The <history> tag, representing a history state, only allows the <onentry> and <onexit> tags aschildren. Its attributes are limited to an id and a type attribute. The latter has as possible valuesshallow and deep, with shallow being the default one.

<scxml initial="A">

<state id="A" initial="K">

<state id="K">

<transition event="x" target="../L"/>

</state >

<state id="L"/>

29

Page 31: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<transition event="y" target="../M"/>

<history id="H"/>

</state >

<state id="M">

<transition event="z" target="../A/H"/>

</state >

</scxml >

Code Sample 2.4: The SCCDXML concrete syntax of Figure 2.4

<transition>

A <transition> tag defines a transition originating from its enclosing state. Its event attribute defineswhich event should trigger the transition and the cond attribute is a boolean expression that guardsthe transition. The target attribute defines the target state(s) of the transition; the syntax for this isdescribed in subsection 2.2.4. To accommodate for input events sent through ports from the diagram,a special attribute named port is available. When set, only matching events from the specified portcan enable the transition. For a transition to fire after a number of seconds, the after attribute shouldspecify a expression that evaluates to a numeric value. The after attribute can not be combined withany of the other attributes except target, which is the only mandatory attribute.

The children of a transition consist of formal event parameters and the different available executablecomponents (as listed in the next section) that should be executed when the transition is fired. Theparameters are formed with a <parameter> tag and have the same attributes as the formal parametersof a method i.e., name, type and default. When the transition is fired these formal parameters takethe value of the actual parameters supplied by the trigger event. These formal parameters can then bereferenced in the conditional statement and action code using their identifiers as local variables.

2.2.3 Executable Content

Executable content is a series of zero or more executable components wrapped in a containing ele-ment like <onentry> or <transition>. They are processed in document order. The main executablecomponent available is the <script> tag. Any text contained by it, will be interpreted as code of thetarget language to which the compiler is set. It is possible to obtain the behaviour of all the otherexecutable components solely by using the script component.

Text contained by a <log> component will simply be output to a console. The <assign> componentassigns a value to either a local variable, or to a member value if the SELF macro is used for referenc-ing. The value is obtained by evaluating the expression of the expr attribute, while the ident attributeindicates how to access the location to which the value needs to be assigned.

The <raise> tag allows for event generation. Its only mandatory attribute event defines the name of

30

Page 32: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

the event to be broadcast. As for the optional attributes, not all possible combinations are valid/al-lowed. The scope of the event, i.e., to which instances the event will be visible, dictates whichcombinations are valid and it can be explicitly set by using the scope attribute. Its possible values are:

• local : The event will only be visible to the context statechart.• broad : The event is broad-cast and thus visible for all instances.• output : The event will be send to an output port and is only valid in combination with the

output attribute.• narrow : The event will be narrow-cast, i.e., sent to certain specified instances only, and is only

valid in combination with the target attribute.• cd : The event will be processed by the object manager. See subsection 2.3.1.

If the scope attribute is not explicitly set, it will get a value depending on which of the other optionalattributes are set. If none of these has a value, the scope of the event will be local. Having a valuefor port, which defines the name of the output port to which the event should be send, will result inan output scope. Similarly the presence of the target attribute will enforce a narrow scope. This lastattribute takes a string as value that specifies which association links should be followed to find thetarget instance(s). This is explained in detail in subsection 2.3.2.

2.2.4 State Referencing

For the referencing of one or more states, as needed for example to specify the target of a transition,we created a syntax similar to XPath. To access a certain state, a location path should be formedthat ends in the wanted state. This location path is a string consisting of state identifiers separated byforward slashes (’/’), they present the hierarchy to be traversed before reaching the end state.

There is the option to use either a relative path or an absolute path. The latter will start traversing thehierarchy from the root and is denoted by prepending the path with a forward slash. The relative pathwill just start traversing the hierarchy from the context state. To go a level up in the hierarchy (i.e.access the parent of a certain state) two dots (’../’) should be used instead of a state identifier. Onesingle dot (’.’) will always refer to the current state in the path.

Specifying multiple target states can be done either by a comma separated list of state references, theuse of branching, or a combination of both. Branching is done by using brackets to define a commonsource location path. We illustrate this with the following example :

1) A/B/C, A/B/D, A/B/E

2) A/B(C,D), A/B/E

3) A/B(C,D,E)

31

Page 33: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

All three expressions denote the same three resulting states. For the third expression we start at thecontext state where the child with identifier A is selected. This is then followed by going down thehierarchy and looking for a child of A with identifier B. We then encounter a left bracket, meaningthat we branch off from the selected B node. Enclosed by the left bracket and an ending right bracket,we find a comma separated list of expressions. These expressions are now parsed to obtain (a subset)of the resulting states, using B as starting point instead of the original context state. This basicallymeans that our result set will contain the children of B with identifiers C, D and E.

Note that more complex expressions can be used inside the branches and even nested branching issupported. This can result in more complex expressions as shown below together with its branchlessequivalent :

1) A/B/C(D/E,F(G,H)), I/J

2) A/B/C/D/E, A/B/C/F/G, A/B/C/F/H, I/J

2.3 Runtime Platform

The execution/simulation of SCCD models is similar for every single model. To avoid the unnecessarygeneration and compilation of the duplicated execution code, SCCD provides a runtime library thatcombines all the entities needed for proper execution. Multiple simulation methods are supported bythis library, which are called runtime platforms. The wanted execution method should be supplied asparameter to the compiler, which will then generate the correct calls to the matching platform togetherwith the model-specific code.

2.3.1 Object Manager

The object manager is an always present entity responsible for managing the class diagram and co-ordinating all corresponding actions. This includes the creation and deletion of new instances andhandling the communication between them. Commanding the manager happens solely through eventsbut for some actions like narrow casting, this is abstracted away by the formalism. To directly mes-sage the manager, an event should be cast with cd as value for the scope attribute. The compiler willautomatically set the first parameter of such an event to be a reference to the sender, so that the objectmanager can reply to the caller if needed. What follows is an overview of the different events themanager acts upon, their parameters, and the replies the manager returns as response to them.

create_instance Upon receiving this event the object manager will create a new instance, if the classdiagram allows it. The first user-supplied parameter should be the name of the associationfor which a new instance should be created. Next, the wanted type of the instance shouldbe specified followed by any constructor parameters. If the creation succeeded, a reply event

32

Page 34: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

instance_created will be sent to the requester. As first argument the reply event will containan identifier that can be used to reference the created instance in the association. The secondargument is simply the name of the association for which the instance was created. The samearguments are sent with the instance_creation_error in case creation failed or was not allowed.

delete_instance The delete_instance event allows for the deletion of instances. The manager expectsthe supplied string argument to be an association reference (see subsection 2.3.2) referencingthe instance(s) to be deleted. All relations with the deleted instance(s) are removed as well,which implies that the deletion needs to conform to the class diagram.

start_instance This event will start the execution of the statecharts of the instances referenced by thesole association reference argument.

associate_instance When an instance is newly created it is not associated with any instance at all.For this reason there is the associate_instance event that makes it possible to associate instanceswith multiple other instances. The event expects two association references as arguments, asource path and a target path. The instance(s) found processing the first reference, will beadded to the association that results by processing the second. This implies that the secondreference can not have an index specified for the last association name. An instance_associated

event is sent back to the requester when the operation is successful and has the same parametersas the instance_created event.

2.3.2 Association Referencing

In order for an instance to contact certain other instances from the class diagram, for instance toperform a narrow cast, an XPath-like syntax has to be used to create an association reference. Suchreference is a string consisting of association names, optionally followed by a square-bracketed index,separated by forward slashes (’/’). They present which associated instances should be traversed toreach the requested instance(s).

2.3.3 Controller

The controller is the top level element and acts as an interface to the class diagram. It has access to allthe instances that make up the diagram through the object manager and takes care of the execution ofthe state charts. If the default instance needs any constructor arguments, these should by supplied tothe constructor of the controller. Each runtime platform is represented by a different controller classinheriting from a common base class. The interface of this base controller exists out of the followingmethods :

• start() : Starts the execution of the class diagram and thus of all present statecharts.

33

Page 35: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

• stop() : Ends the execution of the class diagram.• addInput(event_name, port[, parameters, time]) : Adds an input event to the diagram with the

specified arguments. Note that the supplied time is relative to the time the event gets added.• addInputEvent(event[, time]) : Adds an already created event with optional relative time.• addEventList(event_list) : Inputs a list of events.• addOut putListener(ports) : Creates and adds an output listener to the diagram and then returns

the reference.

2.3.4 Game Loop Platform

In this thesis we will make use of the Game Loop platform. The goal of this platform is to alloweasy integration of the generated code with games and game engines that make use of a game loopfor execution. The platform adds an extra method update() to the controller, which should be calledevery frame of the loop with as sole argument the time that has passed since the last call. This way thecontroller is able to execute the actions that should have happened during the last frame, resulting ina decent approximation of continuous time. Figure 2.7 illustrates the delayed processing of an eventat the beginning of the next frame. The platform supports both fixed and variable time steps.

Figure 2.7: Diagram illustrating the different simulation methods.

34

Page 36: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

2.3.5 OutputListener

Receiving output from a compiled diagram is done by attaching output listeners to the correct ports.By calling the addOut putListener() method on the controller with an array of ports, a listener getscreated and returned. The diagram will attach all output for the listed ports to this listener and thusoutput can be easily gathered by calling the fetch() method on it. The different run-time platformsoverload the createOut putListener method of the base controller so that a correct type of listener isreturned. For instance when using a platform that makes use of threads, a thread-safe listener will becreated and returned.

35

Page 37: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

3Visual Editor

In this section a visual modelling environment for SCCD in Unity is created. As software modelling isalso powerful for the creation of applications with lots of user interaction[DD09][Dub06], the editorwas built using SCCDXML. In section 3.1 we will first look at the requirements of the visual mod-elling environment. This is then followed by risk analysis in section 3.2 and we will conclude thissection with looking at the different iterations the application went through in the sections rangingfrom section 3.3 to section 3.8.

3.1 Requirements

In this section we look into the requirements of the visual editor. The overall goal is to obtain a userfriendly environment where a complete SCCD model can be created to define the behaviour of a gameobject in Unity. Additionally a compile function should be provided that generates executable codefrom the model and that immediately deploys the behaviour on successful compilation. Furthermorethe editor should be able to save any model and link it to the corresponding game object so that itcan be edited at any time to change the behaviour. The application should also provide a way to setmodel information such as its name, author and description. Means of defining the <top> element ofa model should be provided as well, together with the possibility of defining input and output ports.

As an SCCD model consists out of a class diagram in which each class can have a statechart, theeditor should provide functionality to create and manage both these types of components while still

36

Page 38: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

making it clear which class corresponds to which statechart. In subsection 3.1.1 we will look at therequirements for the part of the editor that takes care of the class diagram, while the requirements ofthe statecharts part are described in subsection 3.1.2.

3.1.1 Class Diagram Editor

The main purpose of the class diagram editor is to let the user create several classes and position themon the screen. The user should then be able to connect the different classes with edges to indicatethe different relationships. Settable properties for a class should include its name, optional attributesand methods(including a constructor and a destructor), and whether the class is the default class ornot. For each attribute, ways to set the type and name should be provided as well as the possibility todefine an initial value. Methods require input fields for a return type, name and a function body. Nextto that, the user should be able to create formal parameters for each method, defining their type andname and an optional default value.

When drawing edges, the user should have the option to add and remove control points in orderto obtain the optimal diagram layout. As each edge resembles a relation, input methods should beprovided for the user to set the name of the relation as well as the minimum and maximum cardinality.A label resembling the name should be placed in the center of the edge, but the user should have theability to reposition it. Finally it should be possible to associate a statechart with each class in thediagram.

3.1.2 Statechart Editor

The basic requirements for the editing of statechart elements are similar to those of the class diagram.States can be drawn on the screen and connected by directed edges that represent transitions. A majordifference though, is that states can be contained by other states. A way should thus be providedto indicate that child-parent relationship. The best way to do this is by simply dragging a state intoanother. However, when a state is dropped, it is possible that the dragged state is overlapping multipleother states. In this case the user should be able to indicate to which state the connection should bemade as well as have the option to not connect to any state at all.

As SCCD has three different types of states, the user should have a way to indicate which type of stateshould be drawn. It is also important that each state type has a different visual representation on thecanvas in order to have a clear distinction. Settable properties for a state should include its name andwhether or not it is a default state. The latter should only be available if the parent is not a parallelstate. In case of a history state there should also be an option to change the history type betweenshallow and deep. Lastly the user should have the option to define enter and exit actions for a state.As an action consists of an infinite number of scripts and raise events, the user should be able to addas many of these as needed. For a script, a simple text area should be provided while for each raise

37

Page 39: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

event there should be input fields for the event, scope and target attributes as well as the option to addparameters to be sent with the raised event.

The user should also be able to define actions for transitions. Additionally, input fields should beprovided to set a transition’s event, guard, cond and after attributes. Furthermore, there should be anoption to add formal event parameters to a transition where the name and type attributes can be set.Lastly, the user should be able to control both the text and position of the labels of transitions.

3.2 Risk Analysis

In order to determine whether the Unity platform fits our needs we performed several risk analyses toensure that we would not get stuck in the middle of the development process. The feasibility of theserisk analyses was also used to determine which engine we would actually use for the project.

1. The first thing we tested was whether it is possible to create some sort of plugin for the platformwhere textures and lines could be rendered. To test this in Unity we created an editor windowwith boxes on the screen connected by lines.

2. Next we tested whether autonomous behaviour was possible and the ability to process userinput. We did this by extending the previous prototype where a box would float around once itgets clicked. Furthermore we allowed the user to manually position the boxes by dragging themaround.

3. The goal of the third risk analysis was to check whether it is possible to access data inside agame when it is running and use it in the plugin. For this we made a small game in Unity withonly a cube in it. The cube has a single integer property which gets incremented each second.We then created a custom inspector for this cube and would display the integer value.

4. For the fourth risk analysis we wanted to see whether it was possible to get compiled SCCDmodels to actually work in a game. For this we started building the game from chapter 4 andmodelled the behaviour of the player tank using SCXML. We then inserted the compiled modelinto the game and tested whether the player tank reacted properly to user input.

5. So far all testing was inside the editor environment. For the final risk analysis we tested whethera game using SCCD modelled behaviour can actually be built into an executable and run inde-pendently outside of the editor on different platforms. In order to check this we simply usedUnity’s build options to create an executable of the demo game for the wanted operating sys-tems.

38

Page 40: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

3.3 Iteration 0: Model Everything

As MSDL’s motto is to model everything, the first approach to designing the visual editor was to writeas little code as possible and to model every single piece of functionality. Even before a minimalisticprototype was established, it was clear that this method had a significant number of flaws when doneat the wrong level of abstraction and that highly complex models would need to be created even forthe simplest of features. Obtaining a full fledged editor would be near impossible and the resultingmodels would be very hard to understand, which is exactly the opposite of what software modellingis trying to accomplish.

To illustrate the pitfalls of the "model everything" approach we look at the implementation of oneof the key basic features needed to create the visual editor, namely the ability to detect over whichelement the mouse is currently positioned. The most straightforward use-case for this is to determinewhich element should react upon the detection of a click event, crucial for the positioning of elementson the editor canvas. When disregarding software modelling, a very straightforward implementationis to simply loop over all elements currently present and check whether the current mouse position iscontained in the element’s bounding rectangle. A possible implementation of this can be seen in 3.1.

Element getClickedElement(Vector2 mouse_position){

foreach (Element element in elements) {

if (element.contains(mouse_position))

return element;

}

return null;

}

Code Sample 3.1: The detection of which element is being focused without the use of softwaremodelling.

For the modelled variant, we will first look at a very simplified model with just two classes presentin the diagram. The first and default class is a Canvas class representing the editor canvas, while thesecond class Element represents any element on the canvas. As the Canvas instance is responsiblefor creating all the elements (on detection of the right input event from the user), it maintains anassociation to all created elements. In 3.2 we see a possible model for the Element class.

<class name="Element">

<attribute type="Rect" name="rectangle"/>

<constructor >

<parameter type="Rect" name="rectangle"/>

<body >

this.rectangle = rectangle;

39

Page 41: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

</body >

</constructor >

<scxml initial="not_selected">

<state id="not_selected">

<transition

port="input"

event="left -mouse -down"

cond="this.rectangle.contains(mouse_pos)"

target="../selected"

>

<parameter type="Vector2" name="mouse_pos"/>

</transition >

</state >

<state id="selected">

<transition

port="input"

event="left -mouse -down"

cond="!this.rectangle.contains(mouse_pos)"

target="../not_selected"

>

<parameter type="Vector2" name="mouse_pos"/>

</transition >

</state >

</scxml >

</class >

Code Sample 3.2: The part of the SCCD model defining the Element class for iteration 0.

The model starts out in a not_selected state and for every left-mouse-down event it receives at theinput port, it will check whether the mouse position (passed as parameter mouse_pos) is containedin its rectangle property denoting its position and dimensions. If the condition evaluates positively,then the statechart transitions to the selected state. A similar evaluation on receiving the mouse eventtakes place in this state, triggering a transition back to the not_selected state if the mouse positionis not contained in the rectangle. While this model will effectively maintain the state of an Element

instance, there is currently no representation of the state to the user (nor is the user able to determinethe position of the element which makes the selection feature obsolete at this point).

When extending the Unity editor one has to keep in mind that Unity makes use of an immediate modeGUI as we saw in subsection 1.4.1. In short this means that for each OnGUI() call, every singledraw function needs to be called for all the elements that should be displayed. As we want to modeleverything, this problem was approached by first generating an update event in the engine port forevery OnGUI() call, followed by an update() call on the controller. In 3.3 it is then shown how wecan use this event to display a box for every element on the screen.

40

Page 42: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<scxml initial="not_selected">

<state id="not_selected">

<transition

port="input"

event="left -mouse -down"

cond="this.rectangle.contains(mouse_pos)"

target="../selected"

>

<parameter type="Vector2" name="mouse_pos"/>

</transition >

<transition port="engine" event="update" target=".">

<script >

GUI.Box(this.rectangle);

</script >

</transition >

</state >

<state id="selected">

<transition

port="input"

event="left -mouse -down"

cond="!this.rectangle.contains(mouse_pos)"

target="../not_selected"

>

<parameter type="Vector2" name="mouse_pos"/>

</transition >

<transition port="engine" event="update" target=".">

<script >

GUI.Box(this.rectangle , "selectedstyle");

</script >

</transition >

</state >

</scxml >

Code Sample 3.3: Updated version of the Element class where the update event is used to displayvisual representations.

At this point states can be created and displayed. It requires only a single transition to be added to theselected state to achieve the (basic) ability to move elements around. A drag event should simply begenerated and caught, followed by the position of the element being adjusted according to the changein position of the mouse (which should be passed as a parameter with the drag event). While after thisaddition the prototype still works, it is showing certain expected issues related to the overlapping ofelements. For one, dragging an element on top of another will not guarantee that the selected elementwill be displayed on top. Also when multiple elements are on top of each other, clicking on them will

41

Page 43: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

select them all instead of just the top one. For this layers or hierarchies need to be introduced to thedesign.

To create a hierarchy we add the notion of child elements to our design. As our goal is to createa Statecharts (and Class Diagram) editor, where overlapping elements will normally be child statesof the state they overlap, this seems the most logical decision to solve the layer problem. A non-modelling solution as displayed in 3.4 will simply use a recursive approach to find the deepest elementthat still contains the mouse position. This effectively returns at most one element and makes surethat it is the intended one.

Element getClickedElement(Vector2 mouse_position){

foreach (Element element in this.children)

{

if (element.contains(mouse_position))

return element.getClickedElement(mouse_position);

}

return this;

}

Code Sample 3.4: A non-modelling approach for determining which element in a hierarchy getsclicked.

When attempting a pure modelling approach, the first step is to add a relation to Element that asso-ciates a parent with its children. Unfortunately it is not simple for an Element instance to determinethat it is the top most element being clicked without direct access to its children. If we use the samerecursive idea as before, an element will first check whether the mouse position is contained in itsbounding rectangle. If that result is negative we know that the element is not being clicked and nei-ther are its children. However if the evaluation is positive, the results from all the children first needto be evaluated to determine whether it is the current element being focused or one of its children.For this, all the children should send an event to their parent indicating whether they got clicked ornot. Once the parent receives a positive event, it knows that it was not clicked. However if it keepson receiving negative events, the parent will actually not be able to determine that it is in fact the topmost focused element.

One could argue that that element is indeed the focused one after receiving as many negative elementsas it has children but SCCD currently does not expose the number of instances for an association. Inprinciple there are some (complex) ways around this but one of the reasons we want to use softwaremodelling to develop the application is that it should be easier overall. As at this point multipleconfusing tricks are needed as well as over communication between instances we can conclude thatthis is not the right approach. Also the overlap problem is hard to solve when solely using modellingand we are convinced that more issues like this will pop up when the application evolves. It looks like

42

Page 44: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

some sort of middle (abstraction) layer needs to be developed on top of the Unity API that exposesextra functionality, like determining which element is currently focused, in order to better supportsoftware modelling.

3.4 Iteration 1: The First Step to a Middle Layer

To solve the main problem of the first iteration, namely detecting which element is focused whenthere is overlap, a CanvasItem class is introduced that will maintain the position and dimensions ofany element in the application. Moreover it allows a hierarchy to be created, as each CanvasItem willmaintain a list to its child items. Note that this class is not part of the diagram model and is simply ahelper class that bridges the gap between Unity’s GUI API and the model.

Now instead of the class models having to maintain a rectangle property, the Canvas and the State

(named Element in the initial iteration) class in the diagram will simply hold a reference to a corre-sponding CanvasItem instance. Any operation ranging from retrieving to adjusting the position or thesize will happen through this reference. To actually solve the overlap problem a unique number isassigned to each CanvasItem which we will call its tag. Before we go into detail how this tag is used,we will first explain how we let Unity and the compiled model interact with each other.

For our editor we will make use of an editor window as explained in subsection 1.4.1. In this iterationwe started out with an editor for the Statecharts part of the formalism, therefore the window classis called StateChartEditorWindow and its implementation can be seen in Code Sample 3.5. Thestatic method Init() is responsible for the creation of the window and can set certain properties on itlike a title. This function is triggered by the menu item SCCD/Open Editor. Upon creation of thewindow, the constructor will initialize the properties canvas and controller. The canvas property isa CanvasItem and is set to the size of the drawable portion of the editor window at the beginning ofeach OnGUI() call to take into account any possible resizing the user might have done of the window.All the (top-level) elements that get drawn onto the canvas will be added as children to the canvas

property.

public class StateChartEditorWindow : EditorWindow {

sccdlib.GameLoopControllerBase controller;

CanvasItem canvas;

double update_time = 0;

[MenuItem("SCCD/Open Editor")]

public static void Init(){

StateChartEditorWindow window = (StateChartEditorWindow)

EditorWindow.GetWindow(typeof(StateChartEditorWindow), false);

window.title = "StateChart Editor";

43

Page 45: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

}

public StateChartEditorWindow(){

this.canvas = new CanvasItem(0,0);

this.controller = new Controller(this.canvas);

this.controller.start();

}

private void leftMouseDown() {

int tag = this.catchClick (Event.current.mousePosition);

this.controller.addInput(new sccdlib.Event(

"select",

"input",

new object[] {tag}

));

}

private void middleMouseDown() {

this.controller.addInput(new sccdlib.Event (

"create",

"input",

new object[] {Event.current.mousePosition}

));

}

private void leftMouseDrag() {

int tag = this.catchClick(Event.current.mousePosition -

Event.current.delta);

this.controller.addInput(new sccdlib.Event(

"drag",

"input",

new object[] {tag, Event.current.delta}

));

}

private void handleEvents() {

if (Event.current.type == EventType.MouseDown)

if (Event.current.button == 0)

this.leftMouseDown();

else if (Event.current.button == 2) {

this.middleMouseDown();

} else if (Event.current.type == EventType.MouseDrag)

this.middleMouseDrag();

44

Page 46: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

}

private int catchClick(Vector2 mouse_position) {

if (this.canvas.containsPosition(mouse_position))

return this.canvas.catchClick(mouse_position);

return -1;

}

public void OnGUI(){

this.canvas.setSize(this.position.width , this.position.height);

this.handleEvents();

this.controller.addInput(new sccdlib.Event("draw", "engine"));

this.controller.update (this.update_time);

this.update_time = 0;

}

public void Update(){

this.update_time += Time.deltaTime;

}

}

Code Sample 3.5: Iteration 1 implementation of the StateChartEditorWindow class.

The controller property is an instance of the GameLoopControllerBase class from the sccdlib libraryand is generated by the SCCD compiler from the model in Code Sample 3.6. On creation it gets thecanvas passed as parameter followed by a call to its start() method to start execution. As we make useof the game loop platform, the controller needs to be updated every frame. As any component in Unity,the editor window has an Update() method were it has access to a property called Time.deltaTime. Thisproperty contains the time it took to complete the last frame. We save this time in the member variableupdate_time and use it in OnGUI() when updating the controller. As OnGUI() gets called more thanonce per frame (see subsection 1.4.3), we have to set the update_time to 0 once the controller isupdated so that the controller does not advance in time multiple times each frame.

<diagram author="Glenn De Jonghe" name="SCCD Editor">

<top>

using UnityEditor;

using UnityEngine;

using SCCDEditor;

using Event = sccdlib.Event;

</top>

<inport name="input" />

<inport name="engine" />

<class name="Canvas" default="true">

45

Page 47: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<relationships >

<association class="State" name="states"/>

</relationships >

<attribute type="CanvasItem" name="canvas"/>

<constructor >

<parameter type="CanvasItem" name="canvas"/>

<body >

this.canvas = canvas;

</body >

</constructor >

<scxml initial="waiting">

<state id="waiting">

<transition event="create" port="input" target=".">

<parameter type="Vector2" name="position"/>

<script >

CanvasItem new_canvas_item = new CanvasItem(position , this.canvas);

this.canvas.addChild(new_canvas_item);

</script >

<raise scope="cd" event="create_instance">

<parameter expr=’"states"’ />

<parameter expr=’"State"’/>

<parameter expr=’"name"’ />

<parameter expr=’new_canvas_item ’ />

</raise >

</transition >

<transition event="instance_created" target=".">

<parameter name="association_name" type="string"/>

<raise scope="cd" event="start_instance">

<parameter expr="association_name" />

</raise >

</transition >

<transition event="draw" port="engine" target=".">

<raise scope="narrow" event="draw" target="states"/>

</transition >

</state >

</scxml >

</class >

<class name="State">

<attribute type="string" name="name"/>

<attribute type="CanvasItem" name="canvas_item"/>

<constructor >

<parameter type="String" name="name"/>

<parameter type="CanvasItem" name="canvas_item"/>

<body >

46

Page 48: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

this.name = name;

this.canvas_item = canvas_item;

</body >

</constructor >

<method name="draw" type="void">

<parameter type="bool" name="is_selected"/>

<body >

if (is_selected)

GUI.Box(this.canvas_item.rect , name , "selectedstyle");

else

GUI.Box(this.canvas_item.rect , name);

</body >

</method >

<scxml initial="not_selected">

<state id="selected">

<transition target="." event="draw">

<script >

this.draw(true);

</script >

</transition >

<transition target="." port="input" event="drag"

cond="true/*this.canvas_item.tag == tag*/">

<parameter type="int" name="tag"/>

<parameter type="Vector2" name="delta"/>

<script >

this.canvas_item.move(delta);

</script >

</transition >

<transition event="select" port="input" target="../not_selected"

cond="this.canvas_item.tag != tag">

<parameter type="int" name="tag"/>

</transition >

</state >

<state id="not_selected">

<transition target="." event="draw">

<script >

this.draw(false);

</script >

</transition >

<transition event="select" port="input" target="../selected"

cond="this.canvas_item.tag == tag">

<parameter type="int" name="tag"/>

</transition >

</state >

47

Page 49: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

</scxml >

</class >

</diagram >

Code Sample 3.6: The SCCD editor model during iteration 1.

Next to updating the controller, OnGUI() also takes care of generating events for the controller. Asseen in subsection 1.4.3 the current event is stored in Event.current. In handleEvents() we check theevent type and generate an SCCD event accordingly. In case of a mouse event, the mouse position isfirst used to calculate which item is clicked. This is done by calling the catchClick() function (seenin Code Sample 3.7) on the canvas which will use recursion to find the top most element hoovered bythe mouse. The tag of this element is then passed as a parameter along with the events that need it.

public int catchClick(Vector2 mouse_position) {

for (int i = this.children.Count -1; i >= 0; i--){

if (this.children[i].containsPosition(mouse_position)) {

return this.children[i].catchClick(mouse_position);

}

}

return this.tag;

}

Code Sample 3.7: The catchClick() method of the CanvasItem class.

Finally right before updating the controller, the OnGUI() function will also send a draw event sothat every GUI control can draw itself on the canvas. It is actually this part of the iteration thatis problematic. Making the models responsible for drawing themselves on the screen turns out tocreate all sorts of problems when we advance further than the early stage prototype and get to a morecomplex interface. The main issue is the unpredictable timing and order of the drawing of the controls.For this reason a new approach needs to be taken in order to get Unity’s immediate mode GUI to workproperly with the execution of the models.

3.5 Iteration 2: Rendering Elements Independently of the Model

The main change in this iteration is that the models are no longer responsible for the drawing of theircontrols on the screen. Instead we extend the middle layer with drawing functionality. What thismeans for the CanvasItem class is that a draw() function will be added. Next to that, CanvasItem nowalso needs methods to change its visual appearance. This is important since the SCCD model mightdetect for instance that a state gets selected. To denote this to the user we would want the color of itsvisual representation to change. As the drawing now gets outsourced to the middle layer the only wayto do this is to call a function on this middle layer that takes care of setting the color. For this specific

48

Page 50: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

example, a color property and a simple setColor() method are added to the CanvasItem class.

What also changed in this iteration is that we created a separate class for the canvas called Editor-

Canvas so that all functionality regarding the handling of elements on the canvas can be moved fromthe editor window to this canvas class. This was needed as we started extending the editor with otheruser interface components like a toolbar with different state types and scrollbars around the canvasas we want it to be able to expand to any size needed. In Code Sample 3.8 the public interface ofEditorCanvas is shown.

public class EditorCanvas {

public Rect rect { get; private set; }

public void addChild(CanvasItem child);

public void removeChild(CanvasItem child);

public bool containsPosition(Vector2 position);

public int catchClick(Vector2 mouse_position);

public void draw();

public void pushChildToFront(CanvasItem item);

public void adjustSizeToMinimum(Rect minimum);

}

Code Sample 3.8: The public interface of EditorCanvas.

The canvas’ draw() method will simply loop over all its child items and call their draw() function.They will in turn first draw themselves on the screen before recursively rendering their children. TheadjustSizeToMinimum() function is used to set the canvas’ scroll area properly. To explain how thatworks we will first look at the implementation of the extra GUI components. As can be seen in CodeSample 3.9 we did not make use of modelling for these components in this iteration, instead we usedthe conventional way of calling the corresponding GUI methods in OnGUI().

public class StateChartEditorWindow : EditorWindow {

...

EditorCanvas canvas;

Vector2 scroll_pos = Vector2.zero;

Rect toolbar;

string[] buttons = new string[] {"Basic", "Parallel" "History"}; //Toolbar

int selected = 0; //Index of the selected button in the toolbar.

private void drawToolArea()

{

this.toolbar = new Rect(0,0, this.position.width , 40);

GUILayout.BeginArea(this.toolbar , "", "box");

49

Page 51: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

this.selected = GUILayout.Toolbar(this.selected , this.buttons);

GUILayout.EndArea();

}

public void OnGUI()

{

this.drawToolArea();

Rect draw_area = new Rect(0, this.toolbar.height , this.position.width ,

this.position.height - this.toolbar.height);

this.canvas.adjustSizeToMinimum(draw_area);

this.scroll_pos = GUI.BeginScrollView(draw_area , this.scroll_pos ,

this.canvas.rect);

this.handleEvents();

if (Event.current.type == EventType.Repaint)

this.canvas.draw();

this.controller.update(this.update_time);

this.update_time = 0;

GUI.EndScrollView();

}

...

}

Code Sample 3.9: The partial implementation of StateChartEditorWindow during iteration 2.

We start off with drawing a horizontal toolbar area. For this we will first draw a container with theBeginArea() function. Every other GUILayout function call will now draw inside this container untilEndArea() is called. Inside we make use of the Toolbar function, which is essentially a horizontal listof buttons of which just one button is selected at a time. The labels of the buttons should be passedas parameter as well as the index of the button that is currently selected. The function will then returnthe index of the button that is selected after the input events are processed. Unless the user clickedon the toolbar, this will result in the same index as what has been passed. This process is used formost of the more complex GUI controls in Unity including the BeginScrollView() we use. This scrollview component needs a Vector2 instance as parameter defining the position of both the horizontaland vertical scrollbar. The possibly adjusted values will then be returned and should be saved to usein the next frame.

The BeginScrollView() also requires two rectangles as parameters. One to denote the area visible onthe screen and another to define the total area of the canvas. Naturally if the second one is bigger thanthe first one, the scroll bars will become visible. The first rectangle can be easily calculated using thesize of the editor window subtracted by the size of the toolbar. The second rectangle however dependson the elements present on the canvas. This is where the adjustSizeToMinimum() method comes into

50

Page 52: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

play. It will use the the function calculateContainer in Code Sample 3.10 to calculate a rectangle thatcontains all canvas items keeping in mind a certain margin at the borders.

public Rect calculateContainer(Rect minimum , float margin = 0.0f)

{

float x_min = minimum.xMin + margin;

float y_min = minimum.yMin + margin;

float x_max = minimum.xMax - margin;

float y_max = minimum.yMax - margin;

foreach(CanvasItem element in this.elements)

{

if (element.position.xMin < x_min) x_min = element.position.xMin;

if (element.position.yMin < y_min) y_min = element.position.yMin;

if (element.position.xMax > x_max) x_max = element.position.xMax;

if (element.position.yMax > y_max) y_max = element.position.yMax;

}

return new Rect (x_min - margin , y_min - margin , x_max -x_min + 2 * margin ,

y_max -y_min + 2 * margin);

}

Code Sample 3.10: The calculateContainer() method used to calculate a rectangle for an element thatencompasses all its children.

3.5.1 Drag and Drop

Further in this iteration we started the implementation of being able to drag states into other states todeclare the child-parent relationship. As the size of the model file started to become rather large andunclear at this point, the different classes were split up into separate files. A main file then simplydefines the diagram and links to every class file as in Code Sample 3.11.

<diagram name="StateChartEditor">

<!-- Description, top and input ports hidden.-->

<class name="Window" default="true" src="window.xml"/>

<class name="Toolbar" src="toolbar.xml"/>

<class name="PropertiesPanel" src="properties_panel.xml"/>

<class name="StateProperties" src="state_properties.xml"/>

<class name="Action" src="action.xml"/>

<class name="Script" src="script.xml"/>

<class name="Raise" src="raise.xml"/>

<class name="ActualEventParameter" src="actual_event_parameter.xml"/>

<class name="FormalEventParameter" src="formal_event_parameter.xml"/>

<class name="Canvas" src="canvas.xml"/>

<class name="State" src="state.xml"/>

51

Page 53: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<class name="StateDrop" src="state_drop.xml"/>

<class name="Transition" src="transition.xml"/>

<class name="TransitionProperties" src="transition_properties.xml"/>

</diagram >

Code Sample 3.11: The main model file defining the statechart editor in the final result.

When a state gets dropped into another state, the dropped state should be removed from its previousparent and added to its new parent. This is no problem for the middle layer components, but adjustingthe SCCD associations turns out to be rather complex. Imagine a situation where there are just twostates on the canvas, StateA and StateB. The canvas’ children association will thus link to both. Nowwhen StateB gets dropped into StateA, the association to StateB from the canvas should be removed.It is StateB that is currently aware of the state drop and thus needs to signal its parent to disconnect.However in order for the parent to remove the association, it needs to know the identifier assigned toStateB when the association was made.

<transition event="change_connection" target="../../ not_dragging">

<parameter type="SGUICanvasElement" name="connection"/>

<raise event="disconnect_child" target=’"parent"’>

<parameter expr="this.widget"/>

</raise >

<raise scope="cd" event="unassociate_instance">

<parameter expr=’"parent"’ />

</raise >

<raise event="connect_child_to_parent" target=’"canvas"’>

<parameter expr="this.widget"/>

<parameter expr="connection"/>

<parameter expr="this.state_xml"/>

</raise >

</transition >

Code Sample 3.12: The transition in the statechart of the State class that gets triggered when the stateshould connect with a new parent.

While this looks like a serious flaw in SCCD and could definitely use some improvement, a wayaround this is by maintaining a mapping of a unique state identifier to the assigned association iden-tifier. Since every State instance has a CanvasItem instance, and every such instance has a uniquetag, we can use this for the mapping. In Code Sample 3.12 we see the transition that is triggeredafter a state is dropped onto another state. First a disconnect_child event is send to the parent withthe state’s CanvasItem instance as parameter. This is followed by the unassociation of the parent andfinally a connect_child_to_parent event is send to the canvas with the CanvasItem instances of boththe dropped state and the target state.

52

Page 54: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<transition event="disconnect_child" target=".">

<parameter name="child" type="CanvasItem"/>

<raise scope="cd" event="unassociate_instance">

<parameter expr=’String.Format("children [{0}]",

this.children_map[child.tag])’ />

</raise >

<script >

this.children_map.Remove(child.tag);

this.canvas.removeChild(child);

</script >

</transition >

Code Sample 3.13: The transition in the statechart of the Canvas class acting on the disconnect_childevent.

In Code Sample 3.13 we see how the disconnect_child event is handled by the canvas and the states.It will first use the children mapping to send an unassociate_instance event to the object manager andthen removes the CanvasItem instance from both the mapping and its middle layer representation.

<transition event="connect_child_to_parent" target="../connecting">

<parameter name="child" type="CanvasItem"/>

<parameter name="parent" type="CanvasItem"/>

<script >

this.current_item = child;

String parent_path = String.Format("all_states [{0}]",

this.all_states_map[parent.tag]);

String child_path = String.Format("all_states [{0}]",

this.all_states_map[child.tag]);

Debug.Log("connect_child_to_parent");

</script >

<raise scope="cd" event="associate_instance">

<parameter expr=’child_path ’ />

<parameter expr=’parent_path + "/children"’/>

</raise >

<raise scope="cd" event="associate_instance">

<parameter expr=’parent_path ’ />

<parameter expr=’child_path + "/parent"’/>

</raise >

</transition >

Code Sample 3.14: The transition in the statechart of the Canvas class that connects a state to a newparent.

53

Page 55: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Code Sample 3.14 shows the transition triggered by the connect_child_to_parent event. Note the ad-ditional association called all_states and the corresponding mapping. This turns out to be necessary toconnect the dropped state to the new parent. With just the children association of both the canvas andthe dropped state, it is impossible to determine an association reference to the new parent. Thereforethe canvas will maintain an association to all states present on the canvas at any time. The transitionhas as target the hierarchy_connection state that will signal the parent to update its children mappingand take care of the CanvasItem hierarchy.

3.5.2 Modal Window

If a state overlaps with several other states the moment it gets dropped, the user should be able todecide to which state to connect to (or to connect to no state at all). For this a small window shouldpop up showing the several options the user has as is depicted in Figure 3.1. Obtaining such a windowin a modelled environment with Unity’s GUI API is not exactly straight forward. Options consideredinclude creating another EditorWindow and using built-in modal window functionality. The secondoption unfortunately only allows for a message and one to three buttons being showed. The first optionlooks rather clumsy and would require a lot of code for the communication between the windows andto disable the statechart editor until a reply is received from the modal window.

As a lot of extra code would be required anyway we decided to instead create our own modal windowsystem using GUILayout’s Window function. What this function does is create a subwindow that cancontain its own GUI controls. For this to work properly though, the methods BeginWindows() andEndWindows() have to be called on the editor window that will render the subwindow. To do thiswe added an extra method to StateChartEditorWindow that needs to be called for a modal windowto be created. This is shown in Code Sample 3.15 along with the adjustments made to the OnGUI()

function in order to take care of the rendering of the modal window.

public void createModalWindow(string title , ModalWindow.DrawFunction

draw_function)

{

this.modal_window = new ModalWindow(title , draw_function , this);

}

public void OnGUI()

{

GUI.enabled = this.modal_window == null;

this.drawGUI();

if (Event.current.type == EventType.Layout)

{

if (this.modal_window != null && this.modal_window.should_close)

this.modal_window = null;

54

Page 56: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

}

if (this.modal_window != null)

{

GUI.enabled = true;

this.BeginWindows();

this.modal_window.draw();

this.EndWindows();

}

}

Code Sample 3.15: The functions that take care of the creation, rendering and closing of a modalwindow.

At the beginning of the function GUI.enabled is set false if any modal window is active. This willgive a disabled look to all GUI components rendered afterwards and turns off all events generated bythese components. This makes sure that when a modal window is active, nothing can be changed inthe editor. Right before rendering the modal window, GUI.enabled is set to true again so that the sub-window will have active controls. The OnGUI() function also takes care of closing the window. Forthis we will first look at the ModalWindow class representing the modal window in Code Sample 3.16.

public class ModalWindow

{

public delegate void DrawFunction(ModalWindow window);

public bool should_close { get; private set; }

private DrawFunction draw_function;

private EditorWindow editor_window;

private int repaints = 3;

private string title;

private Vector2 size new Vector2(0, 0);

public SCCDModalWindow(string title , DrawFunction draw_function , EditorWindow

editor_window)

{

this.should_close = false;

this.title = title;

this.draw_function = draw_function;

this.editor_winwdow = editor_window;

}

public void close()

{

this.should_close = true;

55

Page 57: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

}

private void windowDrawFunction(int unused_window_id)

{

this.draw_function(this);

}

public void draw()

{

Rect position = new Rect(0, 0, this.size.x, this.size.y);

position.center = new Vector2(this.window.position.width/2,

this.window.position.height/2);

position = GUILayout.Window(0, position , this.windowDrawFunction ,

this.title);

this.size = newVector2(position.width , position.height);

GUI.FocusWindow(0);

if (this.repaints > 0){

this.editor_window.Repaint();

this.repaints --;

}

}

}

Code Sample 3.16: The middle layer class ModalWindow used to display a modal window.

What ModalWindow basically does is maintaining a DrawFunction that is responsible for drawing thecontrols that should appear in the modal window. This function is a delegate that should be passed asconstructor parameter. The draw() method will then use this delegate to call GUILayout.Window andactually render all components. We make use of GUILayout instead of GUI as it will calculate theneeded size for the window to fit all the content and return it. This is then saved in the size member topass as parameter for the next call, resulting in a perfectly sized window after the second call. Sincewe want the automatic sizing to happen instantly, we added a repaints property with an initial valueof 3. In the draw function we then check whether this value is bigger than 0 and if so, we force thewindow to recall OnGUI() by calling the Repaint method on the editor window. This is followed bydecreasing this value so that the redrawing only happens three times.

The close method simply sets a should_close property to true. The editor window will use this prop-erty to determine when the modal window should be closed, which basically means not renderingit any more and clearing all references to it so that garbage collection will take care of it. In CodeSample 3.17 we see the function that is used to create the modal window for state drops. A simpleselection grid is used that shows all possible parent states followed by a ’Yes’ and ’No’ button. When

56

Page 58: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 3.1: The modal window shown upon dropping a state onto multiple other states.

the ’Yes’ button is pressed, the state_drop_popup_response event is generated for the instance’s stat-echart with as first parameter true indicating that the parent-child connection should be made, anda second parameter that contains the CanvasItem instance of the new parent. If ’No’ is pressed, thesame event will be generated with a negative first parameter. While this works perfectly, the addEvent

method we used should normally not be exposed.

<method type="void" name="drawModalWindow">

<parameter name="modal_window" type="ModalWindow"/>

<body >

GUILayout.Label("Connect to:");

this.selected_option = GUILayout.SelectionGrid(this.selected_option ,

this.connection_options_strings , 1, "MenuItem");

EditorGUILayout.BeginHorizontal();

if (GUILayout.Button("Yes"))

{

this.addEvent(new sccdlib.Event("state_drop_popup_response", "", new

object[] {true , this.connection_options[this.selected_option]}));

modal_window.close();

}

if (GUILayout.Button("No"))

{

this.addEvent(new sccdlib.Event("state_drop_popup_response", "", new

object[] {false , null}));

modal_window.close();

}

EditorGUILayout.EndHorizontal();

</body >

57

Page 59: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

</method >

Code Sample 3.17: The delegate function used to display the modal window for dropped states.

We solve this problem in the next iteration by extending the middle layer with classes, not only forthe modal window, but for every single GUI component so that all parts of the user interface can bemodelled. Events can then be generated in the middle layer and send through input ports to the correctinstances.

3.6 Iteration 3: Extended Middle Layer

So far only the canvas was modelled. In this iteration we introduce a complete hierarchy of GUIwidgets to the middle layer so that we are able to model the complete editor including its toolbars,scroll areas, text fields, buttons and much more.

3.6.1 Widget Hierarchy

A large part of the functionality that was contained in the CanvasItem class up till now is moved toa new class called SGUIWidget. This class will serve as a base class for any type of GUI widget.In Figure 3.2 we see the complete class hierarchy that got built during the creation of the visualeditor. Note that most private methods are omitted in order to keep the diagram clean. Next to theUML symbols for public(+), private(−) and protected(#) properties, the symbol ∗ is used to indicateproperties that make use of the C# specific syntax to automatically create a public getter and privatesetter. An example of this is the should_close property of the ModalWindow class we saw in CodeSample 3.16.

public void doOnGUI(){

bool previous_enabled_state = GUI.enabled;

if (!this.is_enabled)

GUI.enabled = false;

this.OnGUI();

GUI.enabled = previous_enabled_state;

}

Code Sample 3.18: The doOnGUI() method of SGUIWidget which will call OnGUI() if the widget isenabled.

Every widget inheriting from SGUIWidget should implement the OnGUI() function to specify itsvisual appearance on the screen and generate any events based on user input. Note that this methodis protected and thus can not be called directly. Instead in order to trigger the rendering of any GUIelement, the doOnGUI() method should be called. As shown in Code Sample 3.18 it simply calls

58

Page 60: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

OnGUI() but will first store the state of the GUI, disable it depending on SGUIWidget’s is_enabled

property, and finally restore the GUI state. What this results in is that a single widget can be disabledusing its setEnabled() method. It is also possible to do this for a group of widgets, which brings us tothe SGUIGroupWidget class.

59

Page 61: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 3.2: The complete class hierarchy of SGUI widgets that got created during the creation of the visual editor.

60

Page 62: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

3.6.2 Group Widget

SGUIGroupWidget is basically a widget that contains other widgets. Its OnGUI() method does noth-ing more than calling doOnGUI() on all its children. Simple subclasses include SGUIHoritonztal-

Group and SGUIVerticalGroup which do nothing more than adapting the OnGUI() method in order todisplay the children in a respectively vertical and horizontal order. In Code Sample 3.19 the OnGUI()

function of SGUIVerticalGroup is displayed. As with the scroll view we saw in section 3.5 a beginand end call is used again. While this was pretty much impossible to use in a "model everything" ap-proach, the widget hierarchy facilitates this very well and we can simply call base.OnGUI() betweenthese two calls. Passed with BeginVertical() is the style property of SGUIWidget. This property oftype GUIStyle is used to have for example a different visual appearance for different state types orin this case, to have settings like background, border, padding and margin for the container. At theend of the function, the position property is set using GUILayoutUtility.GetLastRect(). This functionreturns the last Rect instance calculated by the automatic layout engine, which in this case is the oneused for the vertical container.

protected override void OnGUI()

{

EditorGUILayout.BeginVertical(this.style ,

GUILayout.ExpandHeight(this.expand_height),

GUILayout.MinWidth(this.min_width));

base.OnGUI();

EditorGUILayout.Space();

EditorGUILayout.EndVertical();

if (Event.current.type == EventType.Repaint)

this.position = GUILayoutUtility.GetLastRect();

}

Code Sample 3.19: The OnGUI() method of the SGUIVerticalGroup class.

3.6.3 Modal Window

A more complex subclass of SGUIGroupWidget is SGUIModalWindow. Compared to its versionwe saw in subsection 3.5.2 it no longer requires a draw function to be supplied, instead the widgetsthat should be drawn inside the modal window need to be added to the widget using the addChild()

method. The SGUIModalWindow class will then simply use base.OnGUI() as draw function forGUILayout.Window. The constructor of SGUIModalWindow will add the created instance to thecurrent SGUIEditorWindow instance, which is the class responsible for the rendering of the modalwindow as we will explain in subsection 3.6.4.

61

Page 63: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<method type="void" name="drawModalWindow">

<body >

this.modal_window = new SGUIModalWindow("State Drop");

this.modal_window.addChild(new SGUILabel("Connect to:"));

this.selection_grid = new

SGUISelectionGrid(this.connection_options_strings);

this.modal_window.addChild(this.selection_grid);

this.modal_window.addChild(new SGUISpace());

SGUIHorizontalGroup buttons_widget = new SGUIHorizontalGroup();

this.modal_window.addChild(buttons_widget);

this.yes_button = new SGUIButton("Yes");

buttons_widget.addChild(this.yes_button);

this.no_button = new SGUIButton("No");

buttons_widget.addChild(this.no_button);

</body >

</method >

Code Sample 3.20: The drawModalWindow() method which constructs the same modal window as inCode Sample 3.17 but by using SGUI.

Code Sample 3.20 shows the construction of the modal window using SGUI to obtain the same GUIcomponents as in Code Sample 3.17. After the creation of the modal window and the addition ofa simple label, the selection grid gets first instantiated and stored into the property selection_grid

before it gets added to the container widget. This is necessary in order to fetch the selected optionwhen needed. Next an instance of SGUISpace is added, which does nothing more than creating somespace between two components, followed by the creation of an SGUIHorizontalGroup instance tocontain the "Yes" and "No" button. The buttons, represented by SGUIButton instances, are also storedin properties so that the statechart can detect when they get clicked.

<state id="popup_open">

<onentry >

<script >this.drawModalWindow();</script >

</onentry >

<onexit >

<script >this.modal_window.close();</script >

</onexit >

<transition event="button_pressed" port="input" cond=’this.yes_button.tag ==

tag’ target="/popup_closed">

<parameter name="action" type="string"/>

<raise target=’"dropped_state"’ event="change_connection">

<parameter expr="this.connection_options[this.selected_option]"/>

62

Page 64: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

</raise >

</transition >

<transition event="button_pressed" port="input" cond=’this.no_button.tag ==

tag’ target="/popup_closed">

<parameter name="action" type="string"/>

<raise target=’"dropped_state"’ event="not_change_connection"/>

</transition >

</state >

Code Sample 3.21: The state that is active during the time the state drop modal window is presentedto the user.

In Code Sample 3.21 we see the state that is active during the time the state drop modal window ispresented to the user. Its enter action is responsible for the opening of the window, while the exitaction will close it. There is a transition for each button that is triggered as soon as a click on them isdetected. The way this is done is by checking whether the tag that is passed with the button_pressed

event matches the tag of the button widgets. Note that this is the method used in the final iteration. Inthis iteration a string identifying the button was used to determine when a button got clicked. We talkabout this old method in subsection 3.6.5.

When the "Yes" button gets clicked, a change_connection event gets sent to the dropped state with asparameter the state that got selected by the user in the selection grid. If it is the "No" button beingclicked, then a not_change_connection event is send. Both will transition to the closed state which inturn will trigger the exit action and thus close the modal window.

3.6.4 Editor Window

SGUIEditorWindow is a class that inherits from Unity’s EditorWindow and should be used as superclass for any editor window that wants to make use of SCCD and SGUI(our middle layer). It has acontroller property that will contain the generated GameLoopControllerBase from an SCCD model.An input event can be sent to this controller using the generateEvent() method. It also contains a staticproperty current of type SGUIEditorWindow which will contain the editor window that is currentlybeing rendered. For instance modal windows make use of this static property to signal their existence.The way the property is enforced, is by setting it at the start of SGUIEditorWindow’s OnGUI() methodas shown in Code Sample 3.22. The top_level_widget property is an instance of SGUIGroupWidget

and will contain all the widgets in the editor window. For every frame, its size is first set to reflectthe size of the editor window. This is followed by calling doOnGUI() on it and a processEvent()

call if top_level_widget is enabled. The latter depends on whether a modal window is active or not,which in turn decides if the modal window should be rendered. Note that the code sample is fromthe final version and that SGUIEvent and processEvent() are not introduced until the next iteration. Inthis iteration they were replaced by a static property of SGUIWidget called current_event but this is

63

Page 65: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

explained in more detail in subsection 3.6.5.

public void OnGUI(){

GUI.skin = Resources.LoadAsset(SCCDSkin.guiskin);

SGUIEditorWindow.current = this;

if (Event.current.type != EventType.Layout)

{

this.top_level_widget.setPosition(this.position);

if (Event.current.type != EventType.Repaint)

SGUIEvent.current = null;

}

this.top_level_widget.doOnGUI();

if (this.top_level_widget.is_enabled)

this.processEvent();

else if (this.modal_window.should_close)

{

this.modal_window = null;

this.top_level_widget.setEnabled(true);

}

if (this.modal_window != null)

{

SGUIEvent.current = null;

this.BeginWindows();

this.modal_window.doOnGUI();

this.EndWindows();

this.processEvent();

}

SGUIEditorWindow.current = null;

if (this.repaints > 0)

{

this.Repaint();

this.repaints --;

}

}

Code Sample 3.22: The final version of SGUIEditorWindow’s OnGUI() method.

64

Page 66: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

As the complete SCCD editor actually consists of a class diagram editor and a statechart editor, whichboth have a separate model, they each have their own editor window class inherited from SGUIEd-

itorWindow. For the class diagram part we have the class ClassDiagramEditorWindow. Its open()

function expects an SCCDScript as parameter and will store this in its sole property sccd_script. Aswe saw in subsection 1.4.2 SCCDScript is the script that should be added to a game object in order tomake use of SCCD modelled behaviour and the visual editor. The custom inspector of the script willshow a button that triggers the opening of the editor. In the start() method the controller is instantiatedwith as constructor parameters the properties top_level_widget and sccd_script. The latter is used bythe (editor) model to access the path to the corresponding (game object) model file, if any, and is usedto attach information regarding this model to properly execute the generated code.

StateChartEditorWindow is very similar to ClassDiagramEditorWindow but differs in the way it isopened. Its open() function expects as parameter the XElement matching the <scxml> tag of anSCCD model. It will not only pass this on to its controller but it will also store it in a dictionary. Thisdictionary is then used to determine if a window for a specific <scxml> tag is already open and if thatis the case, instead of creating a new one, the existing window will be focused.

3.6.5 Event Generation

In this iteration major improvements were achieved compared to previous iterations regarding thegeneration of mouse events. The calculation of these events was moved away from the editor windowto the widgets. Instead of calculating the focused element when a mouse event is received, the eventgeneration code is now incorporated into the OnGUI() methods of each widget that should generatemouse events. This was achieved by adding a static property current_event to SGUIWidget with astype Event from the SCCD library. When a widget detects in its OnGUI() function that the currentmouse position is contained in its bounding rectangle, it creates an event depending on what sort ofmouse event is currently being processed and stores it in current_event. As this calculation happensbefore the doOnGUI() functions of any possible children are called, the event that got generated bythe innermost widget will be the one that is eventually stored in current_event when the call of thetop-level widget’s doOnGUI() function ends. The editor window will then simply send this event tothe controller.

An advantage of this approach is that certain widgets can decide to ignore mouse events. For instancelabels have no need to detect that the mouse is being dragged inside their bounding rectangle. Withthe old approach an event would still be generated for this label which can be problematic in certainsetups. For example when we have a state on the canvas containing a label, the state would not receivea drag event if the mouse is dragging over the label.

public override void OnGUI()

{

65

Page 67: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Rect position = GUILayoutUtility.GetRect(new

GUIContent(this.properties.label), this.style);

int id = GUIUtility.GetControlID (FocusType.Keyboard);

EventType event_type = Event.current.GetTypeForControl(id);

if (event_type == EventType.MouseDown)

{

if (this.position.Contains(Event.current.mousePosition))

{

GUIUtility.hotControl = id;

this.doLeftMouseDown();

}

} else if (event_type == EventType.MouseUp)

{

if (GUIUtility.hotControl == id)

{

GUIUtility.hotControl = 0;

}

} else if (event_type == EventType.Repaint)

{

this.position = position;

button_style.Draw(

this.position ,

this.label ,

this.position.Contains(Event.current.mousePosition), //isHover

GUIUtility.hotControl == id, //isActive

this.is_on , //on

false //hasKeyboardFocus

);

}

}

Code Sample 3.23: Iteration 3 implementation of SGUIButton’s OnGUI() method.

In order to illustrate the event generation we look in Code Sample 3.23 at the implementation ofSGUIButton’s OnGUI() method resulting from this iteration. In case of a MouseDown event, thebutton will check if the current mouse position is contained in its bounding rectangle. If this is thecase it calls a doLeftMouseDown() method of its base class SGUIWidget of which the implementationcan be seen in Code Sample 3.24. It does nothing more than creating a left-mouse-down event andstoring it in current_event. As a button is normally the lowest-level widget, this should be followedby the editor window sending this event to the controller.

protected void doLeftMouseDown(){

GUIWidget.current_event = new sccdlib.Event(

66

Page 68: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

"left -mouse -down", //event

"input", //port

this.tag, Event.current.mousePosition //parameters

);

}

Code Sample 3.24: The doLeftMouseDown() method of SGUIWidget which simply generates acorrect SCCD event.

In Code Sample 3.25 we see the Button class of the SCCD model. The button model accommodatestwo types of buttons, a normal one that can just be clicked and a toggle button that can be turned onand off. What type a button is, is stored in the is_toggle property of SGUIButton. This property isused in the conditions of the two transitions in the off state. A left-mouse-down event with a negativeis_toggle property will cause a transition to return to the same state and if the property is positive, theon state will be entered. This will cause the is_on boolean property of the button widget to be set totrue, changing the appearance of the button to reflect its new state. The exit action of the off state,which gets executed each time one of its two transitions is triggered, sends a button-pressed event tothe event-receiver association. This should be set by the creating instance to the instance that shouldreceive the event. Upon creation of the button, a string should also be passed as constructor parameterthat uniquely defines the button. This string, stored in action, is passed with the event in order for theevent receiver to check which button generated the event.

<?xml version="1.0" encoding="UTF-8" ?>

<class name="Button">

<relationships >

<association class="IRuntimeClass" name="event_receiver" max="1"/>

</relationships >

<attribute type="SGUIButton" name="button_widget"/>

<attribute type="string" name="action"/>

<constructor >

<parameter type="SGUIButton" name="button_widget"/>

<parameter type="string" name="action"/>

<body >

this.button_widget = button_widget;

this.action = action;

</body >

</constructor >

<scxml initial="off">

<state id="off">

<onentry >

<script >this.button_widget.is_on = false;</script >

</onentry >

67

Page 69: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<transition event="left -mouse -down" port="input" target="../on"

cond="this.button_widget.tag == tag && this.button_widget.is_toggle">

<parameter name="tag" type="int"/>

</transition >

<transition event="left -mouse -down" port="input" target="."

cond="this.button_widget.tag == tag && !this.button_widget.is_toggle">

<parameter name="tag" type="int"/>

</transition >

<onexit >

<raise event="button_pressed" target=’"event_receiver"’>

<parameter expr="this.action"/>

</raise >

</onexit >

</state >

<state id="on">

<onentry >

<script >this.button_widget.is_on = true;</script >

</onentry >

<transition event="reset" target="../off" cond="this.button_widget.tag !=

except_tag">

<parameter name="except_tag" type="int"/>

</transition >

</state >

</scxml >

</class >

Code Sample 3.25: The part of the SCCD model defining the Button class for iteration 3.

Also introduced in this iteration is SGUIWidget’s generateEvent() method. This function is simplyused to generate events not related to the mouse as they do not need to take into account the hierarchyof widgets and can be added to the controller immediately after creation. An example of this is acheck-box getting (un)checked. As we can see in Code Sample 3.26, if SGUICheckbox detects thatits checkbox got changed, it simply generates a changed event with its tag as parameter. The modelcan then simply access the checkbox’s value using its is_checked property upon detecting the event.

protected override void OnGUI(){

EditorGUI.BeginChangeCheck ();

this.is_checked = EditorGUILayout.Toggle(this.label , this.is_checked);

if (EditorGUI.EndChangeCheck ()) {

this.generateEvent("changed", "input", this.tag);

}

}

68

Page 70: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Code Sample 3.26: The implementation for SGUICheckbox’s OnGUI() method.

3.7 Iteration 4: Proper Event Generation

While the previous iteration already resulted in a better way of generating mouse events, there is stillroom for improvement. If a certain widget wants to make use of multiple different types of mouseevents, code for both the detection of each type and the subsequent event generation needs to bewritten. Now imagine several widgets requiring the same thing and you end up with a lot of similarcode that needs to be written for every single widget. For this reason we created the SGUIEvent classwhich will effectively replace the functionality of SGUIWidget.current_event. This class, of which theimplementation is shown in Code Sample 3.27, is simply a small container class that saves a widget’stag and the position of the mouse.

public sealed class SGUIEvent

{

public static SGUIEvent current = null;

public int focus_tag { private set; get; }

public Vector2 mouse_position { private set; get; }

public SGUIEvent(int focus_tag , Vector2 mouse_position)

{

this.focus_tag = focus_tag;

this.mouse_position = mouse_position;

}

}

Code Sample 3.27: The implemtation of the SGUIEvent class.

Instead of creating an event for every single mouse event in the OnGUI() method, a widget can simplycheck if the mouse is contained in its bounding rectangle and if so create an SGUIEvent instance us-ing its tag and the current mouse position. This instance should then be stored in SGUIEvent.current

and SGUIEditorWindow will then use this to generate proper mouse events as we saw in Code Sam-ple 3.22. We created the method catchMouseDefault() for SGUIWidget as shown in Code Sample 3.28to have a default way of catching mouse events.

protected void catchMouseDefault(){

if (Event.current.type != EventType.Repaint && Event.current.type !=

EventType.Layout){

if (this.position.Contains(Event.current.mousePosition))

69

Page 71: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

SGUIEvent.current = new SGUIEvent(this.tag, Event.current.mousePosition);

}

}

Code Sample 3.28: The implementation of catchMouseDefault() providing a default way of catchingmouse events.

The addition of SGUIEvent and the moving around of code it caused has as extra advantage that allSCCD related code is now contained in the classes ClassDiagramEditorWindow, StatechartEditor-

window and SGUIEditorWindow. If the SCCD specific code from the latter would be moved to a newsubclass of SGUIEditorWindow, then all SGUI components could be used for different applicationsinside Unity that do not make use of SCCD at all. While this was not necessarily our aim it showsthat the middle layer has a modular final design.

3.8 Iteration 5: Final result

In section 3.6 we looked at the rather complex implementation of SGUIButton. The reason it wasso complex is because of the feature of having a button that could be turned on. As this featurewas no longer needed after the introduction of SGUIToolBar, the implementation of SGUIButton waschanged to simply make use of GUI.Button to both draw the button and detect when it gets clicked.This new implementation is shown in Code Sample 3.29. By setting SGUIEvent.current to null itmakes sure no other mouse events are generated besides the button-pressed event. Now that thewidget generates this event and there is no need to keep any state for the button, the SCCD classButton we saw in Code Sample 3.25 becomes obsolete and can be removed from the model. Thisreduces the size of the statecharts of any classes present in the model that make use of buttons as theyno longer need to create, activate and associate any Button instances. The only thing now needed tocreate a button, as with basically any other SGUI widget, is simply instantiating it and adding it to acontainer component that has the top level widget as ancestor.

protected override void OnGUI(){

if (GUILayout.Button(this.label , style))

{

SGUIEvent.current = null;

this.generateEvent("button_pressed", "input", this.tag, this.action);

}

}

Code Sample 3.29: The final implementation of SGUIButton’s OnGUI() function.

70

Page 72: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

3.8.1 Model Generation, Compilation and Saving

The main feature of the editor is to create executable code from an SCCD model. As we have accessto a compiler that can generate C# from models adhering to the SCCDXML formalism, we simplyneed to transform the model data in the editor to SCCDXML and feed that into the compiler. Theway we achieve this is by maintaining an instance of XDocument[Net], a class from the C# standardlibrary to create XML files, throughout the editing of a model and adapt it every time the user makesa change in the editor. If we make sure that this is SCCDXML compliant at all times, we can simplycall the save() method on this XDocument instance once the user decides to compile the model andpass the resulting file to the compiler.

Regarding the saving of a model, we will again just use the save() method of XDocument in combina-tion with a file path supplied by the user. However, in order to restore a model to the exact same stateas when it was created, extra info such as the positions and dimensions of the visual elements need tobe saved as well. While a lot of choices are available to serialize this data, by far the best option is tosimply store this information in extra tags and attributes in the SCCDXML file. This will not causeany problems with compiling, as the compiler will simply ignore these extra elements.

Figure 3.3: An example model created in the SCCD editor defining just two classes and one associa-tion.

In Figure 3.3 a useless but valid SCCD model is depicted with just two classes and one association.The file that gets generated upon saving is shown inCode Sample 3.30. As we can see, the positionof a class is stored in the attributes x and y. Together with the attributes w and h representing thedimensions of the class, we can exactly restore a class as the user saved it. Using the same method,also relations can be restored perfectly. The attributes start-id and end-id indicate which connectionpoints were used to draw the edge. As for the position of the label, the offset value is saved thatindicates the difference between the position calculated by the editor (the center between the twoconnection points) and the position the user dragged the label to. We use an offset value instead ofan absolute value so that the label would move accordingly when one of the involved classes changesposition. If control points were added by the user, they will be saved in separate <point> tags. Insubsection 3.8.2 we will look at how these values are saved and restored for transitions.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<diagram name="TestDiagram" author="">

71

Page 73: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<description >description </description >

<top>using UnityEngine; using Event = sccdlib.Event;</top>

<class name="ClassA" x="193" y="155" w="92" h="22" default="true">

<relationships >

<association min="0" max="1" class="ClassB" name="assocation -name"

x-offset="1" y-offset="-9" start -id="1" end-id="3" />

</relationships >

</class >

<class name="ClassB" x="446" y="155" w="87" h="23" default="false">

<relationships />

</class >

</diagram >

Code Sample 3.30: The file generated by the SCCD editor upon saving the model shown in Figure 3.3.

3.8.2 The Modelling of Transitions

In order to give a better idea of how the different components in the model cooperate and how theelements of a model are loaded and adapted, we will have a look at all the parts that are involved in theloading, creating, and editing of transitions in a statechart. The reason we pick this feature is becauseit can easily be deemed the most complex one of the editor and communicates with a lot of differentclasses in the model. When the user opens the SCCD editor, he is faced with an editor window of typeClassDiagramEditorWindow where a class diagram can be created. The moment the user decides topress the "Edit Statechart" button in the properties panel of a class, a new editor window will popup of type StateChartEditorWindow. In Figure 3.4 we can see this editor window with at the top atoolbar, on the right the properties panel and on the left the actual canvas with all the available types ofstates displayed. As we saw in subsection 3.6.4, StateChartEditorWindow’s open() function requiresas parameter the XElement instance which should represent the <scxml> tag of the class that is beingedited. This is passed on to the controller of the compiler statechart editor model, followed by startingits execution.

Figure 3.4: The statechart editor window with at the top a toolbar, on the right the properties paneland on the left the actual canvas with all the available types of states displayed.

72

Page 74: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

The model will start of creating the toolbar, the properties panel and the canvas. The canvas willthen determine which states and transitions need to be loaded using the <scxml> element. In CodeSample 3.31 we see the part of the constructor of Canvas that is responsible for this. It simplytraverses each level of states in the model and adds all the transitions to a list of XElements calledtransitions_to_load. In Code Sample 3.32 we then see how this list is used to actually create theproper Transition instances out of it. In the state transitions_loading there are two transitions. Ifthere are still transitions left to load the first transition will trigger, otherwise the second transitionwill bring the statechart to the listening state. This is basically an idle state meaning that the canvas isfully loaded and waiting for events.

this.states_to_load = new List <XElement >();

this.transitions_to_load = new List <XElement >();

this.state_xml_to_widget = new Dictionary <XElement , SGUICanvasElement >();

List <XElement > current_level_states =

this.statechart_xml.Elements("state").ToList();

while(current_level_states.Count > 0)

{

List <XElement > next_level_states = new List <XElement >(){};

for(int i=0; i<current_level_states.Count; i++)

{

XElement current_element = current_level_states[i];

states_to_load.Add(current_element);

this.state_xml_to_widget[current_element] = new SGUICanvasElement();

next_level_states.AddRange(current_element.Elements("state"));

this.transitions_to_load.AddRange(current_element.Elements("transition"));

}

current_level_states = next_level_states;

}

Code Sample 3.31: The part of the Canvas constructor that determines which states and transitionsneed to be loaded.

The other transition will pop a <transition> tag from the transitions_to_load property and will useit to create a Transition and SGUICanvasEdge instance. For the latter it needs both the widgets of thestart and end state of the transition. Getting the start state is trivial since it is just the parent XMLelement of the transition. For the end state however, a calculation has to be done using the target

attribute. This turned out to be rather simple as well, as we could use the same functionality as theSCCD compiler uses to determine and validate targets of a transition. Also the attributes start-id andend-id are passed on to the SGUICanvasEdge constructor and the resulting instance is send together

73

Page 75: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

with a create_instance event to the object manager to create the Transition instance. The <transition>

element is also passed as parameter as well as a positive boolean value to indicate that the transitionwas loaded and not newly created. In Code Sample 3.35 we see how this value is used to execute theproper initialization code in the constructor of Transition instances.

<state id="transitions_loading">

<transition target="../ loaded_transition_activation"

cond="this.transitions_to_load.Count > 0">

<script >

XElement transition_xml =

this.transitions_to_load[this.transitions_to_load.Count - 1];

this.transitions_to_load.RemoveAt(this.transitions_to_load.Count -

1);

SCCDUtility.assureAttribute(transition_xml , "target");

SCCDUtility.assureAttribute(transition_xml , "start -id", "0");

SCCDUtility.assureAttribute(transition_xml , "end-id", "0");

XElement start_xml = transition_xml.Parent;

XElement end_xml = SCCDUtility.getTransitionTarget(

this.statechart_xml , start_xml ,

transition_xml.Attribute("target").Value);

this.current_transition = new SGUICanvasEdge(

this.state_xml_to_widget[start_xml],

int.Parse(transition_xml.Attribute("start -id").Value),

this.state_xml_to_widget[end_xml],

int.Parse(transition_xml.Attribute("end-id").Value)

);

</script >

<raise scope="cd" event="create_instance">

<parameter expr=’"all_transitions"’ />

<parameter expr=’"Transition"’/>

<parameter expr=’this.current_transition ’ />

<parameter expr=’transition_xml ’ />

<parameter expr=’true ’ />

</raise >

</transition >

<transition target="../../ listening" cond="this.transitions_to_load.Count ==

0">

<script >

this.transitions_to_load = null;

this.state_xml_to_widget = null;

74

Page 76: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

</script >

</transition >

</state >

<state id="loaded_transition_activation">

<transition event="instance_created" target="../transitions_loading">

<parameter name="id" type="int"/>

<parameter name="association_name" type="String"/>

<script >

String association_path = String.Format("{0}[{1}]", association_name , id);

this.all_transitions_map[this.current_transition.tag] = id;

</script >

<raise scope="cd" event="associate_instance">

<parameter expr=’"."’/>

<parameter expr=’association_path + "/canvas"’ />

</raise >

<raise scope="cd" event="start_instance">

<parameter expr=’association_path ’ />

</raise >

</transition >

</state >

Code Sample 3.32: The state that actually creates the Transition instances that need to be loaded.

In the case of loading a transition, the position and value of the label are set and any control pointsthat were saved are added to the edge widget. Also an is_loading property is set to indicate to thestatechart that it can skip the creation phase and go straight to the active state. This state in turnhas two substates selected and not_selected. Transitioning between the latter and the first happensupon clicking the label of the transition, while moving in the other direction happens when receivingan unselect event. Entering the selected state results in a color change of the label to green and thetransition properties panel being activated. In this property panel the label can be changed as well asdefining which actions should be executed when the transition is triggered.

The selected state also acts upon a key-down event, if the key being pressed is the delete key. This willsimply result in the transition being deleted by sending a delete_transition event to the canvas withits edge widget as parameter. Lastly a transition will also be triggered if the user drags the left-mousebutton over the label, this will simply cause the label to be repositioned and the attributes x-offset andy-offset being updated.

<state id="transition_creation" initial="activation">

<state id="activation">

<transition event="instance_created" target="../creating">

<parameter name="id" type="int"/>

75

Page 77: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<parameter name="association_name" type="String"/>

<script >

String association_path = String.Format("{0}[{1}]", association_name ,

id);

this.all_transitions_map[this.current_transition.tag] = id;

</script >

<raise scope="cd" event="associate_instance">

<parameter expr=’"."’/>

<parameter expr=’association_path + "/canvas"’ />

</raise >

<raise scope="cd" event="start_instance">

<parameter expr=’association_path ’ />

</raise >

</transition >

</state >

<state id="creating">

<!-- Mouse released on canvas, so transition gets cancelled.-->

<transition event="transition_cancelled" target="../../ default">

<script >

String association_path = String.Format("all_transitions [{0}]",

this.all_transitions_map[this.current_transition.tag]);

this.all_transitions_map.Remove(this.current_transition.tag);

</script >

<raise scope="cd" event="delete_instance">

<parameter expr="association_path"/>

</raise >

<script >

this.current_transition = null;

</script >

</transition >

<!-- Event received from a state, that the edge end got released over it.

-->

<transition event="transition_end" target="../../ default">

<parameter type="XElement" name="end_state_xml"/>

<script >

String association_path = String.Format("all_transitions [{0}]",

this.all_transitions_map[this.current_transition.tag]);

this.current_transition = null;

</script >

<raise event="transition_finished" target="association_path">

76

Page 78: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<parameter expr="end_state_xml"/>

</raise >

</transition >

<!-- Event received from a state, that the edge end is currently hovering

it. -->

<transition event="transition_end_over_state" target=".">

<parameter name="element" type="SGUICanvasElement"/>

<parameter name="position" type="Vector2"/>

<script >

String association_path = String.Format("all_transitions [{0}]",

this.all_transitions_map[this.current_transition.tag]);

</script >

<raise event="transition_end_over_state" target="association_path">

<parameter expr="element"/>

<parameter expr="position"/>

</raise >

</transition >

</state >

<onexit >

<raise event="transition_creation_stopped" target=’"all_states"’/>

</onexit >

</state > <!-- end of transition creation -->

Code Sample 3.33: The state entered by the Canvas instance when a transition is being created.

The process of actually creating a new transition involves a lot more steps. In order for a user to createa transition, he should drag the right mouse button from one state to another. If a state detects that itis being clicked by this mouse button it will send a create_transition event to the canvas. The canvaswill then use the source state and the mouse position to create an edge widget and ultimately startthe creation of a Transition instance, this time with a negative value for the third parameter indicatingthat it concerns a newly created transition. The canvas then enters the transition_creation state asshown in Code Sample 3.33. A similar state with the same name is entered by all the State instanceson the canvas. As can be seen in Code Sample 3.34 a state will signal a transition_end event if themouse button is released over it to indicate that it should be the end state of the transition. This alsomeans that the state will leave the transition creation state, which it also does when receiving thetransition_creation_stopped event. Lastly it will narrow-cast a transition_end_over_state event whenthe mouse is simply being dragged over it.

After having activated the Transition instance, the canvas goes into the creating state where it actsupon those events send by the states and the transition being created. The canvas will simply for-

77

Page 79: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

ward the transition_end_over_state and transition_end events to the transition, and will delete it uponreceiving the transition_cancelled event. Upon leaving the creating state, the canvas will send atransition_creation_stopped event to all states so they will leave their transition creation state as well.

<state id="transition_creation">

<!-- Signal that this is a valid end connection for the transition being

created. -->

<transition event="right -mouse -up" port="input" cond="tag == this.widget.tag"

target="../default">

<parameter name="tag" type="int"/>

<parameter name="position" type="Vector2"/>

<raise event="transition_end" target=’"canvas"’>

<parameter expr="this.state_xml"/>

</raise >

</transition >

<!-- Signal that a possible end connection is targeted. -->

<transition event="right -mouse -drag" port="input" cond="tag ==

this.widget.tag" target=".">

<parameter name="tag" type="int"/>

<parameter name="position" type="Vector2"/>

<raise event="transition_end_over_state" target=’"canvas"’>

<parameter expr="this.widget"/>

<parameter expr="position"/>

</raise >

</transition >

<!-- Transition creation terminated. Return to default state. -->

<transition event="transition_creation_stopped" target="../default"/>

</state >

Code Sample 3.34: The state entered by State instances when a transition is being created.

During creation, a Transition instance can reside in two different states as shown in Figure 3.5. Thefirst and default state called state_drag is active when the user is currently dragging over a state.This indicates that when the user would stop dragging the edge, the transition would be successfullycreated using the state that is currently being hoovered on as end state. On the other hand, in thesecond state canvas_drag releasing the mouse button would result in the transition being cancelled.

78

Page 80: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

When the transition creation succeeds, both the end-id and the target XML attributes are set. For thelatter a function is used that will keep moving upwards in the XML hierarchy until the root is reached,while combining the different names of the states along the path to become an absolute state referencepath to the target state. Using setControlPoints() <point> tags are created for each control point.

Figure 3.5: The visual representation of the Transition class’ statechart.

When dragging over the canvas, a control point can be added by clicking the left mouse button. Onecan be removed regardless of which of the two states the statechart is currently in, by clicking themiddle mouse button. The transition that takes care of this, has as target a history state. The reasonwe make use of a history state here is so that after the control point is deleted, the statechart will enterthe same state as it was in before. We also use a control point for the feature where the end of theedge follows the mouse. When leaving the canvas_drag state, we remove the end point and add acontrol point at the mouse’s current position. When a drag occurs on the canvas, we delete the lastcontrol point and add a new one again using the current position of the mouse. Upon entering thecanvas_drag state, we remove the last control point and add an end point. This end point will be theconnection point of the state that is closest to the mouse position, creating a snapping effect. Thiscalculation is done for each transition_end_over_state event, in order to allow to the user to changethe connection point.

<class name="Transition">

<relationships >

79

Page 81: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<association class="Canvas" name="canvas" max="1"/>

</relationships >

<attribute type="SGUICanvasEdge" name="edge_widget"/>

<attribute type="XElement" name="transition_xml"/>

<attribute type="bool" name="is_loading"/>

<constructor >

<parameter type="SGUICanvasEdge" name="edge_widget"/>

<parameter type="XElement" name="xml"/>

<parameter type="bool" name="is_loading"/>

<body >

this.edge_widget = edge_widget;

this.is_loading = is_loading;

if (is_loading)

this.loadTransition(xml);

else

this.newTransition(xml);

</body >

</constructor >

<destructor >

<body >

this.edge_widget.delete();

this.transition_xml.Remove();

</body >

</destructor >

<method type="void" name="loadTransition">

<parameter type="XElement" name="transition_xml"/>

<body >

this.transition_xml = transition_xml;

SCCDUtility.assureAttribute(transition_xml , "x-offset", "0");

SCCDUtility.assureAttribute(transition_xml , "y-offset", "0");

SCCDUtility.assureAttribute(transition_xml , "label");

this.edge_widget.setLabel(transition_xml.Attribute("label").Value);

this.edge_widget.moveLabel(new Vector2(

float.Parse(transition_xml.Attribute("x-offset").Value),

float.Parse(transition_xml.Attribute("y-offset").Value)

));

foreach(XElement point in this.transition_xml.Elements("point"))

{

this.edge_widget.addControlPoint(new Vector2(

float.Parse(point.Attribute("x").Value),

float.Parse(point.Attribute("y").Value)

));

}

</body >

80

Page 82: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

</method >

<method type="void" name="newTransition">

<parameter type="XElement" name="state_xml"/>

<body >

//state_xml is parent , create XElement for state

this.transition_xml = new XElement("transition",

new XAttribute("event", ""),

new XAttribute("port", ""),

new XAttribute("target", ""),

new XAttribute("after", ""),

new XAttribute("label", ""),

new XAttribute("x-offset", 0),

new XAttribute("y-offset", 0),

new XAttribute("start -id", this.edge_widget.start.point_id.ToString()),

new XAttribute("end-id", 0)

);

state_xml.Add(this.transition_xml);

</body >

</method >

<method type="void" name="setControlPoints">

<body >

foreach( XElement point in this.transition_xml.Elements("point"))

{

point.Remove();

}

foreach(Vector2 point in this.edge_widget.control_points)

{

this.transition_xml.Add(new XElement(

"point",

new XAttribute("x", point.x),

new XAttribute("y", point.y)

));

}

</body >

</method >

<scxml initial="setup">

<state id="setup">

<transition cond="!this.is_loading" target="/creation"/>

<transition cond="this.is_loading" target="/active"/>

</state >

<state id="creation" initial="state_drag">

<history type="deep" id="history"/>

<transition event="middle -mouse -down" port="input" target="history">

<parameter name="tag" type="int"/>

81

Page 83: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<parameter name="position" type="Vector2"/>

<script >

if (this.edge_widget.hasControlPoints())

{

this.edge_widget.popControlPoint();

this.edge_widget.popControlPoint();

this.edge_widget.addControlPoint(position);

}

</script >

</transition >

<!-- EDGE END IS CURRENTLY OVER A STATE -->

<state id="state_drag">

<transition event="transition_finished" target="/active/selected">

<parameter type="XElement" name="end_state_xml"/>

<script >

this.transition_xml.Attribute("end-id").Value =

this.edge_widget.end.point_id.ToString();

this.transition_xml.Attribute("target").Value =

SCCDUtility.createTargetString(end_state_xml);

this.setControlPoints();

</script >

</transition >

<transition event="transition_end_over_state" target=".">

<parameter name="element" type="SGUICanvasElement"/>

<parameter name="position" type="Vector2"/>

<script >

this.edge_widget.createEndPoint(element , position);

</script >

</transition >

<!-- Mouse dragging over canvas -->

<transition event="right -mouse -drag" port="input"

cond="this.edge_widget.canvas.tag == tag" target="../canvas_drag">

<parameter name="tag" type="int"/>

<parameter name="position" type="Vector2"/>

<script >

this.edge_widget.addControlPoint(position);

this.edge_widget.removeEndPoint();

</script >

</transition >

</state >

<!-- EDGE END IS CURRENTLY ON CANVAS (NOT OVER A STATE) -->

<state id="canvas_drag">

<transition event="transition_end_over_state" target="../state_drag">

<parameter name="element" type="SGUICanvasElement"/>

82

Page 84: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<parameter name="position" type="Vector2"/>

<script >

this.edge_widget.popControlPoint();

this.edge_widget.createEndPoint(element , position);

</script >

</transition >

<transition event="right -mouse -up" port="input"

cond="this.edge_widget.canvas.tag == tag" target="../../ destroyed">

<parameter name="tag" type="int"/>

<raise event="transition_cancelled" target=’"canvas"’/>

</transition >

<transition event="right -mouse -drag" port="input"

cond="this.edge_widget.canvas.tag == tag" target=".">

<parameter name="tag" type="int"/>

<parameter name="position" type="Vector2"/>

<script >

this.edge_widget.popControlPoint();

this.edge_widget.addControlPoint(position);

</script >

</transition >

<transition event="left -mouse -down" port="input"

cond="this.edge_widget.canvas.tag == tag" target=".">

<parameter name="tag" type="int"/>

<parameter name="position" type="Vector2"/>

<script >

this.edge_widget.popControlPoint();

this.edge_widget.addControlPoint(position);

this.edge_widget.addControlPoint(position);

</script >

</transition >

</state >

</state > <!-- end of creation state -->

<state id="active" initial="not_selected">

<state id="not_selected">

<transition event="left -mouse -down" port="input" cond="tag ==

this.edge_widget.tag" target="../selected">

<parameter name="tag" type="int"/>

<parameter type="Vector2" name="position"/>

<raise event="unselect" target=’"canvas"’>

<parameter expr=’this.edge_widget.tag ’/>

</raise >

</transition >

</state >

<state id="selected" initial="listening">

83

Page 85: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<onentry >

<script >

this.edge_widget.setLabelStyle("greentitle");

</script >

<raise event="set_transition_properties"

target=’"canvas/window/properties_panel"’>

<parameter expr=’this.transition_xml ’ />

<parameter expr=’this.edge_widget ’ />

</raise >

</onentry >

<onexit >

<script >

this.edge_widget.resetLabelStyle();

</script >

<raise event="reset_panel" target=’"canvas/window/properties_panel"’/>

</onexit >

<state id="listening">

<transition event="unselect" target="../../ not_selected"

cond="this.edge_widget.tag != except_tag">

<parameter type="int" name="except_tag"/>

</transition >

<transition target="/destroyed" port="input" event="key-down"

cond="key_code == KeyCode.Delete">

<parameter type="KeyCode" name="key_code"/>

<raise event="remove_transition" target=’"canvas"’>

<parameter expr="this.edge_widget"/>

</raise >

</transition >

<transition target="." port="input" event="left -mouse -drag" cond="tag

== this.edge_widget.tag || tag == this.edge_widget.canvas.tag">

<parameter type="int" name="tag"/>

<parameter type="Vector2" name="position"/>

<parameter type="Vector2" name="delta"/>

<script >

this.edge_widget.moveLabel(delta);

this.transition_xml.Attribute("x-offset").Value =

this.edge_widget.label_offset.x.ToString();

this.transition_xml.Attribute("y-offset").Value =

this.edge_widget.label_offset.y.ToString();

</script >

</transition >

</state >

</state >

</state >

84

Page 86: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<state id="destroyed"/>

</scxml >

</class >

Code Sample 3.35: The Transition class of the SCCD model for the statechart editor.

85

Page 87: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

4Example Case : Tank Wars

Once we obtained a fully working SCCD editor in Unity, we wanted to show what it is capable ofby building a game that makes use of modelled behaviour. More specifically we created a tank gamesimilar to the one in [Jon14] where the player controls a tank to battle against one or more computer-controlled tanks. The benefit of creating a similar game is that we can reuse the models, both for theNPC and the player tank, that were developed in [Jon14]. The only thing we had to do was recreatethese models using the SCCD editor and change the platform specific action code.

The game, shown in Figure 4.1, makes use of rather complex input controls to control the playertank, where the body and the turret of the tank have to be managed separately. This makes not onlythe game-play more interesting but helps us in showing that, next to artificial intelligence, handlingfairly complex input is also a good use case for software modelling. In Code Sample 4.1 we seethe script that should be attached to a game object in order to enable SCCD modelled behaviour.As we saw before in subsection 1.4.2, this will allow the user to open the SCCD editor and createa model to define the behaviour of the game object. Once the user presses Compile & Deploy, thesccd_namespace property of the SCCDScript is set to the name of the diagram. Next, the compilerwill generate code from the model using this name as namespace to encapsulate all generated classes.The property is then used in the Awake function, which is called by Unity during the initializationphase of the game, to instantiate the correct Controller class. The matching game object is passed assole constructor parameter so that it is possible to actually perform actions on the game object from

86

Page 88: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 4.1: A screenshot of the demo game.

inside the model.

We also see in Code Sample 4.1 how input events are generated. In the Update() function any relevantinput controls are polled, as we saw in subsection 1.3.2, and corresponding events are generated. Thisis followed by updating the controller using the deltaTime property we explained in section 3.4. TheSCCDScript will also generate a fixed-update event every time the FixedUpdate function of the gameobject gets called. In contrast to the Update function, this method gets called in a fixed interval and issend right before Unity makes any physics calculations. For this reason, this event should be used tomake any adjustments to the game object if it makes use of any physics components.

public class SCCDScript : MonoBehaviour {

public string sccd_namespace;

public string xml_file;

private sccdlib.GameLoopControllerBase controller;

void Awake () {

this.controller = (sccdlib.GameLoopControllerBase)

Activator.CreateInstance(Type.GetType(string.Format("{0}. Controller",

this.sccd_namespace)), new object[]{this.gameObject});

}

87

Page 89: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

void Start () {

this.controller.start();

}

void Update () {

this.generateInputEvents();

this.controller.update(Time.deltaTime);

}

void FixedUpdate() {

this.controller.addInput(new sccdlib.Event("fixed -update", "engine", new

object[] {

Time.deltaTime

}));

this.controller.update(0);

}

void inputKey(KeyCode key, string pressed_event , string relesed_event)

{

if (Input.GetKeyDown(key))

this.controller.addInput(new sccdlib.Event(pressed_event , "input"));

if (Input.GetKeyUp(key))

this.controller.addInput(new sccdlib.Event(relesed_event , "input"));

}

void generateInputEvents() {

this.inputKey(KeyCode.W, "up-pressed", "up-released");

this.inputKey(KeyCode.S, "down -pressed", "down -released");

this.inputKey(KeyCode.A, "left -pressed", "left -released");

this.inputKey(KeyCode.D, "right -pressed", "right -released");

this.inputKey(KeyCode.LeftArrow , "arrow -left -pressed",

"arrow -left -released");

this.inputKey(KeyCode.RightArrow , "arrow -right -pressed",

"arrow -right -released");

this.inputKey(KeyCode.UpArrow , "arrow -up-pressed", "arrow -up-released");

}

}

Code Sample 4.1: The script that enables SCCD modelled behaviour when attached to a game object.

In section 4.1 we will look at the model for the user-controlled tank, followed by a detailed descriptionof the computer-controlled tank in section 4.2. We will see that the designs are simple but effectiveand that the compiled models integrate perfectly with the engine resulting in a stable game application.

88

Page 90: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

4.1 User-Controlled Tank

The model for the user-controlled tank is responsible for handling both the user-input and the corre-sponding actions that should be performed. In Figure 4.2 we see the class diagram of the model. Itconsists out of a default (denoted by the italic style of its name) class Tank that is associated with aBody and a Turret class. The sole purpose of the Tank class is to instantiate instances of both the otherclasses as its statechart shows in Figure 4.3. It does this by generating an appropriate create_instance

event upon entering one of the two creation states. The corresponding instance_created event is thenused to activate the instance and advance to the next state. As Tank is the default class of the diagram,it will receive the tank game object as constructor parameter upon creation and it will pass this on tothe other instances in the diagram so that they can adjust the position and rotation of the tank.

Figure 4.2: The class diagram of the model defining the user-controlled tank’s behaviour.

Figure 4.3: The statechart of the Tank class.

In Figure 4.4 we see the model of the Turret class. A parallel state can be seen, containing threesub-states (or orthogonal regions). The bottom two orthogonal regions are responsible for both firinga bullet and keeping track of the reload time. This is done by entering the unloaded state once a bulletis fired which will ignore any shoot events. This state has just one transition which gets triggeredafter the reload time has passed, only then the tank will be able to shoot another bullet. The transitionalso casts a loaded event in case the user was holding the fire button, so that a bullet can be firedimmediately. The orthogonal region at the top will simply keep track of which buttons the user ispressing regarding the rotation of the turret. Upon receiving the fixed-update event, it will adjust theturret’s rotation according to which sub-state is active. The Body class works in the exact same wayas this last orthogonal region, but will instead use two of these to control the position of the body onthe one hand and the rotation on the other.

89

Page 91: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 4.4: The statechart of the Turret class.

4.2 Computer-Controlled Tank

The model for the NPC is based on the findings in Model-based Design of Computer-Controlled GameCharacter Behavior [JK07]. They propose a layered class architecture, as can be seen in Figure 4.5.Input arrives at the classes in the sensors layer and output is generated in the actuators. These twolayers have the lowest level of abstraction, they closely correspond to the actual components of thetank. The layers in the middle on the other hand, model the high-level goal of the NPC. They adjuststate based on the received events from the upper layers, while generating events in order to achievethe current goal.

As with the user-controlled tank we will look at the different classes in the model separately anddescribe what each statechart does. Since the default class is similar to the one of the model for theuser-controlled tank, it only differs in the number of instances that have to be created and associated,we will skip it and immediately start with the sensor layer and work our way down the hierarchy tothe actuators.

The Radar component as shown in Figure 4.6 is a sensor that will announce the position of the closest

90

Page 92: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 4.5: The layered architecture used to model the tank NPC.

enemy, if there is one in the range of the tank. The very trivial statechart starts in the no_enemy stateand continuously checks whether an enemy is visible. Once an enemy is spotted, the transition toenemy_in_sight is triggered, causing an enemy_sighted event to be narrow-casted to both the Enemy-

Tracker and the PilotStrategy. Once in the enemy_in_sight state, the component will keep checkingthe position of the enemy tank for every fixed-update it receives. If the enemy tank is still visible, theobserved position is sent to the EnemyTracker, otherwise the transition to no_enemy is fired togetherwith the narrow-casting of an enemy_out_of_sight event to the EnemyTracker.

Figure 4.6: The statechart of the Radar class.

In Figure 4.7 we see the statechart of the memorizer called EnemyTracker. As its name suggest itwill simply keep track of the enemy position using the information from the Radar. It starts in a statewhere it has no enemy to track. Once an enemy_sighted event is received however, the statechartwill save the position and advance to the enemy_pos_known state. For every subsequent enemy_pos

event, the received position is compared to the saved position. If these are not the same value, anenemy_pos_changed event is sent to the AttackPlanner and the memorized position is updated. Uponreceipt of an enemy_out_of_sight event from the Radar, the state enemy_pos_unsure is entered. While

91

Page 93: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

in this state, the current saved position is the position where the enemy tank was last seen beforedisappearing. Remembering this position is useful as it can be used to go look for the enemy. Itis however no longer relevant once a destination_reached event has been received from one of theupper layers. In this case the no_enemy state will be entered after sending an enemy_lost event to theAttackPlanner.

Figure 4.7: The statechart of the EnemyTracker class.

If one wonders why this memorizer is not just combined with the Radar, think of a situation wheremultiple sensors are available. There could for instance be a radar in the front of the tank and one inthe back, even information received from ally tanks could be considered a sensor. In that situation itdefinitely makes sense to have just one separate component responsible for tracking the position of theenemy. With the technique we use in this demo, we want to show that it is possible to create complexand realistic behaviour for NPCs while at the same time keeping an easy-to-understand design.

The PilotStrategy component shown in Figure 4.8 is a strategic decider. It determines which of thetwo available strategies, exploring or attacking, should be ensued. The NPC starts in the exploring

state (sending an explore event to the ExplorePlanner upon entering) and transitions to the attacking

state upon receiving the enemy_sighted event from the Radar. The latter will also cause an attack

event to be send to the AttackPlanner. The statechart will return to the exploring state if an event isreceived that indicates that the enemy is lost.

For both of the strategies a separate tactical decider is present in our model. On the one hand thereis the ExplorePlanner which will simply generate new destinations as long as the NPC is in explore-mode. On the other hand we have the AttackPlanner, of which the statechart is depicted in Figure 4.9.The planner starts in an idle state and waits for an attack event to transition to the attacking state. Thisevent supplies the position of the enemy, which the planner will forward to the PathFinder in orderto set as new destination and to the TurretSteering executor as new target to aim for. The parallelstate attacking controls both the high-level movement of the tank as well as the decision on when to

92

Page 94: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 4.8: The statechart of the PilotStrategy class.

shoot. The planner keeps getting informed about the enemy’s position and will set new destinationsaccordingly as well as change the point to aim for. When the enemy gets out of sight, the plannerinforms the TurretSteering executor to interrupt aiming. In the shooting orthogonal region we seethat a shot will be fired upon receiving the ready_to_shoot event. This is followed by entering theunloaded state. Only after the reload time has passed, the statechart will advance to the loaded state,allowing the NPC to shoot again.

Figure 4.9: The statechart of the AttackPlanner class.

Another strategic decider can be seen in Figure 4.10. The PathFinder translates destinations, re-quested by one of the other strategic deciders, into a path of way-points. In the default idle state, thecomponent either expects a waypoint_reached event or a new_destination event. If the latter is thecase and the PathFinder decides that the newly received destination is sufficiently different than thelast destination for which a path was set (if any), then a new set of way points is calculated and thecheck_points state is entered. In this state either the next way-point is sent to the Steering executor or

93

Page 95: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

a destination_reached event is broadcast if no more way-points are left.

Figure 4.10: The statechart of the PathFinder class.

Two executors are present in the model that translate the high level commands received from thestrategic layers into events that the actuators can understand. While the TurretSteering executor isresponsible for generating events for the TurretControl actuator, the Steering executor will send eventsmainly to the MotorControl actuator. In Figure 4.11 the TurretSteering executor is displayed. It startsin an idle state and begins steering once it receives an aim_at event. The target position suppliedwith the aim_at event is stored and then used to calculate the angle between the turret and the target.Depending on the result, appropriate events are generated to adjust the tank’s angle with as goal todirectly face the target. For each fixed-update event the statechart receives, it will perform the samesteps again so that it can actually align with the target after a number of iterations. If it receivesan updated position of the target, it simply uses this new position for the angle calculations. Whenthe enemy tank goes missing, the executor transitions back to the idle state and will narrow-cast astop_turning event to the TurretControl actuator.

The last layer of our model contains two actuators, one for the motor (body) and one for the turret ofthe tank. As these are very similar, we only look into the TurretControl actuator which can be seenin Figure 4.12. As the actuators are responsible for executing the actions they receive from the upperlayers, they should have access to the tank object they need to adapt and hence this object is suppliedas parameter for their constructors. Since movement does not happen continuously but in discretesteps, the actuator components only execute a movement action on the receipt of a fixed-update event.What action should be executed is determined by the current state of the actuator’s statechart. Thisis very similar to the model we saw for the user-controlled tank. The difference is that the state inthe user-controlled tank is determined by user-input, while with the NPC it depends on the events itreceives from the upper layers. For example after processing the event turn_right, the current state

94

Page 96: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 4.11: The statechart of the TurretSteering class.

will be turning_right. If subsequently a fixed-update event is generated, the NPC will adjust the angleof the turret slightly to the right.

95

Page 97: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Figure 4.12: The statechart of the TurretControl class.

96

Page 98: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

5Conclusion

The goal of this thesis was to demonstrate the usefulness of the general purpose visual modellingformalism SCCD. We decided to do this by modelling the behaviour of NPCs for a game made in acommercial engine. We obtained a fully working and stable game application with the use of modelsthat are intuitive and easy to understand. We also created a visual editor environment inside Unityto facilitate the game development process. By developing this editor with SCCD as well, we alsoproved the general-purpose aspect of the formalism. Furthermore we showed that integration withUnity becomes simple once a middle layer is obtained at the right level of abstraction.

During the development of the visual editor we also noticed that the SCCD formalism could heavilybenefit from certain adjustments and extra features to be an even more attractive choice for softwaredevelopers. We have made a list of possible improvements and explained them in more detail insection 5.1.

5.1 SCCD improvements

During this thesis we made extensive use of the SCCD formalism and its execution environment forthe creation and testing of the SCCD editor and the game models. While doing this we encounteredseveral issues with SCCD and different areas that could use some improvements. In this section wewill highlight these and suggest a possible solution.

97

Page 99: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

5.1.1 Conditional Action Statements

In Code Sample 5.1 we see the transition from the statechart editor that is responsible for removing astate from the canvas. Next to deleting the State instance, it also deletes any transition that has the stateas either begin or end point. In order for us to be able to do this, we made use of a simple hack wherewe have the condition of an if statement in a first <script> tag together with the opening brace. Thisis then followed by the <raise> tag which contains the event that should be raised if the if conditionholds. Finally we end with another <script> tag just to close the curly brackets. While this works inthe intended way, it definitely looks ugly and is not guaranteed to work in for instance languages thatdo not make use of curly brackets. For this reason it would be interesting to have constructs added tothe SCCD formalism that support both conditional and loop statements.

<transition event="remove_state" target=".">

<parameter name="remove_state" type="SGUICanvasElement"/>

<raise scope="cd" event="delete_instance">

<parameter expr=’String.Format("all_states [{0}]",

this.all_states_map[remove_state.tag])’ />

</raise >

<script >

this.all_states_map.Remove(remove_state.tag);

foreach (SGUICanvasEdge edge in this.canvas_widget.edges)

{

if (edge.start.canvas_element == remove_state || edge.end.canvas_element

== remove_state)

{

//remove edge by sending remove_transition event to canvas

</script >

<raise scope="local" event="remove_transition">

<parameter expr=’edge ’ />

</raise >

<script >

}

}

</script >

</transition >

Code Sample 5.1: The transition from the statechart editor that is responsible for removing a statefrom the canvas. It makes use of a hack to only raise an event if a certain condition holds.

98

Page 100: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

5.1.2 Else Target

Another feature that SCCD lacks is the possibility of defining an "else" target for a transition. Toexplain what we mean by this, we will look at the setup state of Code Sample 3.35. Two transitionsare defined here, both evaluating the is_loading property. If this property is positive the active stateis entered, else the creation state is entered. It is exactly this last sentence we would like to defineliterally with a SCCD construct instead of having to evaluate the same property twice. While in thisexample it does not cause that big of a performance hit, it might have a noticeable impact if a verycomplex calculation is used as condition instead. In Code Sample 5.2 we suggest a possible syntaxfor defining conditional transition targets.

<transition event="x">

<if cond="a<=0" target="state_U">

<log>a is less than or equal to 0.</log>

</if>

<elif cond="a<2" target="state_V">

<log>a is bigger than 0 and smaller than 2. </log>

</elif >

<else target="state_W">

<log>a is bigger than or equal to 2.</log>

</else >

</transition >

Code Sample 5.2: A possible syntax we suggest for supporting conditional transition targets.

5.1.3 Exiting a Parallel State

An error we discovered with the runtime platform is illustrated in Code Sample 5.3. When the tran-sition to state c is triggered, the execution code simply throws an exception. The reason behind thisis because of the way parallel execution is simulated. If the first transition is triggered the structuremaintaining the current state is changed, effectively removing the parallel state and thus also stateb. The parallel execution however will still check if any transitions are triggered in state b and in itssubstates. What happens then is that state b will try to the access information from the current statedata structure to see which one of the states y and z is active. Because this requested information isalready removed, an index error is thrown.

<scxml initial="parallel">

<parallel id="parallel">

<state id="a">

<state id="x">

99

Page 101: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

<transition event="w" target="/c"/>

</state >

</state >

<state id="b" initial="y">

<state id="y"/>

<state id="z"/>

</state >

</parallel >

<state id="c"/>

</scxml >

Code Sample 5.3: Example statechart showing the error currently present in the simulation of parallelstates.

While we found ways around this and thus was not a problem blocking us from developing ourapplications, it certainly is an issue that should be fixed. A question that should be asked is thatwhen this first transition triggers an exit of the parallel state, should any other transition in the sub-states still be executed? If so, what if other transitions cause exits as well? If not, how will wedeal with priority of transitions? Presumably a method should be used, similar to the detection ofindeterministic transitions in a single state.

5.1.4 Association Mappings

In subsection 3.5.1 we introduced dictionaries to map widget tags onto association identifiers so thatwe would be able to adapt the relations between instances. It turns out that we used this methodmultiple times throughout the creation of the editor and we believe that this is the most convenientway to solve the issue of rearranging associations. Therefore it would make sense to include thismechanism in SCCD to make modelling even more straightforward. As currently the object managergenerates a unique identifier upon associating an instance, we could easily supply such an identifierourselves by passing it as parameter with the create_instance and associate_instance event. In ourcase this would result in a much slimmer model where we could send the tag of a widget as identifierupon association and no longer have to maintain dictionaries. When relations then need to be adjusted,we could simply use the tags of the widgets immediately.

5.1.5 Private Ports

Currently SCCD only supports public input ports. This means that when an event is sent to a port,that every single instance in the model will receive this event regardless of whether they will actuallyuse it or not. This could be a big bottleneck for rather large models. An improvement that could bemade is by creating a mapping structure at compile time, that maps an input port to the classes thatactually make use of that input port. When an event then gets added to the controller, it should check

100

Page 102: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

the port and only send it to those instances that actually need it. This however still does not allow anevent to be sent to just a single instance. For this we would like to introduce a concept called private

ports. Ultimately it should be possible to send an event to a single instance in the diagram using theseports.

101

Page 103: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

Bibliography

[AIG13] Guerilla Games AIGameDev. Capture The Flag, 2013. http://aigamedev.com/open/coverage/ctf-report/.

[Art05] Electronic Arts. EA Tank Wars, 2005. http://www.info.ea.com/company/

company-tw.php/.

[BAA+13] Jim Barnett, Rahul Akolkar, RJ Auburn, Michael Bodell, Daniel C. Burnett, Jerry Carter,Scott McGlashan, Torbjorn Lager, Mark Helbing, Rafah Hosn, T.V. Raman, KlausReifenrath, No’am Rosenthal, and Johan Roxendal. State Chart XML (SCXML): StateMachine Notation for Control Abstraction. http://www.w3.org/TR/scxml/, 2013.

[CD99] James Clark and Steve DeRose. XML Path Language. W3C Recommendation, 1999.

[Cor] Valve Corporation. Source Engine. http://www.valvesoftware.com/.

[Cry] Crytek. CryEngine. http://cryengine.com/.

[DD09] Hans Vangheluwe Denis Dubé, Jacob Beard. Rapid Development of Scoped User Inter-faces, 2009.

[DKVV11] Christopher Dragert, Jörg Kienzle, Hans Vangheluwe, and Clark Verbrugge. Generatingextras: Procedural AI with statecharts. Technical report, Technical Report SOCS-TR-2011.1, 2011.

[Dub06] Denis Dubé. Graph Layout for Domain-Specific Modeling. Master’s thesis, McGillUniversity, 2006.

[Goo11] Google. AI Challenge Ants, 2011. http://ants.aichallenge.org/.

[Har87] David Harel. Statecharts : a visual formalism for complex systems. Science of Computer

Programming, 8(3):231 – 274, 1987.

[Inc] Epic Games Inc. Unreal Engine. https://www.unrealengine.com/.

102

Page 104: A visual modelling environment for Statecharts and …msdl.cs.mcgill.ca/people/glenn/thesis.pdf(NPCs) in the commercial game engine Unity. Since visual modelling works best in combination

[JK07] Hans Vangheluwe Jörg Kienzle, Alexandre Denault. Model-based design of computer-controlled game character behavior. Lecture Notes in Computer Science, 4735, 2007.

[Jon14] Glenn De Jonghe. Statecharts and Class Diagram XML: A general-purpose textual mod-elling formalism, 2014. Research Internship, University of Antwerp.

[Kom] Jari Kommpa. Sol on Immediate Mode GUIs (IMGUI). http://iki.fi/sol/imgui/.Accessed: 2015-03-20.

[Net] Microsoft Developer Network. XDocument Class (System.Xml.Linq). https://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.aspx.

[OMG05] OMG. UML 2.0 superstructure specification. Technical report, Object ManagementGroup, 2005.

[Teca] Unity Technologies. Unity. https://unity3d.com.

[Tecb] Unity Technologies. Unity Editor Extensions Manual. http://docs.unity3d.com/

Manual/ExtendingTheEditor.html.

[Tecc] Unity Technologies. Unity Scripting API. http://docs.unity3d.com/

ScriptReference/index.html.

[Uni] Carnegie Mellon University. Panda3D. https://www.panda3d.org/.

[Wuy12] Gino Wuytjens. Modelling and Transformation of Non-Player Characters’ Behaviour inModern Computer Games. Master’s thesis, University of Antwerp, 2012.

103