In order to support extremely large game environments, the World uses a floating origin based system. This system uses two key pieces of data to function; the Origin Position and Origin Cell.
--Special Note--
While each World Grouping has its own Origin Cell and Origin Position, for the purposes of this Section you should assume (unless otherwise specified) that any mention of these terms refers to the Base Grouping. This is because the Base Grouping's Origin Cell and Position are the only settings which can be directly manipulated: the Origin Cell and Position of Sub Groupings are calculated automatically at runtime from the Base Grouping's Origin Cell and Position!
Imagine we have a game environment which represents the entire planet of Earth. If we pick a point in our game (let's say the center of the United States) to serve as the origin of our world, there exist a finite set of the game world which is relatively close to that point. For that area, we can very accurately describe the position of various assets and run calculations that we know will function correctly.
If we pick a point on the other side of the planet however (let's say somewhere in India), because the positions are still relative to our origin in the United States, the values are extremely large. In some game engines, this may not be an issue, but in Unity where most systems utilize floating point numbers (float) to represent things, these large values cannot be represented without sacrificing accuracy in the fractional part of the values.
A floating origin based system allows us to move the origin depending on which part of the world we want to work with. Using the example above, when we are working with an area of the game world in the U.S. the origin can be in the center of the U.S., but when working with the game world in India, the origin can be changed to some point in India.
In the example above, we discussed the Origin Point as a movable location. Many floating origin based systems use such a system by applying an offset value to all Transforms and game systems in order to mimic a moving origin.
In SAM, we do not utilize such a system, since we theorize that using an offset value would eventually introduce the same floating point issues that a non-floating origin system has. Instead, within SAM the Origin Position of the Base World Grouping remains fixed at a pre-defined point (defined in the inspector or via scripting before the World has been initialized).
Instead, what changes is the World Cell from the Base World Grouping that is treated as the Origin. This Cell is known as the Origin Cell.
This Cell is placed so that its corner representing its minimum values on each axis is positioned over the Origin. All other Cells are placed relative to the Origin Cell, which effectively moves the entire game World.
Using this system, we can describe any position in the game world as a value relative to a World Cell on the World Grouping (more specifically, the values would be relative to the minimum corner of the Cell). That World Cell can either be the current Origin Cell, or better yet, the World Cell that the position falls within. Using the latter option allows us to use the smallest possible positional values we can, which leaves more room in the fractional part of the values which allows for greater accuracy.
Of course, there will be many instances where you need to convert these World Cell Relative Positions to raw World Positions within the Scene (Scene Relative Positions). Fortunately, this is easy to do since we always know the Origin Cell and Origin Position of each World Grouping, and in fact the World class contains several methods designed to aid you in batch converting Cell Relative Positions to and from Scene Relative Positions.
In addition, because we generally only need to convert Cell Relative Positions to Scene Relative Positions when we are working with assets that are close to the Player and Origin (i.e., the part of the game world that is 'active'), the Scene Relative Positions are almost always small as well, which again, is important in accurately representing fractional parts of the position values.
In a floating origin based system, the starting Origin Cell of your World should be set depending on which World Cell you want your Player to begin in. If you cannot determine this in the inspector, you can set this value via scripting before the World has been initialized.
If you are having trouble identifying where to place your Player, we recommend opening the World Designer Tool, setting the Origin Cell to the Streamable Grid Cell you want the player to start in, and loading that Cell in the editor. You can load other Groupings' assets as well if they affect where the Player can be placed.
While you can manually change the Origin Cell at any time, it is usually best to enable automatic re-centering, which automatically resets the Origin Cell when the player travels a pre-set distance from the Origin Position in any direction. To enable this functionality, you need to:
1) Enable Allow Active Grid Re-Centering on your World, which can be found within the Origin Settings Window.
2) Define the Re-Centering Boundary Distances From Origin. These define how far the player can travel from the Origin before a re-centering operation is triggered.
3) Enable Allow Grid To Re-Center World on at least one Active Grid that will be synced to the World, which can be found within the General Settings Window.
When the Player crosses the World Re-Centering Boundary, a world re-centering is triggered. This re-centering operation basically identifies which World Cell the Player is in and then performs an Origin Cell Change, making that World Cell the Origin Cell. This results in the World being re-positioned so that the Player is more or less close to the Origin Position.
You can also change the Origin Cell of the World manually via the World's Change Origin Cell method, by loading World Regions, or by using the TryMovePlayerAndChangeOriginCellOfWorld method from the Active Grid class.
The Active Grid method is recommended if you are transporting the Player across large distances from one part of the World to another.
No matter how the Origin Cell Change is initiated (automatically or manually), once an Origin Cell Change is queued, the Origin Cell Change Strategy determines how the World goes about executing the change.
Duplicate World is a brute force method that duplicates every World Cell (and their Asset Chunks). While it requires no extra effort to setup on your end, it has two major disadvantages:
1) The memory usage of your game will nearly double (temporarily).
2) If the World Cells that are currently loaded are not sufficiently far enough from the Origin, there is a chance that the duplicated World Cells will overlap the existing ones.
If one or both of these issues are deal breakers (which they likely will be), you can use the second strategy, Shift World.
This strategy uses a special World Shifter component to shift the position of Asset Chunk that are a part of your World over one or more frames.
While we include a default World Shifter in SAM (that works with the Standard Hierarchy Organizer), you are also free to create a custom World Shifter for more fine-tuned control over the shifting process.
You have two choices for how you send Positional Data.
1) As Raw Scene Relative Positions (Vector3).
2) As World Cell relative positions, in which case you must also send the endless grid indexes associated with the World Cell. You can choose to send the positions themselves as Vector3's or Vector3Double's.
Option 1 should only be used if you know that the Scene Relative Positional Data will be accurate at the time the receiving system processes it. Put another way, the Origin Cell in use by the receiving system's game environment at the time of processing must be the same as the Origin Cell in use by the sending system's game environment when the position was recorded.
For example, in a multiplayer game, each client is likely to be using a different Origin Cell, so using option 1 to send data to/from different clients is not possible. Instead, you must convert each client's Scene Relative Positions to Cell Relative Positions, then send that data.
At the client's end, they can look at the position and the World Cell it is relative to and basically say, "Okay, so this position is relative to Cell 1_4. Cell 1_4 is at position x,y,z in my game world, which means that the position is at x2, y2, z2."
For systems that are confined to the client only (using only data from that client and nothing else), using the Scene Relative Positions is usually not a problem, so long as you have a system in place that monitors and takes into account changes to the Origin Cell.
The Component Manager's Save method automatically saves each World's current Origin Cell with the save data, allowing it to be restored when that data is loaded. Under most situations, this means you should be able to save Scene Relative Positional data without issue. However, if implementing a Save System where the saving can occur over multiple frames, special care must be taken to ensure the Origin Cell does not change while the save operation is executing. Please adhere to the following guidelines in these situations:
1) Your Save script should implement the IWorldUser interface and register with the World as a user.
2) You should return false for the IWorldUser's IsReadyForOriginCellChange implementation if it is queried while a save operation is in progress.
3) Once the World Users OnOriginCellChanging method is called (which indicates that the Origin Cell Change is now in progress), the save script should delay save operations until the change is completed.
4) Depending on the value you return from your World User's UseFastOnOriginCellChangedMethod property, either OnOriginCellChanged_Fast or OnOriginCellChanged_Slow will be called. These methods are called when the Origin Cell change has completed, so you can use one of them to remove the save delay. You could even use the OnOriginCellChanged_Slow method to execute the pending multi-frame save.
The World delays execution of its next Update (in which the Origin Cell will be changed) until all users return true for IsReadyForOriginCellChange, which allows users to purposely delay the Origin Cell Change if it would cause issues with an operation they currently have in progress.
For more information on World Users and the IWorldUser interface, please take a look at the World Users Section within this Chapter.
As stated before, the Origin Cell and Position of Sub World Groupings is not modifiable; these settings are automatically calculated by the World at runtime using the Base World Grouping's Origin Cell and Position.
You can however view these settings in the inspector, after you have entered Play Mode, by navigating to the Sub World Grouping in the World Inspector and looking at the Grouping's General Settings Window. There, you will find each Grouping's calculated Origin Cell and Position.
These settings can also be retrieved via scripting after the World has been initialized, using the GetOriginCellOfWorldGrouping and GetOriginCellPositionOfWorldGrouping methods.
Do keep in mind that if your game world is small, there may not be a need to use a floating origin based World. In such worlds, you can always use the Scene Relative Positions if you know that the Origin Cell will never change.
For such Worlds, it is recommended to set the Origin Cell and Position in the inspector such that the center of your Streamable Grid is as close to point 0,0,0 as possible. To find these values, first find the Streamable Grid Cell that the center of your Streamable Grid lies within. This will serve as the Origin Cell (if it's in a corner or edge, always use the Cell to the right and/or above the point).
For each axis, determine if the center lies within the Cell or on an edge between two Cells. If it is on the edge, set the Origin Position value for that axis to 0. If it lies within the Cell, calculate the distance from the left/bottom edge to the center point. Set the Origin Position value for that axis to the negative of this distance. For instance, if a Cell has a column width of 100 and the center is in the middle of the cell, the x value of the Origin Position would be set to -50.
When using a floating origin, we recommend setting an Origin Position value that results in the largest of your World Cells being centered over 0,0,0. For example, if the largest Column in your Base Grouping's Streamable Grid is 500, you should set the x value of the Origin Position to -250. Since the min corner of each World Cell is always placed at the Origin Position, this will cause the center of World Cells with width of 500 to be perfectly at x = 0.
If these concepts are still not making sense, it may help to view the Getting Started Tutorial Video, which details these concepts with visual aids: