Files
engine/docs/zh/core/scene.mdx
鹅叔 dc1a4793ed Docs: remove playgrounds (#2689)
* fix: doc typo
2025-05-23 17:24:53 +08:00

151 lines
5.2 KiB
Plaintext
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.
---
order: 2
title: 场景
type: 核心概念
label: Core
---
<Image src="https://gw.alipayobjects.com/zos/OasisHub/cbcc9725-811d-4203-a65d-b4a430083db3/image-20250124154359477.png" />
Scene 作为场景单元,可以方便的进行实体树管理,尤其是大型游戏场景。如: **scene1** 和 **scene2** 作为两个不同的场景,可以各自独立管理其拥有的 **Entity** 树,因此场景下的光照组件、渲染组件和物理组件之间也互相隔离,互不影响。我们可以同时渲染一个或多个 Scene也可以在特定时机下根据项目逻辑动态切换当前 Scene。
从结构上每个 Engine 下可以包含一个和多个激活的场景(目前编辑器还不支持多个)。每个 Scene 可以有多个根实体。
## 编辑器使用
### 创建和切换
在 **[资产面板](/docs/assets/interface)** 右键(或资产面板右上角 + 号)创建场景,双击场景可以切换过去:
<Image src="https://gw.alipayobjects.com/zos/OasisHub/eef870a7-2630-4f74-8c0e-478696a553b0/2024-03-19%25252018.04.02.gif" />
### 环境光
详情请参照[环境光教程](/docs/graphics/light/ambient/) 和 [烘焙教程](/docs/graphics/light/bake/)。
### 背景
详情请参照[背景教程](/docs/graphics/background/background/)。
### 阴影
详情请参照[阴影教程](/docs/graphics/light/shadow/)。
### 雾化
可以给整个场景增加 **线性、指数、指数平方** 3 种雾化:
<Image src="https://gw.alipayobjects.com/zos/OasisHub/224fbc16-e60c-47ca-845b-5f7c09563c83/2024-03-19%25252018.08.23.gif" />
## 脚本使用
| 属性名称 | 解释 |
| :---------------------------------------- | :------- |
| [scenes](/apis/core/#SceneManager-scenes) | 场景列表 |
| 方法名称 | 解释 |
| :-------------------------------------------------- | :------- |
| [addScene](/apis/core/#SceneManager-addScene) | 添加场景 |
| [removeScene](/apis/core/#SceneManager-removeScene) | 移除场景 |
| [mergeScenes](/apis/core/#SceneManager-mergeScenes) | 合并场景 |
| [loadScene](/apis/core/#SceneManager-loadScene) | 加载场景 |
### 加载场景
如果想要加载 **Scene** 资产作为应用中的一个场景,可以使用 `engine.resourceManager.load` 传入 url 即可。
```typescript
const sceneUrl = "...";
engine.resourceManager.load({ type: AssetType.Scene, url: "..." }).then((scene) => {
engine.sceneManager.addScene(scene);
});
```
### 获取场景对象
通过调用 `engine.sceneManager.scenes` 可以获取当前引擎运行时激活的全部场景,也可以通过 `entity.scene` 获取对应 `entity` 从属的 `scene`。
```typescript
// 获取当前所有激活的场景
const scenes = engine.sceneManager.scenes;
// 获取节点属于的场景
const scene = entity.scene;
```
### 添加/移除 Scene
`engine.sceneManager.scenes` 是只读的,若需要添加和移除 **Scene** ,需要调用 `engine.sceneManager.addScene()` 或 `engine.sceneManager.removeScene()` **引擎支持同时渲染多个场景**。
```typescript
// 假设已经有两个场景
const scene1, scene2;
// 添加 场景1
engine.sceneManager.addScene(scene1);
// 添加 场景2
engine.sceneManager.addScene(scene1);
// 移除 场景2
engine.sceneManager.removeScene(scene2);
```
### 合并场景
可以使用 `engine.sceneManager.mergeScenes` 将 2 个场景进行合并为 1 个场景。
```typescript
// 假设已经有两个未激活的场景
const sourceScene, destScene;
// 将 sourceScene 合并到 destScene
engine.sceneManager.mergeScenes(sourceScene, destScene);
// 激活 destScene
engine.sceneManager.addScene(destScene);
```
### 销毁场景
调用 `scene.destroy()` 即可销毁场景,被销毁的场景也会自动从激活场景列表中移除。
### 实体树管理
| 方法名称 | 解释 |
| :-- | :-- |
| [createRootEntity](/apis/core/#Scene-createRootEntity) | 新创建的 _scene_ 默认没有根实体,需要手动创建 |
| [addRootEntity](/apis/core/#Scene-addRootEntity) | 可以直接新建实体,或者添加已经存在的实体 |
| [removeRootEntity](/apis/core/#Scene-removeRootEntity) | 删除根实体 |
| [getRootEntity](/apis/core/#Scene-getRootEntity) | 查找根实体,可以拿到全部根实体,或者单独的某个实体对象。注意,全部实体是只读数组,不能改变长度和顺序 |
```typescript
const engine = await WebGLEngine.create({ canvas: "demo" });
const scene = engine.sceneManager.scenes[0];
// 创建根实体
const rootEntity = scene.createRootEntity();
// 添加实体到场景
scene.addRootEntity(rootEntity);
// 删除根实体
scene.removeRootEntity(rootEntity);
// 查找根实体
const allEntities: Readonly<Entity[]> = scene.rootEntities;
const entity2 = scene.getRootEntity(2);
```
### 其他
需要注意的是,当我们熟悉了 [Engine](/apis/core/#Engine) 和 [Scene](/apis/core/#Scene) 之后,如果想要将渲染画面输出到屏幕上或者进行离屏渲染,我们还得确保当前 _scene_ 的实体树上挂载了 [Camera](/apis/core/#Camera),挂载相机的方法如下:
```typescript
const cameraEntity = rootEntity.createChild("camera");
cameraEntity.addComponent(Camera);
```