Custom World Shifters can be used for a variety of purposes, from creating logic that works seamlessly with custom Hierarchy Organizers to introducing precise timing between the movement of Players and the movement of the World.
Whatever the reason for creating a custom World Shifter, here we will tell you everything you need to know in order to do so!
To start, create a new MonoBehaviour script that derives from the WorldShifter base abstract class.
You should place your class inside of the DeepSpaceLabs.SAM namespace, which will make the WorldShifter class available and also help avoid naming conflicts with 3rd party assets or your own code.
--Special Note--
An easy way to start with your custom class is to hover over your custom class name and choose the option Show potential fixes -> Implement abstract class. This will provide default overrides for all abstract class members.
In addition, we recommend adding the following attribute above your class, which will ensure the custom execution controller is shown with other World Shifters in menus:
[AddComponentMenu(GlobalValues.COMPONENT_ROOT_PATH + "World Shifters/Custom World Shifter Name")]
Override to tell the base WorldShifter class whether the WorldShifting event should be fired automatically just prior to the ShiftWorld coroutine being run. This will call the FireWorldShiftingEvent method if true.
You may return false, however you will need to fire the event manually by calling the FireWorldShiftingEvent method.
If you don't elect for either of these two options, the WorldShifting event will not fire. You can create a custom event yourself in this case and fire it at the time of your choosing, however it is generally better to just use the default WorldShifting event, unless you want to utilize different arguments for the event.
When overridden, tells the base World Shifter class whether the WorldShifted event should be fired automatically just after the ShiftWorld coroutine finishes running. This will call the FireWorldShiftedEvent method if true.
You may return false, however you will need to fire the event manually, by calling the FireWorldShiftedEvent method.
If you don't elect for either of these two options, the WorldShifted event will not fire. You can create a custom event yourself in this case and fire it at the time of your choosing, however it is generally better to just use the default World Shifted event, unless you want to utilize different arguments for the event.
The base WorldShifter makes use of Unity's standard Awake method, so if you have Awake related code, you will need to override this method and put it here.
The WorldShifter calls this method automatically after all of its Awake logic has run.
The base WorldShifter makes use of Unity's standard OnDestroy method, so if you have OnDestroy related code, you will need to override this method and put it here.
The WorldShifter calls this method automatically after all of it's OnDestroy logic has run.
When overridden, executes a query to determine if the World Shifter has been configured to move the Player associated with the input Active Grid. This is used by the Active Grid to perform a safety check in order to ensure the Player will not be shifted twice (by the World Shifter and Active Grid), which would result in an incorrect position for the Player.
Override to return the number of Transforms that will be shifted in the next shift. You can query the CurrentWorldToBeShifted property to determine which World is about to be shifted.
The actual method used to shift the World. So long as all Asset Chunks related to the World are shifted, you can perform the shift in whatever way you want.
The amount to shift the World can be retrieved using the CurrentShiftAmount property, while the actual World that is being shifted in the current operation can be retrieved using the CurrentWorldToBeShifted property.
If you wish to support Single Frame Shifting, your method can either query the PerformShiftInSingleFrame property and execute alternative code if true, or utilize a single code implementation that is compatible with the following construct:
while(enumerator.MoveNext()) continue;
With this construct, all yield statements are skipped within the ShiftWorld method.
In order to ensure that your World Shifter works properly with any entities that might subscribe to the base World Shifter's World Shift related events, you should fire the WorldShifting and WorldShifted events at the appropriate times.
Fortunately, these events are fired automatically so long as your FireWorldShiftingEventAutomatically and FireWorldShiftedEventAutomatically overrides return true..
If they return false, you will need to call the FireWorldShiftingEvent and/or FireWorldShiftedEvent methods manually in order to fire these events, before (in the case of WorldShifting) and after (in the case of WorldShifted) executing the World Shift.
If you are 100% certain that these events are not needed, you can return false for the properties mentioned and choose not to manually fire the events.
The World Shifter also has some Transform related events that should be fired for every Transform that is shifted within your ShiftWorld method. These include the TransformShifting and TransformShifted events, which should be fired before and after shifting each individual Transform.
We have included a convenience method called ShiftTransformAndFireEvents that can be used to automate shifting and calling events for each Transform. This method automatically fires the TransformShifting event (if there are subscribers), shifts the Transform, and then fires the TransformShifted event (again, if there are subscribers).
You can elect to not use this method, however you will need to manually perform the shift and call the FireTransformShiftingEvent (before shifting) and FireTransformShiftedEvent (after shifting) methods in order to fire the events. With these methods, you need to pass in the number of each Transform in relation to the other Transforms that have been or will be shifted (the first is 1, second 2, and so on), which means you will need to manually track this value yourself.
If you are 100% sure nothing will utilize the TransformShifting and TransformShifted events, you can elect to not call them.