Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
CustomActivity is a function which is part of every Screen and Entity. This is where you can place code that you would like to run every-frame. Examples of common logic in CustomActivity include:
Collision
Input
Checking for non-UI events such as a timer ending a level
CustomActivity is called by default by generated code, so it should never be called in custom code.
A Screen's CustomActivity will always be called last relative to the Objects inside of it. More generally speaking, the children Objects of a Screen or Entity will have their CustomActivity called before the parent container. Objects in a Screen or Entity will have their CustomActivity called in the order in which they appear in Glue. In this example, the order of CustomActivity will be as follows:
SubEntityInstance
SubEntityInstance2
SubEntityInstance3
TestEntity
Whatever contains TestEntity (like a Screen)
[subpages depth="1"]
The ClickNoSlide event is an event which is raised when the user presses and releases the mouse button or presses and releases on a touch screen without sliding. This method is useful for touch screen games which use sliding as a valid form of input. If a regular Click method is used instead of ClickNoSlide, then pushing, sliding, and releasing on a UI element may be mistakenly interpreted as a click.
The ClickNoSlide method uses the Cursor's PrimaryClickNoSlide property.
The PooledByFactory property on Entities tells Glue that the Factory for the given Entity should perform pooling. For this property to appear, an Entity must have its CreatedByOtherEntities property set to true. More information on CreatedByOtherEntities can be found here.
What is pooling? In programming a "pool" of objects is a group of objects which are instantiated but unused. Whenever a new object is needed, an instance from the pool is returned. Whenever an object is no longer needed, it is returned to the pool - in other words, it's recycled. This allows your game to create and destroy objects without having to allocate memory. This is important for reducing memory allocation, which in turn reduces the number of times that the garbage collector has to run. If your game is experiencing jumps in frame rate you may be suffering from the garbage collector firing frequently, and pooling may help resolve this problem.
The first step, as mentioned above, is to set "CreatedByOtherEntities" to true. Once this is done, you will see a "PooledByFactory" property. Setting "PooledByFactory" to true will enable pooling. The syntax to create an object will be:
This code is identical whether PooledByFactory is true or not. This means that you can switch between PooledByFactory at any point in development. As long as you are using Factories, you will not have to change any code!
You may be wondering about recycling. The great thing about pooling in Glue is that the PooledByFactory will both modify the Factory code for your Entity as well as the Destroy code for your Entity. To recycle an Entity you simply call Destroy on it, just as you would if you weren't pooling. In other words, there is no code change here either!
Pooling allows your game to use the same Entity instance over and over to eliminate new memory allocation. While this is great for performance, it can cause some very confusing bugs. The following sections will help you prepare your Entity so that it does not suffer from poling-related bugs.
Consider the following code for a Bullet object:
The code simply marks the time when the Bullet is instantiated, then checks to see if more than 3 seconds have passed since it has been instantiated, and if so, the Bullet is destroyed. This code will work without pooling; however, if you turn on pooling the Bullet objects will stop appearing after a few rounds are fired. The reason for this is because the Bullet's mTimeCreated is only set when the Bullet is instantiated. Once it is recycled, its mTimeCreated remains at its old value, and since it has already been destroyed once due to time, then more than 3 seconds have passed since it has been instantiated. The end result is, as soon as it is recycled, it is immediately destroyed and put back in the pool. The solution is to move any instantiation into CustomInitialize:
Once this change is applied, the Bullet will work as expected. Since this is a common gotcha, we recommend never setting default values to objects outside of CustomIntialize. For non-pooled objects it makes no difference, but if you do decide to switch to a pooled Entity, you will be avoiding possible bugs.
Another common problem related to pooling is the starting values of objects added to an Entity in Glue. The way that Glue performs attachments depends on the absolute position of attached objects when Initialize is called. For example, if an Entity has a Sprite object, then that Sprite object will be attached to the Entity. The position of the Sprite matters - if it is moved to the right in the .scnx that it comes from, then it will be attached with an offset. The reason this matters regarding pooling is because pooled objects often move. This means that when a pooled object is destroyed, the Sprite attached to the Entity (or any other object attached to the Entity for that matter) will not be in its original position. This is a very common problem regarding pooling, and it can be difficult to solve. Fortunately, Glue can help. If you have switched an Entity to be pooled, you can tell it to reset its attached objects as follows:
Right-click on the Entity
You will be asked for a confirmation. Click "Yes".
Your contained objects will now have reset variables. If you'd like to view what has been reset, you can do the following:
Select an object inside your pooled Entity
A set of static variables which store the values to reset
The setting of these static variables in Initialize (Initialize is only called once for a Pooled object)
The setting of instance variables according to the static variables in "AddToManagersBottomUp" which is called whenever an instance is created or pooled.
Keep in mind that Glue only adds variables to existing objects. If you ever add a new object (such as a collision object) to an Entity that is pooled and which has already had its reset variables set, you will need to right-click on the Entity and select "Add Reset Variables For Pooling" to tell Glue to add reset variables for your newly-created object.
For information on how factories, pooling, and inheritance all work together see the Factory Initialize method page.
The EntitySpawned delegate allows custom code to react to an entity instance being created. For example a game may want to add an Entity to a custom list when spawned.
The following code assigns a custom EntitySpawned delegate which adds any created ball instance to the CustomBallList:
Select "Add Reset Variables For Pooling". This option is only available if "PooledByFactory" is set to True
Right-click on the object and select "Edit Reset Variables"
A window will appear showing the variables that are being reset for the given object: These variables are automatically set by Glue to capture the most common cases of variables which should be reset. You can also view the result of these variables in code by opening the Generated code. You will notice:
The OrderedList property is a List of values which correspond to the order of values in a dictionary CSV. A given CSV must have its CreatesDictionary property set to true for OrderedList to be generated.
OrderedList is not dynamicThe OrderedList is a hardcoded list. It is not dynamic, meaning if you make any modifications to a CSV at runtime, the OrderedList property will not update according to these changes.
The OrderedList property can provide access to entries in a dictionary CSV when order is important. The reason this is necessary is because values in a Dictionary at runtime are not guaranteed to be in the same order as the values in a CSV. For more information, see this page.
The GetFile method is a method which lets you get a file using a string instead of directly accessing a file. In other words, if a screen or entity contains a file called Bear.png, GetFile allows you to do this from within the screen or entity:
Using the example above, you can simply do:
However, if you need to dynamically select a texture (such as if you are reading information from a CSV) your code may need to be dynamic. Therefore, you could do:
Another common example is that a game may support loading levels dynamically, as follows:
GetFile will usually work without any additional code most of the time, but not always. We'll look at two different scenarios and discuss what is required for each:
The most common - and simplest - scenario is calling GetFile when there is already an instance of the object that holds the files created. This can be done in a number of ways:
Calling a screen's GetFile function when the Screen is the active Screen
Calling an entity's GetFile function from within the entity's custom Initialize/Activity/LoadStaticContent methods
Calling an entity's GetFile function through an instance of that entity
In all of the above cases, an instance of that Screen/entity will have been created, meaning that the files will have been loaded and are available to access through GetFile. In short, if an instance is alive, then GetFile should work without any other code.
It is possible to call GetFile on a screen/entity without having an instance of that screen/entity. However, to do this, you must first tell the screen/entity to load the files so that they are available through GetFile. For example, consider the following code:
LoadStaticContent can be called multiple times, and this will not reload the content as long as the same content manager is used. For more information, see the LoadStaticContent page.
The error that is shown above identifies which lists contain objects which have not been cleaned up. To see what is contained in the lists:
Run the game and have the crash occur so the dialog shows.
Copy and paste the name of the list or lists that appear in the exception dialog. For example FlatRedBall.SpriteManager.AutomaticallyUpdatedSprites
Once you've identified the objects that aren't being cleaned up, you will need to remove them from their respective managers, or call Destroy on the container Entities.
Once you have obtained the list of objects which are still being held by the manager, you need to track where the objects are being created. Often, the objects are being created through an entity in custom code. For example, consider the following watch window that displays a Sprite still in the engine at the time of Screen transition:
If your watch window indicates that you have multiple objects which need to be cleaned up, you can focus on the first one by adding [0] to the property being investigated.
If your game is experiencing this problem due to entities which haven't been cleaned up, the FlatRedBall.SpriteManager.ManagedPositionedObjects list will tell you which type of entity needs to be cleaned up. For example the following image shows that an instance of Entity1 needs to be destroyed:
CustomLoadStaticContent is a code that is part of the default generated code file for every Screen and Entity created by Glue. CustomLoadStaticContent is called once when a Screen is first instantiated, and once for every Entity type when it is instantiated in a Screen. This method is called per Entity if it hasn't been called for that entity ever, or if the content manager that was used when it was called last has since been unloaded.
If you have been writing a game and have not been using CustomLoadStaticContent, then you may be wondering why this function exists. Before getting into the details of CustomLoadStaticContent, let's mention that games are not required to use CustomLoadStaticContent. You can create virtually any type of game and it will work without using CustomLoadStaticContent (this is not true of the other three methods in a Screen/Entity: CustomInitialize, CustomActivity, and CustomDestroy). However, the value of CustomLoadStaticContent is that it can run on a second thread, asynchronously. Because of this characteristic, you can perform actions (usually content loading from disk) during loading screens. Therefore, CustomLoadStaticContent isn't required, but it is often useful for making your game transition between Screens without appearing to freeze.
When the Screen is first created (this is called pre-loading)
When the Mushroom is actually created - probably when Mario jumps and hits the block that makes the mushroom appear (this is called lazy loading)
When referring to FRB content, lazy loading refers to the fact that the content isn't loaded until the time when it is needed. When content is pre-loaded, it will be loaded on a secondary thread, so if you are using loading screens, you will not notice a freeze in frame rate. However, if your content is lazy loaded, then you will likely notice a jump in frame rate. The purpose of CustomLoadStaticContent is to perform pre-loading on content that would normally be lazy loaded.
Glue will automatically pre-load content that is added to a Screen (unless it is marked as LoadedOnlyWhenReferenced), so in most cases you will not need to use this method. The CustomLoadStaticContent can be useful in situations where Glue does not know if it should load Content, or if the content that should be loaded initially is not loaded until later because Glue does not know if the content is used.
Glue will automatically load static content for Entities which are added as instances to a Screen (or another Entity). For example, consider a situation where you have created a Screen called GameScreen and an Entity called Player. If you add an instance of the Player Entity in the GameScreen through the Glue UI, Glue will recognize that it should load static content on the Player class. But instead let's say you add an instance of Player to your custom code as follows:
In this case, Glue won't know that you are creating a Player instance when it generates code - it doesn't read your custom code when creating generated code. Therefore, it doesn't know that it should load the static content for Player. Therefore, when the Player is instantiated in CustomInitialize (or any place in custom code) the game frame rate may jump slightly. If you are using async loading screens, then the player will no get loaded in the loading screen. This can cause pops or even cause your game to freeze for extended periods of time depending on how much content is being loaded. You can solve this by loading the Player's static content in CustomLoadStaticContent:
Let's say you have an Entity called Enemy and you add a PositionedObjectList<Enemy> to your GameScreen. In this situation you may intend to populate this list by code or CSV or some other method; however, unless instances are explicitly added to this PositionedObjectList in the Glue UI, Glue doesn't know if you will ever actually instantiate any Enemies or not. Therefore, to save memory Glue will not load the Enemy's static content automatically. Of course this isn't terrible behavior: If you never instantiate an Enemy then you have saved that memory, and if you do then the first Enemy instance that is created will lazy load. You may not notice this at all if the first instance is created in the Screen's CustomInitialize code, or if it is created after but the load time is very quick. Of course as hinted above, there are two problems:
You may instantiate the first enemy some time after the game begins playing, and the load call may cause a frame rate jump in the game, or even freeze the game for a considerable amount of time depending on how long the content load takes.
Even if you instantiate in CustomInitialize, CustomInitialize is called on the primary thread meaning if you are loading your Screen asynchronously, the loading of the Enemy content will not be done on the secondary thread - this may make your loading Screen appear to freeze.
These issues can easily be fixed by simply calling LoadStaticContent on the Enemy type as follows: private static void CustomLoadStaticContent(string contentManagerName) {
} That's all there is to it! Doing this will:
Load the Enemy's content when the GameScreen is first instantiated.
Load the Enemy's content asynchronously, which means it will load during your Load sceen if you are using one.
Not result in a double-load of the Enemy's content. The Enemy code is smart enough to recognize that the Enemy's content has already been loaded in custom code, so it will not load it again when you instantiate an Enemy.
You may be working on a game where content is optionally loaded. Keep in mind that CustomLoadStaticContent is a static method, so you will not have access to the Screen's instance members in this method. However, if you have information that is available globally (such as in GlobalData) you can access it here to perform custom loading. For example, you may know that you will only use the "Orc" class in the OrcLevel and the "Troll" class in the TrollLevel. Therefore you could write code in your GameScreen's CustomLoadStaticContent as follows:
Glue supports optionally loaded content through the use of the LoadedOnlyWhenReferenced property. This property indicates that a particular piece of content should create a getter property, and the content should be loaded the first time the getter is accessed. This feature is often used when creating Entities which may use any number of pieces of content. For example, a racing game may have a large number of pieces of content (ultimately stored in .scnx files). Your game's load times may be extremely long and you may even run out of memory if you load all content that may be referenced by your Car Entity. LoadedOnlyWhenReferenced can eliminate this problem. However, using LoadedOnlyWhenReferenced means that Glue will not automatically load content which is LoadedOnlyWhenReferenced. Of course, you can force content to be loaded simply by accessing the property of your content. To continue the example above, let's say that your Car Entity has three .scnx files which are LoadedOnlyWhenReferenced. The names for these three are:
FordMustangScene
ChevyCamaroScene
HyundaiGenesisScene
We'll also assume that you have a PlayerSave instance in GlobalContent which indicates which Scene to load, as follows. In this case you would have enough information to pre-load the given Car that is needed as follows:
Notice that there is no need to keep track of the throwAwayScene - simply using the getter will load the content so that when the Car instantiates itself later, the content it needs will already be loaded.
Some objects may take some time to instantiate, but not because they load files but rather because they require significant up-front processing. The CustomLoadStaticContent method can be used to do this on a secondary thread. However there are a few requirements which must be met for this to be possible:
The instance must be added as a static object to the Screen
The instance must be of a type that can be instantiated without being added to any FRB managers
The instance should be nulled-out when the containing Screen is destroyed. It is possible to do this with Entities, but it's more complicated so we'll focus on Screens for this example.
If you are instantiating an Entity, then the 2nd requirement (instantiation without adding to managers) will be met for you automatically. If you have constructed your own object, then you should consider having separate Initialize and AddToManagers methods. We'll assume that the object being added is of type LargeEntityObject. To instantiate this in CustomLoadStaticcontent:
Add the following to the Screen's custom code class:
Add the following to the Screen's CustomLoadStaticContent (2nd argument specifies whether to add to managers):
Add the following to the Screen's CustomInitialize (argument specifies the Layer):
Add the following to the Screen's CustomDestroy:
The argument (in the example above "Bear") matches the name of the variable in the screen or entity. This will usually be the name of the file, without any path or extension. The exception to this rule is if the IncludeDirectoryRelativeToContainer value is true. Similary, GetFile can be called to obtain files from GlobalContent. For example, the following returns a song called BattleSong from GlobalContent:
This error can occur if your current Screen is destroyed without cleaning up after itself. More specifically this means that objects were added to the FlatRedBall managers during the Screen's life but were not removed prior to or during the Screen's Destroy method. The error that you see will tell you which member to look at for clues as to which objects are still in the engine.
Open a Watch window by selecting "Debug"->"Windows"->"Watch"->"Watch 1"
Expand the list to see which items are in the list
To understand the difference between content that is "lazy loaded" vs. content that is "pre-loaded" we'll use an example: the mushroom object in Super Mario Bros. If Super Mario Bros. were created in Glue, then the Glue project would probably have a Mushroom Entity. The Mushroom Entity would contain either a .scnx file for the Mushroom Sprite, or simply a .png that would be applied to the Mushroom Sprite. In either case, the Mushroom object would have some content that it would need to load from disk. Of course, in Super Mario Bros. the mushroom graphic is very small, but for this example we'll pretend that loading the content for the Mushroom Entity takes some significant amount of time. Conceptually speaking, there are two possible times when the files for the Mushroom Entity can be loaded:
The PauseThisScreen method is a method available to all Screens. The PauseThisScreen method calls and also sets the IsPaused property to true. This is a handy simple way to pause the game. To unpause the game, use .
If a Screen is paused then all contained Entities will also be paused. This includes Entities that have been directly added through Glue, or Entities that belong to PositionedObjectLists that have been added through Glue. Paused Entities will not have Engine behavior applied (velocity), will not have CustomActivity called, and will not be clickable. Entities (and other objects) which are added to Screens can ignore pausing if their property is set to true.
Entity instantiation in Glue projects is standardized. The constructor appears in Generated code. The standardization of constructors enables the following:
Every Entity is instantiated the same way, making Entity instantiation in custom code easy
Generated code can instantiate any Entity allow for factory and addition of Entities inside other Entities and Screens in Glue.
For information on how to instantiate Entities, see the following tutorial.
The Destroy method is a method which can be used to destroy an instance of an Entity. The Destroy method is also used in generated code to destroy Entity instances that Glue is aware of. The Destroy method does not need to be called if an Entity was added through Glue, or if an Entity is part of a PositionedObjectList created in Glue - in thee cases Glue will take care of calling Destroy when the containing Screen.
For information on when to call Destroy, as well as a general discussion of when Glue calls Destroy for you see the "Destroying Entity Instances" tutorial.
As mentioned above, Destroy needs to be called on all Entities. In many cases generated code will automatically call Destroy on Entities; however, in some cases you may need to call it yourself. The Destroy function is responsible for the following:
Removing any visible objects from their respective managers. After Destroy is called, a given Entity will no longer be drawn.
Removing attachments. If an Entity is destroyed then it will automatically detach itself from anything it is attached to, and anything that is attached to it will be detached.
Removing any updated objects from their managers. This means that any objects which have properties like Velocity or Acceleration will no longer have these properties set.
If an Entity is destroyed it will be removed from all FlatRedBall systems; however that does not mean that references to the Entity will be removed. For example consider the following situation:
If you intend to create and destroy an entity instance we recommend one of two approaches:
Add the entity instance to a PositionedObjectList of Entities. When it is destroyed, it will automatically be removed from the list. This is a good approach for entities which will be either created and destroyed as the game is played (such as bullets) or entities which are all created at the beginning of a Screen then removed over time (such as pellets in Pac Man).
Set the Entity to be invisible. If you simply don't want it drawn or to be clickable with the Cursor, then setting it to invisible will remove it from the player's perspective.
The PauseAdjustedSecondsSince method returns the number of seconds that have passed since the argument time, not including time spent paused. This method is similar to the TimeManager.SecondSince method, however it does not include the amount of time that the current Screen has spent paused. This method is purely a convenience method - it does not provide any functionality beyond subtracting the current time from a given time and returning the result; however it may be more expressive to use in certain situations improving the readability of code. For information on pause-adjusted timing, see the PauseAdjustedCurrentTime page.
You can use PauseAdjustedSecondsSince to see how long the Screen has been around and compare it to a fixed number. To check if the Screen has been around for a certain amount of time:
PauseAdjustedSecondsSince can be used to perform an action after a certain amount of time has passed. The following code shows how to perform an action every 5 seconds:
The following code shows how to create a countdown timer. It assumes that your Screen has a valid Text object called CountDownText
Entities can limit the frequency of an action (such as firing a bullet) using the PauseAdjustedSecondsSince method. The following code limits shooting bullets using the SecondsBetweenShots variable:
Game1CodeGenerator is a base class for code generators which inject code into Game1.Generated.cs. It provides the following methods for derived classes to override:
GenerateClassScope
GenerateInitialize
GenerateUpdate
GenerateDraw
Typically Game1CodeGenerator instances are associated with a specific plugin. Therefore, typical steps for creating a new Game1CodeGenerator-inheriting class are:
Add a new class to your plugin.
Inherit from Game1CodeGenerator
Override the desired methods. For example, to add code to the game's initialization, override GenerateInitialize.
The following shows an example of an empty Game1CodeGenerator-inheriting class:
As mentioned above, Game1CodeGenerators are typically associated with plugins. Therefore, it is common to instantiate and register a code generator in a plugin's StartUp method as shown in the following code snippet
Typically, Glue will generate Game1 whenever a project is loaded. A plugin can forcefully generate Game1 generated code as well using the following code:
CustomLoadStaticContent is a code that is part of the default generated code file for every Screen and Entity created by Glue. CustomLoadStaticContent is called once when a Screen is first instantiated, and once for every Entity type when it is instantiated in a Screen. This method is called per Entity if it hasn't been called for that entity ever, or if the content manager that was used when it was called last has since been unloaded.
If you have been writing a game and have not been using CustomLoadStaticContent, then you may be wondering why this function exists. Before getting into the details of CustomLoadStaticContent, let's mention that games are not required to use CustomLoadStaticContent. You can create virtually any type of game and it will work without using CustomLoadStaticContent (this is not true of the other three methods in a Screen/Entity: CustomInitialize, CustomActivity, and CustomDestroy). However, the value of CustomLoadStaticContent is that it can run on a second thread, asynchronously. Because of this characteristic, you can perform actions (usually content loading from disk) during loading screens. Therefore, CustomLoadStaticContent isn't required, but it is often useful for making your game transition between Screens without appearing to freeze.
When the Screen is first created (this is called pre-loading)
When the Mushroom is actually created - probably when Mario jumps and hits the block that makes the mushroom appear (this is called lazy loading)
When referring to FRB content, lazy loading refers to the fact that the content isn't loaded until the time when it is needed. When content is pre-loaded, it will be loaded on a secondary thread, so if you are using loading screens, you will not notice a freeze in frame rate. However, if your content is lazy loaded, then you will likely notice a jump in frame rate. The purpose of CustomLoadStaticContent is to perform pre-loading on content that would normally be lazy loaded.
Glue will automatically pre-load content that is added to a Screen (unless it is marked as LoadedOnlyWhenReferenced), so in most cases you will not need to use this method. The CustomLoadStaticContent can be useful in situations where Glue does not know if it should load Content, or if the content that should be loaded initially is not loaded until later because Glue does not know if the content is used.
Glue will automatically load static content for Entities which are added as instances to a Screen (or another Entity). For example, consider a situation where you have created a Screen called GameScreen and an Entity called Player. If you add an instance of the Player Entity in the GameScreen through the Glue UI, Glue will recognize that it should load static content on the Player class. But instead let's say you add an instance of Player to your custom code as follows:
In this case, Glue won't know that you are creating a Player instance when it generates code - it doesn't read your custom code when creating generated code. Therefore, it doesn't know that it should load the static content for Player. Therefore, when the Player is instantiated in CustomInitialize (or any place in custom code) the game frame rate may jump slightly. If you are using async loading screens, then the player will no get loaded in the loading screen. This can cause pops or even cause your game to freeze for extended periods of time depending on how much content is being loaded. You can solve this by loading the Player's static content in CustomLoadStaticContent:
Let's say you have an Entity called Enemy and you add a PositionedObjectList<Enemy> to your GameScreen. In this situation you may intend to populate this list by code or CSV or some other method; however, unless instances are explicitly added to this PositionedObjectList in the Glue UI, Glue doesn't know if you will ever actually instantiate any Enemies or not. Therefore, to save memory Glue will not load the Enemy's static content automatically. Of course this isn't terrible behavior: If you never instantiate an Enemy then you have saved that memory, and if you do then the first Enemy instance that is created will lazy load. You may not notice this at all if the first instance is created in the Screen's CustomInitialize code, or if it is created after but the load time is very quick. Of course as hinted above, there are two problems:
You may instantiate the first enemy some time after the game begins playing, and the load call may cause a frame rate jump in the game, or even freeze the game for a considerable amount of time depending on how long the content load takes.
Even if you instantiate in CustomInitialize, CustomInitialize is called on the primary thread meaning if you are loading your Screen asynchronously, the loading of the Enemy content will not be done on the secondary thread - this may make your loading Screen appear to freeze.
These issues can easily be fixed by simply calling LoadStaticContent on the Enemy type as follows: private static void CustomLoadStaticContent(string contentManagerName) {
} That's all there is to it! Doing this will:
Load the Enemy's content when the GameScreen is first instantiated.
Load the Enemy's content asynchronously, which means it will load during your Load sceen if you are using one.
Not result in a double-load of the Enemy's content. The Enemy code is smart enough to recognize that the Enemy's content has already been loaded in custom code, so it will not load it again when you instantiate an Enemy.
You may be working on a game where content is optionally loaded. Keep in mind that CustomLoadStaticContent is a static method, so you will not have access to the Screen's instance members in this method. However, if you have information that is available globally (such as in GlobalData) you can access it here to perform custom loading. For example, you may know that you will only use the "Orc" class in the OrcLevel and the "Troll" class in the TrollLevel. Therefore you could write code in your GameScreen's CustomLoadStaticContent as follows:
Glue supports optionally loaded content through the use of the LoadedOnlyWhenReferenced property. This property indicates that a particular piece of content should create a getter property, and the content should be loaded the first time the getter is accessed. This feature is often used when creating Entities which may use any number of pieces of content. For example, a racing game may have a large number of pieces of content (ultimately stored in .scnx files). Your game's load times may be extremely long and you may even run out of memory if you load all content that may be referenced by your Car Entity. LoadedOnlyWhenReferenced can eliminate this problem. However, using LoadedOnlyWhenReferenced means that Glue will not automatically load content which is LoadedOnlyWhenReferenced. Of course, you can force content to be loaded simply by accessing the property of your content. To continue the example above, let's say that your Car Entity has three .scnx files which are LoadedOnlyWhenReferenced. The names for these three are:
FordMustangScene
ChevyCamaroScene
HyundaiGenesisScene
We'll also assume that you have a PlayerSave instance in GlobalContent which indicates which Scene to load, as follows. In this case you would have enough information to pre-load the given Car that is needed as follows:
Notice that there is no need to keep track of the throwAwayScene - simply using the getter will load the content so that when the Car instantiates itself later, the content it needs will already be loaded.
Some objects may take some time to instantiate, but not because they load files but rather because they require significant up-front processing. The CustomLoadStaticContent method can be used to do this on a secondary thread. However there are a few requirements which must be met for this to be possible:
The instance must be added as a static object to the Screen
The instance must be of a type that can be instantiated without being added to any FRB managers
The instance should be nulled-out when the containing Screen is destroyed. It is possible to do this with Entities, but it's more complicated so we'll focus on Screens for this example.
If you are instantiating an Entity, then the 2nd requirement (instantiation without adding to managers) will be met for you automatically. If you have constructed your own object, then you should consider having separate Initialize and AddToManagers methods. We'll assume that the object being added is of type LargeEntityObject. To instantiate this in CustomLoadStaticcontent:
Add the following to the Screen's custom code class:
Add the following to the Screen's CustomLoadStaticContent (2nd argument specifies whether to add to managers):
Add the following to the Screen's CustomInitialize (argument specifies the Layer):
Add the following to the Screen's CustomDestroy:
To understand the difference between content that is "lazy loaded" vs. content that is "pre-loaded" we'll use an example: the mushroom object in Super Mario Bros. If Super Mario Bros. were created in Glue, then the Glue project would probably have a Mushroom Entity. The Mushroom Entity would contain either a .scnx file for the Mushroom Sprite, or simply a .png that would be applied to the Mushroom Sprite. In either case, the Mushroom object would have some content that it would need to load from disk. Of course, in Super Mario Bros. the mushroom graphic is very small, but for this example we'll pretend that loading the content for the Mushroom Entity takes some significant amount of time. Conceptually speaking, there are two possible times when the files for the Mushroom Entity can be loaded: