Unity文档阅读笔记(一)Working in Unity

上一篇博客结束,应该可以对Unity有个总体但是不深入不系统的理解,这次开始就从头系统得阅读官方文档来深入了解Unity的各种概念和功能。

开始阅读Unity

Creating Gameplay

Scene:场景

场景是你在Unity中处理内容的地方。它们是包含游戏或应用程序全部或部分内容的资产。例如,你可能会在单个场景中创建一款简单的游戏,而对于更复杂的游戏,你可能会在每个关卡中使用一个场景,每个场景都有自己的环境、角色、障碍、装饰和UI。你可以在一个项目中创建任意数量的场景。当你创建一个新项目并首次打开它时,Unity会打开一个只包含摄像机和灯光的示例场景。

创建新的场景

创建新的场景有三种方式:

  • 使用创建场景对话框,可以选择根据某个模版创建新的场景(File -> New Scene)。
  • 使用菜单直接根据当前场景创建新场景(Asset -> Create -> Scene)
  • 使用脚本创建,创建语句会返回新场景的指针,并且会触发创建场景的事件。如果场景模版中有cloned的资源或者依赖,需要指定保存这些资源的路径。

加载场景

要打开一个场景,执行以下操作之一:

  • 在项目窗口中,双击场景资源。
  • 从菜单中,选择文件>新场景
  • 从菜单中,选择文件>最近场景> [NAME-OF-SCENE]

如果你当前场景包含未保存的更改,Unity会提示你保存场景或放弃更改。

保存场景

多场景同时编辑

Unity - Manual: Multi-Scene editing

可以在编辑器中同时打开多个场景进行编辑,但是保存时各个场景都要单独保存一次。

目前不太清楚这个功能意义何在,就是同时把多个场景放进了Hierarchy,具体编辑起来和单个场景没什么太大区别。

Scene Template

Unity使用场景模板来创建新的场景。场景模板是存储在项目中的资产。它们与场景相似,但设计的目的是复制,而不是直接使用。

场景模板可以用于相同场景的快速复用,也可以通过脚本来根据模版创建具体的场景。

每次创建新的场景,Unity都是复制了场景模板。可以将场景模板视为预先配置的场景,其中包含您想要开始的所有内容。例如,默认的Basic模板通常包含一个相机和一个灯。您可以创建自己的场景模板来定制您可以在项目中创建的新场景的类型。例如,你可以为游戏中的每个关卡创建模板,这样项目中的每个人都可以使用正确的资产和配置开始他们的场景。你可以从任何Unity场景中创建模板。

创建场景模版的方式

  • 创建空模板
  • 从已存在的某个场景创建模版
  • 从当前场景创建模版
  • 利用脚本创建模版(可以创建空模板,或者根据某个场景创建模版)

上述过程中,除非是创建空模板,Unity会询问哪些资源或者依赖是需要被复制而不是被引用的。

这里就需要注意了,复制的资源是独立的,引用的资源是共同的,如果错把一个引用的资源当成独立的修改,可能会引入bug。

编辑场景模版

Unity - Manual: Editing scene templates

  • 详细信息:指定模板使用的场景,并包含出现在“新建场景”对话框中的模板描述。
  • 缩略图:提供为模板创建预览图像的选项。
  • 场景模板管道:指定一个可选的自定义脚本,当Unity从模板创建一个新的场景时运行。
  • 依赖项依赖项属性:在它们的清单中定义它们需要的包集。对于项目,这些被认为是直接依赖;对于包来说,这些是间接的或传递的依赖关系。

img

自定义场景的创建过程

其实每次新建场景都是从场景模版中创建一个实例出来,所以Unity提供给我们模版实例化过程中类似hook或者生命周期的能力。

当Unity从模板中实例化一个新场景时,要运行自定义代码,创建一个场景模板管道脚本并将其连接到模板。每次你从模板中创建一个新的场景,Unity也会创建一个管道脚本的新实例。

