# Scene streaming

When loading a large scene with many Prefabs, the download dependent resource size may reach tens of MB, and the entire download process will be relatively long. In order to solve this problem, the WeChat Mini Game Framework provides a scene streaming solution to achieve dynamic on-demand loading of Prefabs in the scene.

The core of the streaming loading solution is the StreamingLoadingComponent component.

# Editing and baking period

  1. Mount the StreamingLoadingComponent node in the editor, and the node tree created by Prefab among its direct child nodes will be regarded as the node tree to be dynamically loaded. As shown in the figure below, the World node is mounted with StreamingLoadingComponent, and the floor, wall1, wall2 and other sub-nodes below it are all created by Prefab.

  1. Introduction to StreamingLoadingComponent properties
Properties Functions
loadingPrioirty Indicates the loading priority of these child nodes.
unloadType Indicates what operation should be applied when these child nodes are dynamically unloaded.
    Deactivate means to set the active of these nodes to false.
    Destroy means that the destroy method of the node will be called, that is, destroyed.
unloadDebounce Indicates a debounce waiting time when the node is determined to be unloaded, in order to avoid repeated unloading caused by the player repeatedly moving in a boundary area.
  1. Right-click the scene in Project and click "Bake Streaming Load Scene".

  1. Baking a scene means to remove all the nodes in the scene that need to be dynamically loaded from the scene mygame.scene and save it as a new scene file. After starting to bake, you need to wait for a while, and there will be a floating window in the upper corner when it is finished

Take the World node here as an example. The next 15 child nodes are all created by Prefab, so in the newly generated assets/bake/mygame.bake.scene, the information of these 15 child nodes is eliminated. Mygame.bake.scene and Prefab corresponding to 15 child nodes will be generated under the assets/bake directory.

  1. Set the directory of the output baked file as the packaging entry, so that the generated Prefab can be dynamically loaded.

  1. Start the build with the baked file as the entrance

# Runtime

Engine.game.streamingLoadingSystem needs to be set at runtime to manage StreamingLoadingComponent.

# interval

What streamingLoadingSystem does is to check the StreamingLoadingObject under StreamingLoadingComponent every once in a while (the above World is an example, StreamingLoadingObject is 15 Prefabs to be dynamically loaded) whether it needs to be loaded/unloaded. This is an update of streamingLoadingSystem.

// The default value is 500, the unit is ms
engine.game.streamingLoadingSystem.interval = 1000;

# Tester

Determining whether an object is to be loaded is controlled by engine.game.streamingLoadingSystem.tester. Tester is an object that implements two methods needTest and test. Both of these methods are callback functions that are called by streamingLoadingSystem every update.

needTest() {
  return true
}

# Tester.prototype.needTest()

needTest is a callback function with no parameters, indicating whether subsequent traversal is required. For example, if the viewing angle/player position does not change much, it can be understood that the player’s field of view does not change much, so there is no need to traverse to check whether the object needs to be loaded/unloaded.

# Tester.prototype.test(object)

test is a callback function passed in StreamingLoadingObject, StreamingLoadingObject contains the following properties

test(object) {
  // object.center, Vector3, represents the center of the object surrounding the ball, which is a worldPosition
  // object.radius, represents the radius of the object surrounding the ball, which is also in the world coordinate system
  // object.priority represents the loading priority of the object
  // return 0 for loading
  return 0
  // return 1 means uninstall
  return 1
}

The default value of engine.game.streamingLoadingSystem.tester is a tester implemented by the engine based on the detection of the intersection of bounding spheres. If there is no special need, you can use this tester.

const tester = engine.game.streamingLoadingSystem;
// Set center to represent the current player's position, center is a Vector3, and it should be a worldPosition.
tester.center.x = -131;
tester.center.y = 50;
tester.center.z = 80;
// Set radius to indicate the player's field of view, objects that intersect within this range will be loaded, otherwise, the objects beyond this range will be unloaded
tester.radius = 50;

If you think that such a tester cannot meet the requirements, you can implement a tester yourself

class CustomTester {
  constructor() {
    this.lastPosition = engine.Vector3.createFromNumber(0, 0, 0);
    this.currentPosition = engine.Vector3.createFromNumber(0, 0, 0);

  }
  needTest() {
    // The last observation point is greater than a certain distance from the current observation point before the detection is performed
    if (this.currentPosition.distanceTo(this.lastPosition)> 20) {
    this.lastPosition.x = this.currentPosition.x;
    this.lastPosition.y = this.currentPosition.y;
    this.lastPosition.z = this.currentPosition.z;

    return true;
    }
    return false;
  }
  test(object) {
    // Special needs, 999 means it must be loaded and never unloaded
    if (object.priority === 999) {
        return true
    }
    // ...
  }
}

engine.game.streamingLoadingSystem.tester = new CustomTester()

After the scene streaming is completed, the resources that dynamically loaded nodes depend on will not be loaded when the scene is loaded. If the root node of the scene is the World in the above example, this scene will not have any dependent resources; all nodes are dynamic When the streamingLoadingSystem determines that it needs to be loaded, it will download & read the corresponding Prefab.