初始化obs/Unity仓库
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
##### 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`。所以你的进度条看起来一瞬间就加载完了。
|
||||
Reference in New Issue
Block a user