Unity - Manual: Customizing new scene creation

我们可以先定义一个Pipline(必须声明ISceneTemplatePiplne接口)

img

然后绑定到场景模版流水线中

GameObject

Unity - Manual: GameObjects

游戏对象是Unity编辑器中最重要的概念。游戏中的每个对象都是游戏对象,从角色、可收集的道具到灯光、摄像机和特效。然而,一个游戏对象不能自己做任何事情;在它成为角色、环境或特殊效果之前,你需要赋予它属性,也就是Component。

游戏对象是Unity中代表角色、道具和场景的基本对象。它们本身并没有完成多少工作,但它们充当实现功能的组件的容器。

所以GameObject其实没什么好讲的,它能做什么,基本取决于它有什么Component。

Transform

Unity - Manual: Transforms

父子关系的影响

Transform的位置、旋转和缩放值是相对于Transform的父对象进行测量的。如果Transform没有父元素,则在世界空间中度量属性。

当一个游戏对象是另一个游戏对象的父对象时,子游戏对象的移动、旋转和缩放与其父对象完全相同。

非均匀的缩放会带来一些问题

非均匀缩放是指在变换中缩放的x、y和z值不同;例如(2,4,2)。相比之下,均匀缩放对x, y, z具有相同的值;例如(3,3,3)。非均匀缩放在一些特定的情况下可能很有用,但它会引入一些均匀缩放不会出现的奇怪现象:

  • 某些组件不完全支持非均匀伸缩。例如,一些组件有一个由半径属性定义的圆形或球形元素,其中包括Sphere Collider、Capsule Collider、Light和Audio Source。在这种情况下,圆形将不会成为椭圆形不均匀缩放,如你所期望的,将只是保持圆形。
  • 当子对象具有非均匀缩放的父对象并相对于该父对象旋转时,它可能显示为倾斜或剪切。有一些组件支持简单的非均匀缩放,但在像这样倾斜时不能正确工作。例如,一个倾斜的Box Collider将不能精确匹配渲染网格的形状。
  • 出于性能原因,非均匀缩放的父对象的子对象在旋转时不会自动更新其缩放。因此,当比例最终被更新时(例如,如果子对象从父对象分离),子对象的形状可能会突然发生变化。

缩放的重要性(尺寸的重要性):

Transform的规模决定了你的建模应用程序中的网格大小和Unity中的网格大小之间的差异。网格的大小在Unity(因此变换的比例)是非常重要的,特别是在物理模拟。默认情况下,物理引擎假设世界空间中的一个单位对应于1米。如果一个物体非常大,它看起来会以慢动作坠落;这个模拟实际上是正确的,因为实际上,你看到的是一个非常大的物体落在很远的地方。

有三个因素可以影响你的对象的尺寸:

  • 在3D建模应用程序中网格的大小。

  • 在对象的导入设置中设置网格比例因子。

  • The scale values of your Transform Component.

理想情况下,您不应该在Transform组件中调整对象的Scale。最好的选择是创建现实规模的模型,这样你就不必改变你的变换规模。下一个最好的选择是在你的网格的导入设置中调整你的网格导入的比例。根据导入大小进行某些优化,实例化具有调整过的缩放值的对象可能会降低性能。

Component

GmeObject是Unity编辑器中包含组件的对象。组件定义游戏对象的行为。要查看游戏对象的组件,在场景窗口或层次窗口中选择游戏对象,然后在检查器窗口中查看所有组件及其设置的列表。您可以在编辑器中直接与组件交互,也可以通过脚本进行交互。

编写脚本(或创建脚本)是使用Unity Scripting API在代码中编写自己添加的Unity Editor功能。当你创建脚本并将其附加到游戏对象时,脚本就会像内置组件一样出现在游戏对象的检查器中。这是因为当您将脚本保存到项目中时,它们就变成了组件。从技术角度来说,你制作的任何脚本都是一种组件类型,所以Unity编辑器将你的脚本视为内置组件。在检查器中定义要公开的脚本成员,然后编辑器执行任何函数

