基本概念
Render Pipeline
游戏引擎将3D Scene渲染到屏幕上的过程
unity中有三种渲染管线
- 内置:Built-in render pipeline
- 通用:Universal Render Pipeline
- 高级:High Definition Render Pipeline
URP (Universal Render Pipeline, 通用渲染管线)
- 性能:前向渲染,对低端硬件友好;渲染控制:剔除、降级适合移动端
- 可扩展:支持自定义渲染(custom render features) && Shade Graph自定义着色器
- 支持多平台,增强不同设备下的视觉一致性
- 不适合高级、极致真实的渲染
Effect-Related
Post-Processing Effect (后处理效果)
是场景在渲染后的进一步处理,其包括
- 抗锯齿 Anti-Aliasing
- 景深 Depth of Field
- 色彩调整 Color Grading
- 动态模糊 Motion Blur
- 辉光 Bloom
- 屏幕空间反射 SSR
Global Volume (全局体积)
是post-process的载体,所有的后处理需要通过volume profile在global volume中定义
效果:对整个场景生效,影响相机渲染的所有内容
Local Volume(局部体积)
与全局体积对应,作用于局部效果
Canvas(画布)
canvas是UI的root节点:所有的UI元素都需要canvas才能渲染,是渲染的必要条件
维度投射:可以将三维空间的元素投射到二维
canvas在unity中有三种不同的模式
- 默认模式:Overlay (screen space)
- 位于最顶层,独立于相机
- 尺寸与屏幕分辨率一致
- 与相机绑定:Camera (screen space)
- UI被渲染到指定相机视图中
- 可设置渲染距离
- World Space
- 将UI设置为世界中的3D对象
MonoBehavior
Unity中的核心基类,继承自它的类可以基于hooks、event进行编程
hooks
- Awake():在脚本实例被加载时调用,通常用于初始l化变量或引用其他组件。
- Start():在脚本实例启用后,在第一帧更新之前调用,通常用于初始化需要在
Awake()
之后执行的逻辑。 - Update():每帧调用一次,通常用于处理游戏逻辑和输入。
- FixedUpdate():在固定的时间间隔调用,通常用于处理物理相关的逻辑。
- LateUpdate():在
Update()
之后调用,通常用于处理相机跟随等需要在所有更新之后执行的逻辑。 - OnEnable():当脚本实例被启用时调用。
- OnDisable():当脚本实例被禁用时调用。
- OnDestroy():当脚本实例被销毁时调用。
event
- OnCollisionEnter(Collision collision):当碰撞发生时调用。
- OnTriggerEnter(Collider other):当触发器被触发时调用。
- OnMouseDown():当鼠标点击游戏对象时调用。
- OnBecameVisible():当游戏对象进入相机视野时调用。
- OnBecameInvisible():当游戏对象离开相机视野时调用。
GameObject
基本实体构建块。所有实体都通过GameObject来构建,其本身只是个容器,所有的行为通过组件来实现
默认会携带Transform组件,用于控制位置、方向、旋转、缩放
其在unity editor中可以以其作为层级结构 Hierarchy来组织场景中的对象
GameObject gameObject = new GameObject("GameObject");
设置父级
gameObject.transform.SetParent(transform);
RigidBody
Rigidbody rb = gameObject.AddComponent<Rigidbody>();
rb.mass = 2;
rb.useGravity = true;
Light
Light light = gameObject.AddComponent<Light>();
light.type = LightType.Point;
Mesh
MeshRenderer renderer = gameObject.AddComponent<MeshRenderer>();
MeshFilter filter = gameObject.AddComponent<MeshFilter>();
GameObject tempCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
filter.mesh = tempCube.GetComponent<MeshFilter>().mesh;
Object.Destroy(tempCube);
COllider
Collider collider = gameObject.AddComponent<BoxCollider>();
Position
gameObject.transform.position = new Vector3();
Mesh
mesh是三维模型的基础数据结构,定义物体的形状与外观。
由顶点、边、面组成
- 顶点:Vertex
- 边:Edge
- 面:Face(多为三角形)
为什么面一般由三角形构成?
三角形是最简单的多边形,易于计算和渲染
Coroutine & Async
Coroutine
基于IEnumerator
和yield return
,的用于处理需要分步执行的任务的方式,通过yield return
来暂停和继续。在unity中,coroutine用于轻量级异步编程,其life time与MonoBahaviour绑定
特性
- 迭代器:基于IEnumerator实现, 通过yield return暂停执行
- 主线程运行:Coroutine运行于主线程,适合处理与Unity对象相关的任务(动画、延时)
Async
C#的异步,基于TPL(Task Parallel Library)
和状态机,通过await
等待运行完毕
特性
- 多线程并行
- 非阻塞
- 后台运行
具体实现
IO For User
在update中按帧调用
void Update()
{
// 获取水平方向和垂直方向的输入
float moveX = Input.GetAxis("Horizontal") * baseSpeed * Time.deltaTime;
float moveZ = Input.GetAxis("Vertical") * baseSpeed * Time.deltaTime;
// 根据输入移动当前GameObject
transform.Translate(moveX, 0, moveZ);
}
SerializeField
[SerializeField] 将private的属性强制序列化,其在Unity编辑器中显示
[System.Serializable] 标记类可被序列化,其实例可被unity中的序列化系统加载(Monobehaviour不支持序列化)
Unity UI与Script连接:在Empty Object-Serialize的类中,拖拽Unity视图节点
C#
IEnumerator
迭代器类型声明
视觉小说
文字渲染
渲染模式
单字符叠加
问题: - 使用特殊效果时,比如下划线、加粗,会把源码也渲染上来 - 某个单词过长时,会导致换行出现问题
打字机(tmpro)
渐变(tmpro)
渲染组成
- 文字
- 当前要渲染的文本
- 将要渲染的文本
- 已有的文本
- 整体的文本(已有文本 + 将要渲染的文本)
- 文字颜色
- 渲染速度
- 基础速度
- 加速系统
- 渲染模式
TMPro的渲染流程
- 文字输入解析:文本、字体、颜色、样式
- 字形处理:选择字体 && 提取字形,转换为纹理或矢量数据
- 布局排版
- Mesh Generation:字符转换为一个四边形(Quad),并生成对应的顶点、UV 和三角形数据 && 使用纹理或材质渲染文本
- 渲染准备 & 渲染:使用着色器渲染文本 && 批处理减少绘制调用(Draw Calls) => GPU渲染
剧情组成部分
- Dialogue System 对话系统:文本渲染 && 文本读取
- Dialogue Container 对话容器:包括了UI层面的Container,Name,Text