P3-SDK 0.9
P3 Software Development Kit
Loading...
Searching...
No Matches
The GUI Layer

Scenes of an App

A Unity app is a collection of scenes. Each scene is a 3D graphical environment in which the action plays out. Because Unity is a video game platform, other resources may refer to scenes as "levels". In P3 development, the "Scene" is also the abstraction that consists of presenting the player with a visual environment and related playfied/display interactions, analogous to a mode in traditional pinball play. From a development perspective, each logical Scene consists of both a Unity/Presentation component (the SceneController) and a Mode-side logic component (the SceneMode).

A P3 app starts with a fairly empty Bootstrap scene which starts the P3Controller so that the modes can be executed.

The following scene is the Attract scene. This is what the player sees when they are in the app but a game isn't being played yet.

When a game starts, it goes to the first scene of the game, known as the Home scene.

P3SA implements all of the above scenes.

The Home scene can be renamed to suit your app. For example, Lexy Lightspeed's home scene is internally named "Map".

The Home scene is also not likely to be the only scene in your game. For example, Lexy Lightspeed's Map/Home scene causes other scenes to be loaded, such as the Warehouse, Weapons Lab and Cabin scenes.

Anatomy of a Scene

Scenes can be found in the asset folder under Assets/Scenes. Within that folder each scene also has its own folder for scene-specific assets.

Each Unity scene will also have a corresponding mode, found in Assets/Scripts/P3SA/Modes/SceneModes.

Every scene contains a scene controller and several GameObjects. Some of those objects will be P3Aware objects so that they can communicate with the modes.

When the scene starts, the scene controller will automatically add some objects to the scene, such as an instance of P3Playfield (for positional reference) and an audio controller.

See also
Sections P3Aware Objects and P3Playfield

Scene Controller

Every Unity scene needs a unique scene controller attached to it. The role of the scene controller is to enable the Unity scene be able to interface with the P3 framework/Mode-side logic. The Scene Controller handles all the P3App specifics that are required to manage and allow interactions between the Unity scene and Mode-side code (ie, connect to p3 interface, handle scene change requests, post events to Modes, receive events from modes, instantiate <AppCode>Audio, connect to p3playfield, etc.).

For example, P3SA contains scenes called Attract and Home. Each of those scenes contains a Unity GameObject - called AttractSceneController and HomeSceneController respectively - and each of which have an attached script component of the same name (HomeSceneController and AttractSceneController). They inherit from the app-specific class P3SASceneController, which in turn inherits from the base class SceneController.

The scene controller takes responsibility for:

  • Ensuring that all game objects are correctly instantiated, initialized and positioned for the opening of the scene or when the scene is reset for the beginning of a ball.
  • Handling any intro required for the scene
  • Updating any in-scene objects as required during scene execution (some objects may listen directly to the events from the mode and behave individually, while other objects will be updated by the scene controller based on the scene controller's receipt of mode events)
  • Handling any outro required for the scene
  • Ensuring that all in-scene objects are disposed of as necessary.
See also
Section Adding a Scene

P3Aware Objects

GameObjects which need to communicate with the mode layer can add a script which descends from the P3Aware class. This class descends from MonoBehaviour so it has the usual Awake, Start and Update methods. These can be overridden, but be sure to remember to call the base class version of the method in your overridden method.

For a P3Aware object to send an event to the modes, it just needs to call PostGUIEventToModes.

For a P3Aware object to receive an event from the modes, it needs to first have an event handler method using the AddModeEventHandler method. This can be done at any time, but it is convenient to do it in the CreateEventHandlers method. There is no need to unregister the event handler - this is handled automatically by the P3Aware class.

P3Aware objects are also able to spawn popup scores.

See also
Class P3Aware and Section Popup Scores.

Ball Collision Detection

A virtual target is a Unity GameObject that can react when the physical ball rolls over it. Like a regular Unity GameObject collision, your GameObject will need a Rigidbody, a Collider and a script with an OnTriggerEnter (or similar) event handler.

The P3Aware class contains everything required to detect collision with the physical ball, so the script class will need to inherit from P3Aware. This gives access to the HitByBall method.

public class MyHittableObject : P3Aware {
public void OnTriggerEnter(Collider other) {
if (HitByBall(other)) {
PostGUIEventToModes("Evt_ObjectHit", position); // Let the mode layer know about the collision
// Add more GUI layer reaction code here
}
}
}

P3Aware inherits from MonoBehaviour, so it has the usual Start and Update methods as well. Be sure to include calls to base.Start() and base.Update() in your method implementations.

See also
Section P3Aware Objects and class P3Aware

A GUI Example: A Moving Virtual Target

Here's an example of a script which allows a GameObject to communicate with the mode layer via events. In this case, if its collider is hit, it will tell the modes the name of the object that hit it. It will also listen for an event from the modes to tell it to move to a new location.

using UnityEngine;
using System.Collections;
using Multimorphic.P3App.GUI;
using Multimorphic.P3App.Logging;
namespace Multimorphic.P3SA.GUI {
public class MovingTarget : P3Aware {
// Use this for initialization
public override void Start() {
base.Start();
gameObject.collider.enabled = true;
}
protected override void CreateEventHandlers() {
base.CreateEventHandlers();
AddModeEventHandler("Evt_MoveTarget", MoveTargetHandler);
// could add more AddModeEventHandler calls here
}
public void MoveTargetHandler(string eventName, object eventData) {
// We're being told to move
int index = (int)eventData;
gameObject.transform.localPosition = new Vector3(
-7f + index,
gameObject.transform.localScale.y,
Random.Range(-2.5f, 2.5f));
}
public void OnTriggerEnter(Collider other) {
if (HitByBall(other)) {
// We've been hit! Tell the modes about it.
PostGUIEventToModes("Evt_TargetHit", other.name);
Logger.Log("GUI layer: Target hit by " + other.name + ". Posting event to mode layer.");
}
}
// Update is called once per frame
public override void Update() {
base.Update();
// Per-frame logic goes here.
}
}
}
See also
Section P3Aware Objects and class P3Aware.

P3Playfield

SceneController ensures that an instance of P3Playfield exists in the scene. P3Playfield is a prefab that represents the virtual counterpart to some of the hardware.

It contains:

  • an avatar for the ball and its path (for detecting when the ball hits a virtual target in-scene)
  • avatars for flippers and slingshots
  • virtual rollover switches (gates) for the outlane and return lanes
  • virtual rollover switches (gates) for the side targets
  • virtual rollover switches (gates) in front of each wall of the P3's wall/scoop assembly
  • an overlay to illustrate where the flippers and slings are situated relative to the scene
  • a virtual version of the infrared grid used for tracking the ball when simulating game play

The prefab has an associated P3Playfield class. Some helpful boolean properties of this class can be flipped using checkboxes in the inspector:

  • Show Ball Path
  • Show Flippers
  • Show Slingshots
  • Show Playfield Overlay
  • Show IR Grid

Note: Do not alter the P3Playfield prefab. It is critical to the proper functioning of your app.

Audio

The IAudio interface exists to facilitate audio functionality. This interface is implemented in P3SAAudio, which you can customize for your own app. The implementations of the IAudio methods allow the scripts and prefabs in the P3App framework to use the same audio methodology as your app. For example, the settings editor, the profile editor and the high score name editor make use of the Audio calls.

See also
Classes Audio, P3SAAudio and interface IAudio.

Events in GUI Layer

Note - This section describes how to send and receive events in GUI scripts. For sending and receiving events in Modes, please refer to Events in Mode Layer.

Receiving Mode Events In GUI Scripts

Modes can send events to GUI scripts to pass information or to request an action. These events are typically referred to as ModeToGUI Events. The following example shows how to subscribe to a ModeToGUI Event in a GUI script:

// This script needs to inherit from P3Aware (or another descendent of P3Aware).
// Then the CreateEventHandlers() method is overridden like this:
protected override void CreateEventHandlers() {
// Call base.CreateEventHandlers so all parent subscriptions are made
base.CreateEventHandlers();
// Now subscribe to the "Evt_SceneCompleted" event with the CompleteEvent handling method
AddModeEventHandler("Evt_SceneCompleted", CompleteEvent);
}
// Define the CompleteEvent handling method.
public void CompleteEvent(string eventName, object eventObject) {
// Cast the incoming data into the expected type
SceneCompleteInfo info = (SceneCompleteInfo)eventObject;
// Do something.
}

Sending Events To Modes

GUI scripts can send events to Modes to pass information or to request an action. These events are typically referred to as GUIToMode events. The following example shows how to send GUI events to Modes:

// This script needs to inherit from P3Aware (or another descendent of P3Aware). Otherwise it can't post GUIToMode events.
// Post the "data" object with the event name of "Evt_EventABC".
PostGUIEventToModes("Evt_EventABC", data);