激活状态

你可以将一个游戏对象标记为非活动,以暂时将其从场景中移除。要做到这一点,

导航到检查器,取消勾选游戏对象名称旁边的复选框(见下图),或者在脚本中使用SetActive方法。如果要在一个对象被标记为活动或非活动时检入脚本,请检查activeSelf属性。

当你停用一个父游戏对象时,你也会停用它的所有子游戏对象。去激活覆盖了所有子游戏对象的activeSelf设置,所以Unity让整个层级从父层级向下处于非激活状态。这不会改变子游戏对象的activeSelf属性的值,所以当你重新激活父游戏对象时,它们会返回到原来的状态。

注意:这意味着你不能通过读取它的activeSelf属性来确定一个子游戏对象在场景中是否处于活动状态,因为即使它被设置为活动状态,它的父对象也可能处于非活动状态。

这就是说,activeSelf这个属性指的是GameObject自身的属性,并不一定是该GameObject是否在场景中厨艺激活状态,即,如果反激活父对象的avtiveSelf,并不会改变子的activeSelf属性,你去判断子的这个属性也还是true,但是该自对象并不会显示和执行。

Tag

标签是一个参考词,你可以分配给一个或多个游戏对象。例如,你可以为玩家控制的角色定义Player Tag,为非玩家控制的角色定义Enemy Tag。你可以用可收集标签定义玩家可以在场景中收集的物品。标签可以帮助你识别用于编写脚本的游戏对象。

他们确保你不需要手动添加游戏对象到脚本的暴露属性使用拖放,从而节省时间,当你使用相同的脚本代码在多个游戏对象。标签对于Collider控制脚本中的触发器很有用。

也就是当多个不同种类的GameObject具有某种逻辑层面上的相似性时,可以将这些GameObject的Tag设置为同一个,从而简化开发复杂度。

静态对象

如果一个游戏对象在运行时没有移动,它就被称为静态游戏对象。如果一个游戏对象在运行时移动,它就被称为动态游戏对象。Unity中的许多系统可以在编辑器中预计算静态游戏对象的信息。因为游戏对象不会移动,所以这些计算的结果在运行时仍然有效。这意味着Unity可以节省运行时计算,并有可能提高性能。

没有刚体且没有碰撞体的GameObject会被视为静态对象——印象中有这个说法,待考证

Static Editor Flags属性列出了许多Unity系统,它们可以在预计算中包含一个静态游戏对象。使用下拉列表定义哪些系统应该在预计算中包含游戏对象。在运行时设置静态编辑器标记对这些系统没有影响。你应该只在系统的预计算中包含一个游戏对象,因为系统需要知道这个游戏对象。在不需要知道游戏对象的系统的预计算中包含游戏对象可能会导致浪费的计算、不必要的大数据文件或意外

静态编辑器标志属性位于游戏对象的检查器中,在最右上方。它由一个复选框和一个下拉菜单组成,复选框将值设置为Everything或Nothing,下拉菜单允许您选择包含哪些值。你也可以使用GameObjectUtility在代码中设置Static Editor Flags属性。

Prefab

Unity的预制件系统允许你创建,配置和存储游戏对象完整的所有组件,属性值,和子游戏对象作为可重用的资产。Prefab Asset作为一个模板,你可以在场景中创建新的Prefab实例。

当你想以特定方式重用一个游戏对象(游戏邦注:如非玩家角色(NPC)、道具或场景中多个地方的场景,或项目中多个场景中的场景)时,你应该将其转换为Prefab。这比简单地复制和粘贴游戏对象要好,因为Prefab系统允许你自动保持所有副本的同步。

