Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Planning for Async/Non-Blocking World Loading #42

Open
BraedonWooding opened this issue Apr 11, 2017 · 0 comments
Open

Planning for Async/Non-Blocking World Loading #42

BraedonWooding opened this issue Apr 11, 2017 · 0 comments

Comments

@BraedonWooding
Copy link
Member

Issue by bjubes
Sunday Feb 26, 2017 at 17:30 GMT # Sample: Friday Sep 13, 2013 at 22:58 GMT
Originally opened as TeamPorcupine/ProjectPorcupine#1784


As discussed in #1593, one of the largest lag spikes in the game is loading a new world or save. Since this is not done asyncronously, the build appears to have crashed and prompts the user to force close the program. Fixing this is a complex task, So i'm putting together a place to create a solution.

The Problem

When the new world is loaded, a variety of slow operation all fire at once.

  • loading the save file/ generating a new world
  • Destroying everything in the current scene, and the resulting garbage collection
  • Instantiating every game object in the new scene, and the resulting memory allocation and unity lag that comes with Instanciating.
  • running the start method of every object in the _World, which then calls almost every constructor of every manager, controller, etc...
  • If its a save, the characters may all have a pathfinding call on top of that.

The Solution

I plan to focus on the fourth bullet, the constructors/start methods of every single manager and controller called when the game loads. These can be split into two categories: Unity centric and non Unity centric. The former interact with some aspect of unity that cannot be put in another thread, like Resource.Load or instanciating gameobjects. the latter only do calculations or can be tailored to do most of their work asyncronously and do the unity specific-work in a callback.

First every start method and constructor has to be analyzed to see what category it falls into. Next, a "master" object will be repsponsible for invoking all start/initialization related calls. Those that have no unity interaction can be run in another thread, while the unity centric ones are put into a queue inside the master object. The master object starts a couroutine where it cycles through the queue like so

//pseudo-code - inside a coroutine
start a timer
while ( timer < maxTimeAllowedPerFrame) {
nextItemInQueue();
}
yield return null;

so that the longest hang time is reduced to the time it takes one function to run/the maxTimeAllowed. Obviously this could take a very long time to complete, so it is important to thread as many calculations and split up large calls into smaller parts. While the queue is still full, the user simply gets a "loading..." dialog and the game will never lag long enough for the OS to report it as not working.

last note: any processes that need to happen in a specific order can hopefully be achieved by a series of callbacks, so that when the first one finishes it puts the next callback into the master queue.

This video is an implementation of a similar system. Its used for pathfinding but the general idea is the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant