I’ve been trying the following to figure out if there’s time left in a frame vs target frame rate, and use excess time to build the world around the player, but it doesn’t work. It keeps building even when frame rate drops way low. So I’m hoping for ideas, … I’m sure alot of you have had the same challenge with in-frame timing.
A simple timer class using Stopwatch, with project settings - Script Execution Order set to -32000:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Diagnostics;
public class Timer : MonoBehaviour
{
static public Stopwatch timer;
void Start()
{
timer = new Stopwatch();
timer.Start();
}
private void Update()
{
timer.Restart();
}
}
And in the builder-class (with Script Exectution Order 1000) I run the test in LateUpdate (also, the only LateUpdate I have in project):
Wait, according to this, Unity - Manual: Order of execution for event functions, scene rendering is done after scripts including LateUpdate, so I guess the only way to find time left in a frame is to look for lowest frame rate encountered lately, and find the proper time left in the current frame based on that? which would be the variable to swap out my hard coded ‘14f’ milliseconds to check against.
Glad you found your solution, but if you are generating something around the player, you probably want to get it off the mainthread anyways. What if your target framerate is unbound, or really high, or there is just little to no time left? Are you fine with the world generation taking literally forever, simply because you determine the time it gets to run based on what’s left between frames? That does not seem to be a good idea for most situations.
Or rather, it is not a good idea, and it wont work in a lot of situations.
Before I get to any proper testing it’s hard to say what will work or not, so you might very well be right with your questions and assumptions.
Indeed. I need to get as much as possible off the main thread for performance. Not there yet though, ECS monster chew me up and spit me out, so I’m back to basics to get ideas going.
Well, I can choose the game’s target frame rate or the player.
There is a indeed a problem that building will in certain situations take forever because of lack of time, so this approach will need to work together with a dynamic quality level control, to make sure the building can progress. Also creating levels of detail, so that rough objects are created and spawned before more detailed ones.
ECS can be a bit daunting, but Jobs and Burst can be used for easy yet increadibly efficient multithreading.
What exactly are you trying to do? You could do what you do now in a similar way using Coroutines. And / or set a minimum of 1 ms to be worked on whatever you want to generate.
However, depending on what you do it wont really be possible to to do it in a while loop to precisely (or even roughly) match the left over time. You said something about generating objects of different levels of detail, implying to me that you plan on creating meshes, for example for a precudural world generator. However, to do something like that you’d need to know how long it takes to create one object, one chunk, or one whatever-else-unit. This can vary from object to object, and from hardware to hardware, making is basically impossible to guess the time it will take on any specific system, making it impossible to determine whether or not it fits into the left over time.
If it goes in the direction of procedural world generation, i’d generate each chunk in an efficient way using Jobs+Burst, and have some (GameObject) Manager class check on the “still generating” chunks each update cycle, to set the mesh information on the main thread after the jobs are completed. Or rather, that’s how i did it when i experimented with procedural generation. Pretty sure there would be a pure DOTS approach to this as well tho.
Well, it’s not one single idea, but the most important point is that the player should be experiencing something new and interesting each time entering a new world or zone. I’m focusing on the world building for now, while game play ideas are forming. I want to achieve this by generalizing wherever I can, “probability randomizing” everything possible, and run generated data through layers of filters.
So yes, it’s definitely procedurally based, and I’m making a point of making it 100% procedurally, as I find it fun to do.
Just one predefined GameObject to kick everything off. I will have to consider having some media files as starting points down the road, if I find some element too time consuming to create through code. (Sound data comes to mind.)
These are great pointers. Coroutines, Jobs and Burst should help accomplish my goals. Cheers.
Yes, that sounds solid. Generation (species and population) done per chunk, but I’m thinking jobs might be per species instead of the whole chunk. The manager can probably be allowed to get information as soon as a species is ready.
Thanks again, Yoreki. This answer was originally 4 pages long, as your input makes me think through the ideas.
I’m not quite sure what you mean by species, since you first mentioned the term in your last sentence pretty much.
Anyways, if you are going to do some procedural generation, then dont do it the way you intended with using up the calculated rest-time. For any realistic use case, this just wont cut it. From what you said, Coroutines wont either, since you really want to make use of as much of the CPU as possible. All of the procedural generation can basically run in the background, as you only need to do very few specific actions on the mainthread. I already described the way i did it, and that i believe there is a pure-DOTS approach to do this, so i’ll leave you with a tutorial (series) that you may find helpful:
I’m assuming you want to do something similar. If you want to procedurally place items on some terrain, you can use an algorithm used Poisson Disc Sampling, which also works decently with a chunk based approach, and is covered on the same channel, which does a great job at explaining these kinds of things imho.
If i somehow completely missed what you plan to do (for example, if you want closed, dungeon like maps), feel free to explain it in more detail. I’m sure i can offer some more information, or link you some more helpful videos or papers maybe. Other than that,
wish you best of luck with your project