您可以将prefab嵌套在其他prefab中(Unity - Manual: Nested Prefabs),以创建易于在多个级别编辑的复杂对象层次结构。然而,这并不意味着所有预制实例都必须相同。如果您希望某个预制件的某些实例与其他实例不同,您可以覆盖单个预制件实例上的设置。您还可以创建Prefab的变体,允许您将一组覆盖组合成一个有意义的Prefab变体。

一些常见的预制使用的例子包括:

  • 环境资产——例如在一个关卡中多次使用的某种类型的树
  • 非玩家角色(npc)——例如某种类型的机器人可能会在你的游戏中出现多次,跨越多个关卡。它们可能在移动的速度或发出的声音上有所不同(使用重载)
  • 投射物-例如一个海盗的加农炮可能会在每次发射时实例化一个炮弹预制件。
  • 玩家的主要角色-玩家的预制件可能被放置在游戏的每个关卡(单独的场景)的起点。

创建预制件及其实例

要创建预制资产,将游戏对象从Hierarchy窗口拖到Project窗口。游戏对象及其所有组件和子游戏对象将成为项目窗口中的新资产。项目窗口中的Prefabs资产会显示为游戏对象的缩略图视图,或蓝色立方体Prefab图标,这取决于你如何设置项目窗口。

这个创建预制资产的过程也将原始游戏对象变成预制实例。它现在是新创建的预制资产的一个实例。预制实例以蓝色文本显示在层次结构中,预制的根游戏对象以蓝色立方体预制图标显示

通过将预制资产从项目视图拖到层次结构或场景视图,您可以在编辑器中创建预制资产的实例

您还可以在运行时使用脚本创建Prefabs实例。

你可以通过从Hierarchy窗口中拖拽一个新的GameObject并将其放到Project窗口中已有的Prefab资产的顶部来替换Prefab。如果你要替换现有的预制,Unity会尝试保存对预制本身和预制的个别部分(如子游戏对象和组件)的引用。为了做到这一点,它会在新的预制和你要替换的现有预制之间匹配游戏对象的名称(这种替换仅以名字为替换原则,所以需要注意)。

编辑Prefab的两种模式

Unity - Manual: Editing a Prefab in Prefab Mode

实例可以覆盖Prefab的默认属性 - override

Unity - Manual: Instance overrides

在检查器窗口中,实例覆盖的名称标签以粗体显示,并在左侧空白处有一条蓝色线。当你添加一个Prefab实例的新组件时,边距中的蓝线会跨越整个组件。

覆盖下拉窗口显示Prefab实例上的所有覆盖。它还允许您将覆盖从实例应用到Prefab资产,或将实例上的覆盖恢复到Prefab资产上的值。覆盖下拉按钮只出现在根预制件实例,而不出现在其他预制件内部的预制件。覆盖下拉窗口允许您单独应用或恢复预制件覆盖,或一次性应用或恢复所有预制件覆盖。

img

预制件变体 - Variant

当你想拥有一组预先定义好的预制变体时,预制变体是有用的。例如,你可能想要在你的游戏中拥有几种不同类型的GermSlimeTarget,它们都是基于相同的基本的GermSlimeTarget预制。然而,你可能想要一些GermSlimeTargets携带物品,一些以不同的速度移动,或一些发出额外的声音效果。

一个预制件变体继承另一个预制件的属性,称为Base。对预制件变体的重写将优先于基础预制件的值。预制件变体可以有任何其他预制件作为其基础,包括模型预制件或其他预制件变体。

Unity - Manual: Prefab Variants

override和variant的层级覆盖

覆盖多个级别 - Unity 手册

解压Prefab

解压缩预制件实例 - Unity 手册

就是将一个预制件实例变成普通的GameObject,与预制件脱离关系。

Layer

Unity中的层定义了哪些游戏对象可以与不同的功能进行交互。它们通常被相机用来渲染场景的一部分,被灯光用来照亮场景的一部分。但它们也可以通过光线投射来选择性地忽略碰撞器或制造碰撞。

