Step 4 - Load assets
Overview
Up to this point within the tutorial we have included players, PhysX, and NPCs. Now we will explain how to setup and configure your game demo to download assets, add terrain to the PhysX scene, and handle initialisation of the terrain. We’ll also give an example of how to cook the terrain data, and host the assets on a local HTTP server for local tests.
One worker per machine will perform an HTTP request, minimising bandwidth and latency. More details on the asset loader can be found in the documentation.
Known issue: as it stands more than one worker per machine will attempt to download the assets. We are aware of the issue and are working on a fix for a later release.
By the end of this step you should be ready to dive into the netcode and net relevancy for optimisation of bandwidth.
Setup
Before we start let's see how the game world looks up to this point.
Get the Source
Navigate to the AetherHunt2 demo folder
There should be a local Git repo in there. All the steps of this tutorial are included as tags on the master
branch of this repo.
Check out the code for this step by running the following command git checkout step-4
. This will leave the code as it was at the end of the previous step. If you wish to check out the completed state of this section run git checkout step-4-complete
. Run git diff step-4 step-4-complete
to inspect the diff.
This step requires the asset server to be properly configured. See Getting started for more information.
Run the Simulation
Open PowerShell inside the simulation folder and run aether build
and aether run
commands
Build the project with
cmake -B build -G Ninja; ninja -C ./build
Run the simulation with
aether run
Once the simulation is running the client need to be built:
To run the client, open
Aether_Hunt.uproject
If you wish to debug the unreal client you can open the Visual Studio solution file and run debug mode from there. Caution this takes more resources
Click build to build the project
Click play to start the client
You will then enter the world as a player.
Look, the orcs are in the sky!
This is because the terrain has been loaded into the client but not into the simulation or parsed into the PhysX scene.
Exit the game and stop the simulation:
Hit \<esc> to exit the game client
Back on the PowerShell where the simulation is running
Press Ctrl+c
Press N to stop the Simulate simulation
How-To Guidelines
Downloading the Terrain on the Simulation
An http request will be made by a worker of the simulation to fetch the asset and allowing it to be used in the simulations.
cell_data.hh
The first thing we need to do is add the include of blob_store.hh
. This contains Aether Engine’s asset loading library which facilitates downloading and distributing data from external endpoints for use on the workers. For more information see the technical documentation.
We then add the necessary members:
download_terrain
andterrain_blob
are what we use to initiate an asset download and store it in shared memory.The mesh pointer
physx::PxTriangleMesh*
is where we will store the parsed PhysX terrain.
Releasing the mesh in the destructor contained within struct cell_data
. This is important to avoid a memory leak.
cell_data.cc
We fill in the constructor for the blob store std::future
. Here we’re making use of the user args again to make it easy to replace these values without rebuilding later. We need to define the address, port and parameters for the terrain download. These parameters can be specified here or passed as user arguments by using the user config file.
Once we have setup the download of the asset into the simulation we have to add the code to use it.
In cell_data::initializing_tick()
a timeout is kept. This is important in order to get relevant output in case of download failure. This checks every tick whether the download is complete.
Adding the Terrain to the PhysX Scenes
cell_data.cc
Still in cell_data::initializing_tick()
, we proceed to parse the serialised mesh into PhysX and store in cell_data::mesh
.
Turning now to initialise_scene()
, we insert the terrain mesh into the PhysX scene.
We already have all our user args, TERRAIN_*
.
TERRAIN_STATIC_FRICTION
- the coefficient of static friction affects how much friction is applied between two surface contact points when they have zero relative velocityTERRAIN_DYNAMIC_FRICTION
- the coefficient of dynamic friction affects how much friction is applied between two surface contact points when there is a non-zero relative velocityTERRAIN_RESTITUTION
- the coefficient of restitution affects how much kinetic energy is lost or gained when two objects collideTERRAIN_SAFETY_NET_Z
- the height of the flat plane
We just need to move the plane down out the way down to z=-300
. This will stop the simulation crashing if a capsule somehow finds itself falling underneath the terrain and it tries to fall to negative infinity under gravity.
Further down we create a rigid static body, rotate it, and add it to the scene.
Streaming and Initialising Cells
simulate.cc
It is important to understand how the user_cell_stat_impl::cell_tick()
behaves.
The cell tick won’t proceed until the terrain is downloaded. This is by design within this tutorial, as we do not need to worry about long download times given the assets are not large. It also ensures the terrain is downloaded before we process any PhysX. No action is required but it is important to understand the behaviour.
It’s up to the developer to decide how the simulation behaves whilst downloads are pending - in our case there is nothing meaningful to process without the terrain, but it could be that you proceed with partially complete game logic as things stream in. For example, if you were streaming in a city you may progressively refine the detail of the mesh, starting with a boxy world, and loading more fine detail over time. This logic is built within the user_cell_state_impl::cell_tick
where we simply skip processing the tick if our assets are not yet downloaded.
world.hh The raycast added in a previous step will spawn NPCs nicely near the surface of the terrain.
We have now completed setting up how to download and load the terrain into the game simulation. In previous steps we have included players and physics, but hadn’t imported any terrain. Now that the terrain is included we should be able to run and build our simulation.
Baking Assets
We include an example program for baking an obj mesh file into a serialised PhysX vertex mesh. This can be found in AssetBaker/
. There is, however, a pre-baked mesh included terrain.obj.cooked
in the assets directory, so that step can be skipped if you don’t intend to edit the terrain.
For the simulation to be able to download the terrain we need to pass the remote server address to which the simulation will connect to for that purpose. Inside simulation directory exists a file named user.cfg
that contains assets for the simulation. We need to set TERRAIN_ADDRESS=runtimeassetsaether.z33.web.core.windows.net \
for the download to be possible.
user.cfg
This is a example of a config file
If you want to see the terrain in the PhysX visual debugger set PVD_ENABLED
to 1.
Build and Run the simulation
Now that we’ve made the changes, let’s build and run the simulation again and check the results.
Build the project with
cmake -B build -G Ninja; ninja -C ./build
Run the simulation with
aether run
And the same with the client:
To run the client, open the
Aether_Hunt.uproject
If you wish to debug the unreal client you can open the Visual Studio solution file and run debug mode from there. Caution this takes more resources
Click build to build the project
Click play to start the client
You should now see all of the orcs running around on top of the loaded terrain.
Below is how the NPCs and PhysX is viewed within the PhysX visual debugger.
You are now ready to move on to Step 5: Netcode
Summary
In this section we were able to download and distribute a raw asset containing our 3D terrain collision mesh, and then parse and add it to the PhysX scene in each cell. The NPCs track the terrain and the work is load balanced spatially across cells using Simulate's quadtree.
If you want to checkout the source code state as it should be at this point, run git checkout step-4-complete
.
Next, is our final step, where we take a look at the netcode which runs on the array of Connect nodes that exist between the simulation and game-clients. We’ll be able to visualise Simulate's quadtree and also dynamically configure net relevancy by sending messages from the client for debug visualisation purposes.
Last updated