A Popup Score is the fleeting score value you see on the screen, for example when you hit a side target.
Named Locations are a way to give names to fixed x,y,z coordinates. The only place where Named Locations are used in the P3 SDK is with Popup Scores.
Popup Scores and Named Locations are documented in <install_dir>\P3_SDK_V0.8\P3SampleApp\Documentation\html\_adding_game_content.html
Technically, a NamedLocations is any GameObject that has a NamedLocations component. That object acts like a container for its children. The way you define a name for a fixed x,y,z coordinates is by creating a child GameObject with that name and coordinates.
There are two prefabs for NamedLocations in P3SampleApp: P3NamedLocations and P3SANamedLocations.
In Assets\Resources\Prefabs\Framework\P3NamedLocations, you will find names for locations on the base machine portion of the playfield.
In Assets\Resources\Prefabs\<appcode>NamedLocations, you will find names for locations specific to the application. In P3SampleApp, that prefab is called P3SANamedLocations. Since P3SampleApp was derived from Lexy Lightspeed, the prefab defines locations on the Lexy Lightspeed module.
It’s unfortunate that the module-specific NamedLocations are not defined by the module driver. Anyway, that idea would not work as is, because Unity expects the prefabs to be directly part of the application.
The SceneController base class instantiates the P3NamedLocations and <appcode>NamedLocations prefabs. It also calls UnityEngine.Object.DontDestroyOnLoad() to make sure these objects are not destroyed when a new scene is loaded. At runtime, these objects will appear under the DontDestroyOnLoad section of the Hierarchy.
BootstrapSceneController is the first SceneController to execute. That’s where the prefabs are instantiated. When the game changes to the Attract or Home scenes, these objects are preserved and therefore do not need to be recreated.
Let’s examine the NamedLocations at runtime.
Load P3SampleApp in Unity. Select the Bootstrap scene and press the play button.
With the game still running, expand DontDestroyOnLoad in the Hierarchy view if not already expanded.
Expand P3NamedLocations(Clone) in the Hierarchy view to see all the named locations of the base machine. The (Clone) suffix is added by Unity when instantiating a prefab.
Select P3NamedLocations(Clone) in the Hierarchy view to load it in the Inspector.
Select “Show Locations” under the Named Locations (Script) component in the Inspector.
This will make the named locations visible as spheres over the playfield.
The names are not shown. To confirm which location is where, you can select an object in the Hierarchy view, and toggle the enable checkmark to the left of the object name in the Inspector. This will make the sphere appear or disappear each time you click.
The top row of partial spheres corresponds to scoop1 up to scoop6. Strangely, scoop0 and scoop7 don’t exist in the physical machine. You don’t see the corresponding spheres because their locations are beyond the screen.
You can try the same experiment with the other NamedLocations prefab.
First undo what we did with P3NamedLocations. Make sure “Show Locations” is disabled under the Named Locations (Script) of P3NamedLocations in the Inspector. Also collapse P3NamedLocations(Clone) in the Hierarchy view.
Now expand P3SANamedLocations(Clone) in the Hierarchy view.
Select P3SANamedLocations(Clone) to load it in the Inspector.
Select “Show Locations” under the Named Locations (Script) component in the Inspector.
There is not much to see because those locations are on the Lexy Lightspeed module, above the screen. Only one sphere appears which corresponds to the belowPops location. This might be a bug.
A PopupScore is created by calling one of the PopupScoreController Spawn methods.
void Spawn(string caption, long score); void Spawn(string caption, long score, float duration); void Spawn(string caption, long score, Vector3 startPosition); void Spawn(string caption, long score, Vector3 startPosition, float duration); void Spawn(string caption, long score, Vector3 startPosition, Vector3 endPosition, float duration); void Spawn(string caption, long score, Vector3 startPosition, Vector3 endPosition, float duration, float speed); void Spawn(string caption, long score, Vector3 startPosition, Vector3 endPosition, float duration, float speed, bool withinLCDBounds); void Spawn(string caption, long score, string startLocationName, string endLocationName, float duration, float speed); void Spawn(string caption, long score, string startLocationName, string endLocationName, float duration); void Spawn(string caption, long score, string startLocationName, string endLocationName); void Spawn(string caption, long score, string startLocationName); void Spawn(string caption, long score, string startLocationName, float duration); void Spawn(string caption, long score, string startLocationName, string endLocationName, float duration, float speed, bool withinLCDBounds); |
There are a lot of Spawn() methods but the real choice is whether the positions are absent, Vector3 or string.
In newer versions of C#, this could be simplified to just 2 method signatures using default argument values.
// hypothetical method signatures in newer versions of C# void Spawn(string caption, long score, Vector3 startPosition, Vector3 endPosition = null, float duration = 1f, float speed = -1f, bool withinLCDBounds = false); void Spawn(string caption, long score, string startLocationName = "screenCenter", string endLocationName = "", float duration = 1f, float speed = -1f, bool withinLCDBounds = false); |
Let’s go back to the existing Spawn() methods.
The endPosition defaults to the startPosition. The endLocationName defaults to the startLocationName. When the start is the same as the end, the PopupScore will not move.
The startLocationName and endLocationName can be a named location or the name of any GameObject in the hierarchy. Named locations are faster to find because they are cached.
The start and end can be outside the screen. When that happens, the PopupScore will be invisible for part or all of the specified duration. To restrict the full duration to within the bounds of the screen, set withinLCDBounds to true. If a position is outside of the screen, this will compute the intersection of the line with the screen boundary and use that instead. The PopupScore will still travel in the direction of the original position.
Remember the named locations of <appcode>NamedLocations are typically over the upper module. You will likely want to set withinLCDBounds to true when using those named locations.
Look at this code found in Assets\Scripts\GUI\P3SASceneController.cs
public void SideTargetScoreEventHandler(string evtName, object evtData) { LocationScore info = (LocationScore) evtData; popupScores.Spawn("", (int)info.score, info.location, info.location + "Center", 1.0f, 0.5f); } |
This event handler is executed when a side target is hit. It extracts the name of the side target from the event argument, and spawns a PopupScore moving horizontally from the side target location towards the center. For example, if the side target hit is sideTarget1, the end location will be sideTarget1Center. Those locations are defined in P3NamedLocations.
Notice the caption is the empty string. This means there is no caption. The PopupScore will only show the score. The score value was also extracted from the event argument.
The statement above is the only active call to Spawn() in P3SampleApp. The other calls to Spawn() appear in unreachable code. P3SampleApp does not use any of the locations in P3SANamedLocations.
The popupScores member is inherited by all P3Aware components. It is initialized to a PopupScoreController instance in the P3Aware base class.
The PopupScoreController creates the PopupScore by instantiating the Prefabs/<appcode>PopupScore. For P3SampleApp, that’s Prefabs/P3SAPopupScore.
Let’s examine that prefab. Expand Assets > Resources > Prefabs in the Project view.
Drag P3SAPopupScore from the Assets view to the Hierarchy to instantiate a copy.
The P3SAPopupScore object has 4 children.
The Caption and Score are white Text Meshes. The CaptionShadow and ScoreShadow are slightly displaced black Text Meshes.
Select the parent P3SAPopupScore in the Hierarchy view. It is a simple GameObject with a P3SAPopupScore component. Click on the little cog to the right of P3SA Popup Score (Script) and select “Edit Script”.
This will open P3SampleApp\Assets\Scripts\GUI\P3SAPopupScore.cs in the code editor.
The base class PopupScore takes care of moving the PopupScore and destroying it when done.
When P3SAPopupScore is initialized, it makes sure the Caption and the CaptionShadow contain the same text. Similarly for Score and ScoreShadow. It also computes a text targetSize depending on the number of digits in the score value.
P3SAPopupScore Update() method gradually changes the size of the text characters towards the targetSize. It also gradually makes the PopupScore transparent by changing the alpha of the color towards 0.
For a fun project, the P3 SDK documentation suggests adding a particle effect to P3SAPopupScore to simulate an explosion or confetti.
When done inspecting, delete the instance of P3SAPopupScore from the Hierarchy.