这是用户在 2025-8-3 13:32 为 https://learn.unity.com/tutorial/shi-jue-feng-ge-li-zi?uv=2020.3&projectId=5facf921edbc2a2003a58d3a#... 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?
Unity Learn 主页
查看教程内容

视觉风格 - 粒子

教程
初级
1 小时
(439)
摘要
粒子在交互式应用程序中广泛用于创建各种效果。粒子系统可以创建数十个甚至数百个粒子,这些粒子是很小的图像,具备方向、速度、生命周期、颜色和许多其他属性。通过使用所有这些参数,粒子可以共同创建诸如烟雾、火花甚至火之类的效果。
选择 Unity 版本
最后更新:2021 四月 12
2020.3
2020.2
2020.1
2019.4
2019.3
2019.2
2019.1
2018.4
2018.3
语言
中文

1.准备精灵

Unity 提供了一种全面的粒子系统。在本教程中,你将使用粒子系统为我们的游戏创建一些粒子,例如损坏的机器人的烟雾效果。
选择要展开的图像
输入图像描述 (可选)

你将使用精灵作为图像以放置在粒子上。这些图像的精灵图集可以在 Art > Sprites > VFX 中找到,名为 ParticlesSheet
1. 将 Type 设置为 Multiple,并将 PPU 保留为 100
2.打开 Sprite Editor 以对不同精灵进行切片。
3.精灵图集拆分为 4 列和 4 行。有关精灵图集切片的提醒,请参阅“精灵动画”教程
准备好所有精灵后,我们来创建一个效果。让我们先从烟雾效果开始。

2.烟雾效果

要创建新的粒子效果,请执行以下操作:
1.使用 Hierarchy 窗口右上角的 Create 按钮(选择 Effects > Particle System)。
2.此时将为你创建一个默认的粒子系统。现在应该看起来像是向上喷射的白点。将这个粒子系统重命名为 SmokeEffect
3.Inspector 中,可以看到粒子系统 (Particle System) 由多个部分组成,这些部分均可折叠,用于定义该系统及其创建的粒子的所有属性。
选择要展开的图像
输入图像描述 (可选)

4.首先,将白点更改为烟雾精灵。在 Texture Sheet Animation 部分中,单击旁边的圆圈以启用该部分。单击该部分的名称以打开该部分:
选择要展开的图像
输入图像描述 (可选)


3.挑选随机精灵

通常可以使用此部分中的设置来对粒子图像进行动画处理。但在这里,你可以通过这种方式为每个粒子挑选随机精灵
1.Mode 设置为 Sprites
2.单击显示的精灵条目旁边的 + 按钮,这样便可以得到 2 个精灵。
3.精灵图集效果中的烟雾精灵分配给这些属性。
4.单击 Start Frame 属性右侧的小下拉箭头,选择 Random Between Two Constants,然后输入 02。系统将选择一个介于 02(不包括 2)之间的随机数,即 01,并对粒子使用相应的精灵
5.最后,单击 Frame over time 旁边的黑框,这个框显示曲线帧中相应的帧随时间的变化情况(从帧 01)。你根本不想要任何动画,所以请右键单击最右边的点,然后按 Delete 键
选择要展开的图像
输入图像描述 (可选)

现在,你可以在 Scene 视图中看到粒子正在随机使用一个或另一个烟雾精灵(如果已经创建这些精灵)。
下一步是更改创建这些烟雾精灵的方式,因为现在它们在方向上过于分散。
6.Inspector 中打开 Shape 部分Scene 视图将显示发射粒子的锥体。将 Radius 设置为 0,因为你希望所有粒子都从一个点发出(该值将更改为 0.0001,但别担心,仅仅是因为这个值不能为 0,所以 Unity 会将其设置为最接近零的值)。
7.将角度更改为大约 5 度,这样可以减少粒子的分散程度并以更加准直的线条生成:
选择要展开的图像
输入图像描述 (可选)

