Files
2026-05-03 14:06:26 +08:00

44 lines
2.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
##### 1.加载界面卡顿
我们在点击开始游戏的时候加载到游戏界面的过程中会卡顿,他会先卡顿一秒然后才进入到加载页面,他的问题就是SceneManager.LoadSceneAsync().
Unity 的所有核心逻辑,包括UI渲染、输入处理和大部分游戏逻辑的执行,都发生在**主线程**上。如果主线程被一个耗时很长的任务(比如一次性从硬盘读取大量数据并解压)卡住,那么整个应用程序就会冻结——画面停止渲染,UI无法响应。这就是你遇到的“卡顿”。
- **`SceneManager.LoadSceneAsync()` 的“陷阱”**
- **用途**:它的设计初衷是为了在后台线程加载场景资源,避免长时间冻结主线程。
- **原理**:虽然名字里有 `Async`(异步),但它在被调用的**第一帧**,仍然需要在**主线程**上执行一些同步的准备工作。这包括:从磁盘定位场景文件、读取场景的元数据、准备反序列化等等。如果你的场景很大,有很多`GameObject`和资源引用,这个“准备工作”本身就可能耗时几十到几百毫秒,足以造成肉眼可见的卡顿。
- **好/不好**:这个函数本身是好的,是异步加载的唯一标准方式。但**不好**的地方在于,开发者很容易误解它,以为调用它的瞬间就是完全异步的。
**代码1的问题剖析:**
```
// 在主线程的某个 Update 或按钮点击事件中被调用
public void Load(string next)
{
LoadingViewController.Instance.Open(); // 1. 请求打开UI
LoginViewController.Instance.Close();
StartCoroutine(LoadSceneAsync(next)); // 2. 启动协程
}
private IEnumerator LoadSceneAsync(string next)
{
// 3. 协程在下一帧开始执行
var operation = SceneManager.LoadSceneAsync(next); // 4. 问题点!
// ...
}
```
**执行流程与卡顿原因:**
1. **点击按钮(第N帧)**: `Load()` 方法被调用。它请求打开 Loading UI。但这只是一个请求,真正的UI绘制要等到这一帧的渲染阶段。
2. **启动协程**`StartCoroutine` 启动了协程,但协程的代码要到**下一帧(第N+1帧)**的 `Update` 阶段才会开始执行。
3. **协程开始(第N+1帧)**: 协程的第一行代码 `SceneManager.LoadSceneAsync(next)` 被执行。
4. **主线程阻塞**:此时,`LoadSceneAsync` 的同步准备阶段开始,它会阻塞主线程。如果场景很大,主线程可能会在这里卡住 1-2 秒。
5. **卡顿后果**:因为主线程被阻塞,第N帧请求绘制的 Loading UI 根本没有机会被渲染出来。所以你的游戏画面会停留在上一个界面(LoginView),直到 `LoadSceneAsync` 的同步阶段完成。
6. **加载飞快**:当卡顿结束后,`LoadSceneAsync` 已经把大部分重活都干完了,`operation.progress` 的值可能直接就是 `0.8` 或接近 `0.9`。所以你的进度条看起来一瞬间就加载完了。