利用摄像机的剔除遮罩,您可以选择性地渲染位于某一特定层中的对象。 为此,请选择需要部分渲染对象的摄像机。

通过使用层,您可以投射光线并忽略特定层中的碰撞体。 例如,您可能希望仅对玩家层投射光线并忽略所有其他碰撞体。

Physics.Raycast 函数获取位掩码,在位掩码中,每个位确定该层是否将被忽略。 如果 layerMask 中的所有位都启用,那么将可以对所有碰撞体进行碰撞。 如果 layerMask = 0,则投射光线不会发生任何碰撞。

Unity - Manual: Layers

Unity - Manual: Layer-based collision detection

Constraints 约束

Unity - Manual: Constraints

约束组件将游戏对象的位置、旋转或缩放与另一个游戏对象关联。受约束的游戏对象像关联到的游戏对象一样移动、旋转或缩放。

Unity 支持以下类型的约束组件:

  • Aim:旋转受约束的游戏对象以朝向关联的游戏对象。

  • Look At:将受约束的游戏对象旋转到关联的游戏对象(简化的 Aim Constraint)。

  • Parent:使受约束的游戏对象跟随关联的游戏对象移动和旋转。

  • Position:像关联的游戏对象一样移动受约束的游戏对象。

  • Rotation:像关联的游戏对象一样旋转受约束的游戏对象。

  • Scale:像关联的游戏对象一样缩放受约束的游戏对象。

关联到游戏对象

使用约束组件中的 Sources 列表可指定要关联到的游戏对象。

例如,要让十字准线跟随 2D 射击游戏中玩家的宇宙飞船,请在十字准线上添加一个 Position Constraint 组件。要将十字准线关联到宇宙飞船,请导航到 Position Constraint 组件,然后将宇宙飞船游戏对象添加到 Sources 列表中。当玩家移动宇宙飞船时,十字准线随之移动。

一个约束可以关联到多个源游戏对象。在这种情况下,约束使用其源游戏对象的平均位置、旋转或缩放。例如,要将光源指向一组游戏对象,请将 Aim Constraint 组件添加到光源游戏对象。然后,在 Sources 列表中添加要接受光照的游戏对象。Aim Constraint 将光源定向至其光源的平均位置。

Unity 按照源游戏对象在 Sources 列表中出现的顺序来对源游戏对象求值。该顺序对 Position ConstraintScale Constraint 组件没有影响。但是,顺序会对 Parent ConstraintRotation ConstraintAim Constraint 组件产生影响。要获得所需的结果,请通过拖放各项来重新排序 Sources 列表。

可以约束一系列游戏对象。例如,假如想让小鸭子排成一排跟随它们的妈妈。应将 Position Constraint 组件添加到游戏对象 Duckling1。在 Sources 列表中,关联到 MotherDuck。然后,将 Position Constraint 添加到 Duckling2_,而后者再关联到 Duckling1*。当* MotherDuck_ 游戏对象在场景中移动时,Duckling1 跟随 MotherDuck_,_Duckling2 跟随 Duckling1

设置约束属性

使用 Inspector 窗口可更改约束中的常用属性。

img

Position Constraint 的 Weight 和 Constraint Settings

使用 Weight 属性可以改变约束的影响。权重 1 会使约束更新游戏对象的速度与其源游戏对象的速度相同。权重为 0 会完全消除约束的影响。每个源游戏对象也有一个单独的权重。

Constraint Settings 中,使用 At Rest 属性可以指定当 Weight 为 0 或未选中 Freeze Axes 中相应属性时要使用的 X、Y 和 Z 值。

使用 Constraint Settings 中的 Offset 属性可以指定约束游戏对象时要使用的 X、Y 和 Z 值。

使用 Freeze Axes 设置可以切换约束可以实际修改的轴。

激活和锁定约束

可以在两个方面使用约束:激活和锁定。