现在,你的粒子将以正确的方向开始,但移动速度还是太快。而且由于所有粒子都形状相同,所以看上去不够真实。自然界的事物是混乱的,因此要让事物看起来不那么虚假,诀窍就是增加随机性。

4.为粒子增加随机性

Particle System 顶部的主要部分中,查找以下三个设置
1.Start Lifetime:粒子的生命周期是指粒子在屏幕上被粒子系统销毁之前存在的时间。如果在 Scene 视图缩小,你会看到所有粒子都差不多在同一位置消失。这是因为粒子的初始速度和生命周期都相同,因此最终在相同的距离处被销毁。
单击 Start Lifetime 右侧的小向下箭头,然后选择 Random Between Two Constants。输入 1.53。粒子的消失速度会更快,因为现在它们的生命周期更短了。而且粒子也会以更加自然的方式消失,因为粒子现在的生命周期各不相同。
2.Start Size:这是粒子创建后的大小。现在只设置了一个数字,因此所有粒子的大小都相同。和上面一样,选择 Random Between Two Constants 并分别设置为 0.30.5,这样来引入一些随机性。粒子现在变小了且大小不同,但移动速度仍然过快。
3.Start Speed:通过将这个属性设置为 Random Between Two Constants,可以降低粒子的初始移动速度并增加一些随机性。将两个常量分别设置为 0.51
粒子开始看起来像烟雾得多了。但是看起来仍然很奇怪,因为当粒子在生命周期即将结束时,就会突然消失。
选择要展开的图像
输入图像描述 (可选)


5.使粒子逐渐消失

为了让这种变化没那么剧烈,我们要让粒子随着生命周期接近最大值的过程中逐渐增大透明度,直至变得完全透明。
这样,粒子就不会突然消失,而是会逐渐消失
1.单击名为 Color over Lifetime 部分的名称旁边的小白色圆圈以启用该部分,然后打开该部分。
2. 为了更轻松查看所有部分,别忘了可以通过单击已打开的部分的标题来关闭相应部分。单击 Color 旁边的白色方框以打开 Gradient Editor
选择要展开的图像
输入图像描述 (可选)

这一渐变显示了粒子颜色在生命周期内的变化方式。底部箭头是颜色,顶部箭头是透明度(在游戏美术用语中称为“Alpha”)。
在创建粒子时,可在左侧看到颜色和 Alpha;在粒子寿命结束时,可在右侧看到颜色和 Alpha
左右两侧之间,可以看到粒子将遵循的颜色和 Alpha 演变过程。
3.目前,粒子将保持完全白色,并且其 Alpha 值将保持不变。所以让我们更改一下:选择右上角的箭头,然后将 Alpha255 更改为 0
选择要展开的图像
输入图像描述 (可选)

你快要完成了!现在的烟雾看起来好多了,但还缺少一个小细节:烟雾应该随着时间而逐渐消失,因此,粒子的大小在其生命周期内也应改变,即逐渐变小。
就像 Color 一样,还有一个名为 Size Over Lifetime 的部分,因此请启用并打开这一部分。
4.单击 Size 框,然后查看显示在 Inspector 底部的曲线:
选择要展开的图像
输入图像描述 (可选)

目前,粒子系统的功能与你想要的效果刚好相反,因为粒子从大小 0 开始并在其生命周期内增大,直到生命周期结束时达到最大大小(这是一个乘数,因此不会破坏我们先前设置的大小的随机性)。
5.我们可以通过将第一个点上调1 并将最后一个点下调0 来进行反转。
注意:可以使用每个点旁边的切线来控制曲线,并进行各种尝试,直到在 Scene 视图中获得所需的结果。要让烟雾更加美观,你需要使曲线保持平坦直到曲线大约一半的位置,然后骤然下降
选择要展开的图像
输入图像描述 (可选)

现在你的烟雾看起来非常漂亮了,接下来便可以将烟雾添加到你的机器人

6.代码中的粒子系统

