| 278 | } |
| 279 | |
| 280 | void Engine::tick() { |
| 281 | CC_PROFILER_BEGIN_FRAME; |
| 282 | { |
| 283 | CC_PROFILE(EngineTick); |
| 284 | |
| 285 | _gfxDevice->frameSync(); |
| 286 | |
| 287 | if (_needRestart) { |
| 288 | doRestart(); |
| 289 | _needRestart = false; |
| 290 | } |
| 291 | |
| 292 | static std::chrono::steady_clock::time_point prevTime; |
| 293 | static std::chrono::steady_clock::time_point now; |
| 294 | static float dt = 0.F; |
| 295 | static double dtNS = NANOSECONDS_60FPS; |
| 296 | |
| 297 | ++_totalFrames; |
| 298 | |
| 299 | // iOS/macOS use its own fps limitation algorithm. |
| 300 | // Windows for Editor should not sleep,because Editor call tick function synchronously |
| 301 | #if (CC_PLATFORM == CC_PLATFORM_ANDROID || (CC_PLATFORM == CC_PLATFORM_WINDOWS && !CC_EDITOR) || CC_PLATFORM == CC_PLATFORM_OHOS || CC_PLATFORM == CC_PLATFORM_OPENHARMONY || CC_PLATFORM == CC_PLATFORM_MACOS) |
| 302 | if (dtNS < static_cast<double>(_preferredNanosecondsPerFrame)) { |
| 303 | CC_PROFILE(EngineSleep); |
| 304 | std::this_thread::sleep_for( |
| 305 | std::chrono::nanoseconds(_preferredNanosecondsPerFrame - static_cast<int64_t>(dtNS))); |
| 306 | dtNS = static_cast<double>(_preferredNanosecondsPerFrame); |
| 307 | } |
| 308 | #endif |
| 309 | |
| 310 | events::BeforeTick::broadcast(); |
| 311 | |
| 312 | prevTime = std::chrono::steady_clock::now(); |
| 313 | if (_xr) _xr->beginRenderFrame(); |
| 314 | _scheduler->update(dt); |
| 315 | |
| 316 | se::ScriptEngine::getInstance()->handlePromiseExceptions(); |
| 317 | events::Tick::broadcast(dt); |
| 318 | se::ScriptEngine::getInstance()->mainLoopUpdate(); |
| 319 | |
| 320 | cc::DeferredReleasePool::clear(); |
| 321 | if (_xr) _xr->endRenderFrame(); |
| 322 | |
| 323 | // Executing async tasks at the end of the current frame to make the callback invoked as soon as possible. |
| 324 | _scheduler->runFunctionsToBePerformedInCocosThread(); |
| 325 | |
| 326 | now = std::chrono::steady_clock::now(); |
| 327 | dtNS = dtNS * 0.1 + 0.9 * static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(now - prevTime).count()); |
| 328 | dt = static_cast<float>(dtNS) / NANOSECONDS_PER_SECOND; |
| 329 | |
| 330 | events::AfterTick::broadcast(); |
| 331 | } |
| 332 | |
| 333 | CC_PROFILER_END_FRAME; |
| 334 | } |
| 335 | |
| 336 | void Engine::doRestart() { |
| 337 | events::RestartVM::broadcast(); |