通过激活约束可以对受约束的游戏对象的位置、旋转或缩放进行求值。Unity 不会对非活动约束进行求值。

通过锁定约束可以移动、旋转或缩放游戏对象。锁定的约束会控制游戏对象的变换组件的相关部分。无法使用锁定的约束手动移动、旋转或缩放游戏对象。也无法编辑 Constraint Settings

要手动编辑游戏对象的位置、旋转或缩放,请解锁其约束。如果约束处于活动状态的同时未锁定,则在您移动、旋转或缩放受约束的游戏对象或其源游戏对象时,约束会更新 Constraint Settings

向游戏对象添加约束组件时,约束在默认情况下处于非活动状态并且未锁定。因此,允许在激活和锁定约束之前微调受约束游戏对象和源游戏对象的位置、旋转和缩放。

为方便起见,ActivateZero 按钮可以更新 Constraint Settings

  • Activate__:保存相对于源游戏对象的当前偏移量,然后激活并锁定受约束的游戏对象。__

  • Zero:重置位置、旋转或缩放以匹配源游戏对象,然后激活并锁定受约束的游戏对象。

动画化和组合约束

使用动画剪辑可以修改受约束的游戏对象关联到的源游戏对象。当动画修改源游戏对象时,约束会修改受约束的游戏对象。

还可以在约束组件中动画化属性。例如,使用 Parent Constraint 将角色的剑从他们的手中移到他们的背后。首先,将一个 Parent Constraint 添加到剑游戏对象。在 Sources 列表中,将约束关联到角色的手和角色的脊椎。要动画化剑,请为每个源的权重添加关键帧。要动画化剑从背部移动到手中的动作,请添加关键帧来将手的权重从 0 更改为 1,并添加关键帧来将脊椎权重从 1 更改为 0。

可以向同一个游戏对象添加多种类型的约束组件。更新游戏对象时,Unity 会按照约束组件在 Inspector 窗口中的先后出现顺序来对这些组件求值。一个游戏对象只能包含同一类型的一个约束组件。例如,不能添加多个 Position Constraint。

Unity中的旋转和方向

https://docs.unity3d.com/cn/current/Manual/QuaternionAndEulerRotationsInUnity.html

光源

https://docs.unity3d.com/cn/current/Manual/Lights.html

相机

https://docs.unity3d.com/cn/current/Manual/Cameras.html

构建发布

https://docs.unity3d.com/2020.3/Documentation/Manual/PublishingBuilds.html

编辑器的功能

模式切换

https://docs.unity3d.com/cn/current/Manual/2DAnd3DModeSettings.html

预设值

https://docs.unity3d.com/cn/current/Manual/Preferences.html

比较需要注意的有缓存服务器和性能分析器

快捷键管理

https://docs.unity3d.com/cn/current/Manual/ShortcutsManager.html

构建设置

https://docs.unity3d.com/cn/current/Manual/BuildSettings.html

项目设置

https://docs.unity3d.com/cn/current/Manual/comp-ManagerGroup.html

下面的列表显示 Project Settings 窗口中可用的默认设置类别。

根据所安装的包,Project Settings 窗口还可能显示其他类别和设置。

Visual Studio集成

https://docs.unity3d.com/cn/current/Manual/VisualStudioIntegration.html

RenderDoc集成 - 可以捕获运行过程中的帧

https://docs.unity3d.com/cn/current/Manual/RenderDocIntegration.html

Xcode帧调试器

https://docs.unity3d.com/cn/current/Manual/XcodeFrameDebuggerIntegration.html

版本控制

https://docs.unity3d.com/cn/current/Manual/Versioncontrolintegration.html

https://docs.unity3d.com/cn/current/Manual/TextSceneFormat.html

安全模式

https://docs.unity3d.com/cn/current/Manual/SafeMode.html

性能分析器

https://docs.unity3d.com/cn/current/Manual/analysis.html