我们来看看代码中的粒子系统
1.首先从烟雾效果制作一个预制件。完成该操作后,可以删除场景中的烟雾效果。
2.打开机器人预制件,然后拖动烟雾预制件以将烟雾设置为机器人子对象,然后放在合适位置,使烟雾看起来像是从机器人头部冒出来的:
选择要展开的图像
输入图像描述 (可选)

3.保存预制件,然后尝试运行游戏。现在,机器人的损坏程度看上去严重得多了。但出现了两个问题:
  • 烟雾会随角色一起移动。我们不想让烟雾呈现这样的效果,即粒子不应该跟随机器人移动
  • 如果让 Ruby机器人投掷一个齿轮来修复机器人,机器人会继续冒烟。你需要在机器人修好后禁用烟雾粒子效果。

7.解决烟雾移动问题

解决烟雾移动问题的方法非常简单:
1.如果查看 Particle System 的主要部分,你会看到 Simulation Space 设置已设置为 Local。请改为 World
选择要展开的图像
输入图像描述 (可选)

此外,要在机器人修好后使烟雾停止,请执行以下操作:
2.打开 EnemyController 脚本,并添加一个名为 smokeEffect 且类型为 ParticleSystem公共成员。
3.现在,在你的机器人预制件Inspector 中将出现一个新字段。将烟雾效果拖入该字段中。
你可能好奇,既然你分配的是游戏对象,为什么类型为 ParticleSystem 而不是 Gameobject
这是因为,如果公共成员是 ComponentScript 类型(而不是 GameObject),则当你在 Inspector 中为这个成员分配游戏对象时,Unity 将存储游戏对象上的组件类型。
这样可以避免必须像以前一样在脚本中执行 GetComponent。此外还会阻止你将没有该组件类型的游戏对象分配给该设置。这也避免了用户不小心制造 bug。
选择要展开的图像
输入图像描述 (可选)

4. 最后,在 EnemyController 脚本Fix 函数中,添加:
smokeEffect.Stop();
现在,在修复了机器人后,烟雾便会停止。
顺便提醒一下,为什么要使用 Stop,而不是像先前飞弹那样简单地销毁粒子系统
如果感到好奇,找到原因的最佳方法是不断尝试:
  • 注释掉 smokeEffect.Stop() 并在下一行添加 Destroy(smokeEffect.gameObject)
  • 运行场景,并修复机器人
你可以看到烟雾会立即消失。这是因为当粒子系统被销毁时,也会销毁当前正在处理的所有粒子,即使是刚刚创建的粒子。
Stop 只会阻止粒子系统创建粒子,已经存在的粒子可以正常结束自己的生命周期。这比所有粒子突然消失要看起来自然得多。

8.创意时刻

你现在已经知道了粒子系统的工作方式,接下来便可以尝试为游戏创建更多的粒子。本教程开始时的精灵图集有一个示例粒子效果,可用来表示击中后的效果以及拾取生命值可收集对象
不必担心做得完全一样,只要发挥创造力并尝试不同的设置,就可以通过反复尝试和试错来了解它们的工作方式。
下面的一些信息可以帮助你实现所需的目标:

循环系统

你制作的烟雾效果是循环的效果,所以始终会生成新的粒子。但是,你可以创建只在特定时间内有效的粒子系统,完成任务后便自行销毁。为此,请进入 Inspector 中的 Particle System 主要部分:
  • 取消勾选 Looping
  • Duration 设置为你希望效果持续的时间。
  • 将该部分底部的 Stop Action 设置为 Destroy。只有在所有粒子的生命周期都结束后,粒子系统才会被销毁,所以不会像手动销毁循环系统时那样出现“所有粒子立即消失”的问题。

爆发发射

你的烟雾效果在之前是以稳定的速率发射粒子。你可以在 Emission 部分中设置该速率。
Rate over Time 控制每秒发射多少粒子。Rate over Distance 可以用于让系统在移动时发出粒子,例如,如果你希望只有在汽车移动时才发出烟雾粒子,那么这个功能很有用。
但对于某些效果,你可能想要一次发射很多粒子,仅此而已。比如,爆炸时会产生大量烟雾粒子,但爆炸结束后便不再产生烟雾粒子。
这就是 Bursts 子部分的用途。单击 + 按钮可添加一个爆发,然后设置在粒子的生命周期内何时应该发生爆发,应生成多少粒子,以及其他一些设置。
例如,对于命中效果粒子,你可以:
  • 禁用 Looping 并将 Stop Action 设置为 Destroy
  • Rate over Time 设置为 0,这样就不会随时间生成任何粒子。
  • 20 个粒子的爆发时间设置为 0.0
然后,一旦创建了系统,便会生成许多粒子,然后在粒子都结束生命周期时自行销毁。

实例化粒子系统

飞弹一样,从粒子系统制作预制件后,便可以使用 Instantiate 函数创建粒子系统。
因此,对于仅发生一次的效果(例如被击中或拾取生命值可收集对象),你可以将对预制件的引用存储在公共变量中,并在应该产生效果时调用 Instantiate。如果 Particle System 未设置为 Looping 并且 Stop Action 设置为 Destroy,则会播放效果,然后销毁。

9.检查你的脚本

你的 EnemyController 脚本现在应如下所示:
public class EnemyController : MonoBehaviour { public float speed; public bool vertical; public float changeTime = 3.0f; public ParticleSystem smokeEffect; Rigidbody2D rigidbody2D; float timer; int direction = 1; bool broken = true; Animator animator; // 在第一次帧更新之前调用 Start void Start() { rigidbody2D = GetComponent<Rigidbody2D>(); timer = changeTime; animator = GetComponent<Animator>(); } void Update() { //注意,! 符号可以反转测试,因此,如果 broken 为 true,则 !broken 将为 false,并且不会执行 return。 if(!broken) { return; } timer -= Time.deltaTime; if (timer < 0) { direction = -direction; timer = changeTime; } } void FixedUpdate() { //注意,! 符号可以反转测试,因此,如果 broken 为 true,则 !broken 将为 false,并且不会执行 return。 if(!broken) { return; } Vector2 position = rigidbody2D.position; if (vertical) { position.y = position.y + Time.deltaTime * speed * direction; animator.SetFloat("Move X", 0); animator.SetFloat("Move Y", direction); } else { position.x = position.x + Time.deltaTime * speed * direction; animator.SetFloat("Move X", direction); animator.SetFloat("Move Y", 0); } rigidbody2D.MovePosition(position); } void OnCollisionEnter2D(Collision2D other) { RubyController player = other.gameObject.GetComponent<RubyController >(); if (player != null) { player.ChangeHealth(-1); } } //使用 public 的原因是我们希望像飞弹脚本一样在其他地方调用这个函数 public void Fix() { broken = false; rigidbody2D.simulated = false; //如果你添加了修复动画,则为可选 animator.SetTrigger("Fixed"); smokeEffect.Stop(); } }

10.总结

在本教程中,我们了解了粒子系统如何创建效果来改善游戏的外观。
粒子系统功能非常强大,可以实现很多创意,请参阅粒子系统的文档以获取关于所有设置以及如何使用这些设置的说明。
在下一教程中,你将添加对任何游戏来说都是最重要的部分之一:用户界面 (UI),从而显示 Ruby 的剩余血量

项目:
Ruby's Adventure:2D 初学者
视觉风格 - 粒子
视觉风格 - 粒子
一般教程讨论
0
0
1. 准备精灵
0
1
2. 烟雾效果
0
0
3. 挑选随机精灵
0
0
4. 为粒子增加随机性
0
1
5. 使粒子逐渐消失
0
1
6. 代码中的粒子系统
2
2
7. 解决烟雾移动问题
2
4
8. 创意时刻
2
1
9. 检查你的脚本
0
0
10. 总结
0
0