当前位置:   article > 正文

Unit官方初学者教程_Ruby的冒险_2D教程(一)_sprite sort point

sprite sort point

官方教程地址如下(仅有英文版):https://learn.unity.com/project/ruby-s-2d-rpg?language=en

近期学习了untiy提供的Ruby的冒险,决定总结一下中文教程(主要为简化流程,希望完全没有接触过unity的朋友还是看官方教程,比较详细)和记录学习心得

虽然目的为简化,但仍然会保证关键的内容,以及画一下自己认为的重点,总体不会跟原版教程差太多,可以一起看,我会加一点点教程没有提到或者容易误解的地方

整个教程制作建议时间14-24小时,请准备至少为期2天的时间来学习本教程~

建议: unity版本 2018.3 以上

由Bigbao实现完整项目代码以及资源(我使用的unity版本为2019.2.0b):https://github.com/Bigbao123/Ruby

这份教程你将学习到:

  • 如何使用和自定义编辑器

  • 如何在整个开发过程中管理项目资源和场景

  • 如何创建角色和控制器

  • 使用tilemaps的世界布局和设计

  • 如何使静态精灵适应动画精灵

 

新建一个项目:

 

从我提供的项目链接(上面)导入资源或从unitystore导入资源:

从unityStore导入Asset: 点击unity窗口最上方 Window > General > Asset Store.

搜索 2D Beginner:Tutorial Resources

在2D Beginner:Tutorial Resources页面上,单击Download 等待下载完成

点击粉红色的按钮Import

点击导入资源->创建新场景->保存

从我提供的项目导入:点击unity窗口最上方Assets->Import Package->Custome Package

选择你从github上下载的.unity文件  导入

 

创建一个新场景

建立Ruby精灵

创建RubyController .cs脚本 并绑定到Ruby上,

首先尝试让你的ruby动起来

  1. public class RubyController : MonoBehaviour
  2. {
  3. // Start is called before the first frame update
  4. void Start()
  5. {
  6. }
  7. // Update is called once per frame
  8. void Update()
  9. {
  10. Vector2 position = transform.position;//声明position变量,在其中存储了Ruby的当前位置
  11. position.x = position.x + 0.1f;
  12. transform.position = position;
  13. }
  14. }

Ctrl+s保存脚本并切换到unity中查看你的更改, 发现ruby动了起来,但这看起来有点傻夫夫的

(教程里基础写的有点多(虽然基础讲的很细但是对于已经对unity有一些了解的同学不免有一丢丢啰嗦,但是建议有时间可以细看看教程,查漏补缺基础知识),所以我在这边简化一下,如果是任何基础都没有的朋友,建议还是看教程)

现在我们来让ruby上下左右移动

  1. public class RubyController : MonoBehaviour
  2. {
  3. // Start is called before the first frame update
  4. void Start()
  5. {
  6. }
  7. // Update is called once per frame
  8. void Update()
  9. {
  10. float horizontal = Input.GetAxis("Horizontal");
  11. float vertical = Input.GetAxis("Vertical");
  12. Vector2 position = transform.position;
  13. position.x = position.x + 3.0f * horizontal * Time.deltaTime;//deltaTime 包含在Time中,是一个变量,Unity填充帧渲染所需的时间
  14. position.y = position.y + 3.0f * vertical * Time.deltaTime;
  15. transform.position = position;
  16. }
  17. }

这里要注意一下:需要表示Ruby移动的数量不是以每帧为单位,而是以每秒单位。所以需要通过将其与Unity渲染帧所花费的时间(Time.deltaTime)相乘来更改移动速度。如果游戏以每秒10帧的速度运行,则每帧需要0.1秒。如果它以每秒60帧的速度运行,则每帧将花费0.017秒。如果将移动乘以该值,则移动将以秒为单位表示。

设计Tilemaps

Tilemaps是个啥东西呢? 我们来看看这个图:

 

Tilemap网格,(unity中的解释)可以在每个网格单元格中设置不同的Sprite。通过使用可以在视觉上连接在一起的Sprite,您可以创建一个更容易在编辑器内直接更改的更大图像

听起来好像也还是没有很懂,那我们先做做了解看

让我们从创建Tilemap开始:

1. 在“层次结构”窗口中,右键单击空白区域。

2. 从上下文菜单中选择2D Object> Tilemap

这将在您的Hierarchy窗口中创建两个GameObject:

  • 网格:正如其名称所暗示的,这是一个场景中的网格,可用于将GameObjects均匀地放置在其单元格中。

Tilemap:Tilemap由Tiles组成 - 为了本教程的目的,将它们视为特殊的Sprites。Tilemap是网格的子GameObject。 

  •  

 

创建Tile

在“项目”窗口中,选择“ FirstTile”

在Inspector中,可以看到Tile Asset的属性。这些包括Sprite的插槽,Tile将绘制:

将精灵分配给FirstTile

找到Tile.png文件,就像使用Ruby.png一样,将此Tile保存在Sprites文件夹中

在Inspector中,单击Sprite 属性右侧的圆圈选择按钮。这将打开一个对话框窗口,其中显示项目的所有Sprite。

 

转到Window > 2D > Tile palette. 打开Tile Palette窗口

为新Palette命名,如GamePalette,然后单击Create

将新Palette保存在Tile文件夹中。

 将Tile(FirstTile )从Project窗口拖到新Palette的中心

Tile现在显示在调色板的网格中。单击平铺以选择它。

从“平铺调色板”顶部的工具栏中,选择“ 画笔工具”

在Hierarchy窗口中,选择Grid GameObject。在Inspector中,找到“单元格大小”属性。你会看到x y 都设置为1

这意味着每个单元格的宽度为1个单位,高度为1个单位。

2. 在“项目”窗口中,选择FirstTile Sprite。Inspector将显示其导入设置。将看到“ 每单位像素数” 属性设置为100

在Inspector的底部,查看Sprite的大小。你会发现它的宽度和高度只有64像素

每单位像素值更改为64. 这告诉Unity在场景中的1个单位内拟合该Sprite的64个像素。由于你的Sprite是64像素,它将完美地填充1个单位。

更改每单位像素数(PPU)后,单击“检查器”底部的“ apply” 。你所有的精灵现在会完全填满网格!

接下来:

按住Ctrl键配合鼠标在Palette面板里可以选更多的区域!!!

你现在知道了:

  • 什么是瓷砖

  • 它与Sprites和Tilemaps的关系

  • 如何使用Tile Palette绘制Tilemap

 

为了更容易创建Tiles和技术优化,用于Tiles的Sprite通常作为单个图像文件称为Tileset
例如,下面的图像在3x3网格上包含九个Tiles,然后Unity可以在导入设置中拆分为9个不同的Sprite:

在“Project”窗口中,搜索名称以“Floor”开头的所有文件都是Tilesets。

在Inspector中,使用下拉菜单将Sprite Mode 从Single 更改为Multiple

ppu值更改为64 (因为这些Tiles宽64像素,就像前面的示例一样)。

单击“ apply” 按钮以应用更改。

调整Tileset的Sprite设置:

将图像分割成九个精灵:

1. 在“检查器”中,单击“ Sprite Editor” 按钮。这将打开一个窗口,您可以在其中调整图像的哪个部分作为Sprite导入。

2. 在窗口顶部的菜单栏中,单击“ Slice。将出现一个窗口,您可以在其中指定切片图像的方式。

3. 使用下拉菜单将“ Type 字段设置为“ Grid by Cell Count

4. 将Column&Row值(C R )设置为3

单击“ Slice。网格将出现在您的图像上; 该网格的每个单元格都是一个单独的Sprite。

在窗口菜单栏的右上角,单击“ apply”

窗口并单击小箭头以查看从该图像创建的精灵,将会有九个!

要将精灵分配给Tiles:

1. 将整个图像从“Project ”窗口拖放到“Palette ”窗口中。

2. 当您松开鼠标按钮时,将出现一个对话框,要求您选择保存Tiles的文件夹。选择Tile 文件夹。

Tiles现在已经创建,是Palette的一部分!您将能够选择它们并对它们进行绘制

对于所有Tileset Assets,重复前三个步骤中的过程,文件名以“Floor”开头(均为3x3 Sprites的Tilesets)。

 

键盘和鼠标快捷键

还有一些有用的快捷方式可以帮助绘制Tilemap:

  • Alt +左​​键拖动 - 平移

  • 轮按钮拖动 - 平移

  • 旋转滚轮按钮 - 放大或缩小

好了!接下来是创作时间 你可以画你自己设计的游戏啦!

 

完成绘制Tilemap后:

1. 将更改保存到场景中。 2. 单击“ 播放” 进入“播放”模式,欣赏您的角色在您绘制的世界中移动。

因为Tilemap和角色具有相同的深度(它们的位置的z坐标),为了避免Tilemap擦除Ruby,您可以更改z位置。但对于纯粹的2D游戏,最好避免触及深度。为了使Ruby出现,你需要告诉Unity它需要绘制的东西。Unity需要首先绘制Tilemap,以便Ruby出现在背景之上。

要更改Unity绘制Tilemap和角色的顺序:

1. 在Hierarchy中,选择Tilemap GameObject 2. 在Inspector中,找到Tilemap Renderer 组件。

3. 设置Order in Layer-10

4.Sorting Layer: default 

在Assets > Art > Sprites > Environment里选择你想要的各种装饰精灵

 

创作完毕后:

让我们看看Ruby的Sprite渲染器:

1. 在Hierarchy中,选择Ruby GameObject。

2. 在Inspector中,找到其Sprite Renderer 组件。

3. 找到Sprite Sort Point 字段。这当前设置为Center ,这意味着它使用Sprite的中心点来决定它是应该在另一个GameObject的前面还是后面。

4. 将Sprite Sort Point更改为Pivot

一个pivot是一种特殊的点,你可以手动定义,它充当“锚”的雪碧。如果旋转Sprite,它将围绕该点旋转。它也是用于放置Sprite的点。这意味着如果GameObject位于(0,0)并且Pivot设置为角色的头部,则头部将被绘制在(0,0)处。如果枢轴在脚上,则P脚将被绘制在(0,0)处。 您需要更改Ruby和MetalCube Sprites的Pivots,以便将它们放置在您想要的位置。 要更改单个Sprite Pivot:

1。 在Project窗口中,转到Assets> Art> Sprites> Environment 。选择MetalCube Sprite。

2. 在Inspector中,找到Pivot领域。使用下拉菜单将其设置为Bottom

单击检查器底部的“apply按钮。

 

使用Sprite编辑器更改轴

更改Pivot的另一种方法是使用Sprite Editor: 1。 在Project窗口中,转到Assets> Art> Sprites 。选择Ruby Sprite。

2. 在“检查器”中,单击“ Sprite编辑器” 按钮。这将打开您在上一个教程中使用的Sprite Editor。 3. 单击图像,显示Sprite边框。在中心,你应该看到一个小蓝圈。这是Pivot的当前位置。

精灵编辑器允许您在Sprite中将该蓝色圆圈拖放到任何位置。

或者,在灰色的Sprite窗口中,您可以:

  • 坐落在Pivot 下降到中心。

  • Pivot 设置为Custom 并手动设置Custom Pivot

4. 自定义轴旋转设为0.5英寸x和0英寸。由于Pivot Unit Mode 设置为Normalized,因此0最小(因此左侧为x,底部为y),1为最大值(右侧为x,顶部为y),0.5为中间值。

5. 单击“ apply” 以保存更改。

 

创建一个预制件

1. 在“项目”窗口中,转到顶级文件夹(资产)。 2. 创建一个新文件夹并将其命名为“ Prefabs ”。 3. 将MetalBox GameObject从层次结构拖动到新的Prefab 文件夹。

 

如果要模拟运动和碰撞,则需要使用所有数学方程来计算对象上的接触和力。但是这写了很多复杂的代码。因为物理定律是相同的,所以可以抽象出这些代码并在所有游戏中分享:这就是物理系统的作用。Unity有一个内置的物理系统,可以为您计算物体移动和碰撞。

为了避免对游戏中的每个对象进行昂贵的数学运算,Unity仅为附加了Rigidbody 2D 组件的GameObjects 进行那些计算。

 

让我们首先在Ruby中添加一个Rigidbody 2D 组件:

1. 在Hierarchy中,选择Ruby GameObject。 2. 将Ruby GameObject从Hierarchy拖动到Project窗口中的Prefab文件夹中。 3. 双击Ruby Prefab以打开预制模式。 4. 在“检查器”中,单击“ 添加组件” 按钮。 5. 搜索“ Rigidbody 2D ”并选择组件。 注意:确保选择2D组件 - 还有一个名为Rigidbody的组件用于3D游戏。

使用“ 保存” 按钮保存预制件,然后返回场景

如果这时候点击运行  你会发现你的Ruby掉下来了,因为Rigidbody将重力应用于GameObject(默认情况下在y轴上设置),所以GameObject下降了

1. 在Hierarchy中,选择Ruby GameObject。

2. 在Inspector中,找到Rigidbody 2D组件。 3. 找到“ 重力比例” 属性并将其设置为0

点击Ruby提交改变Apply All到预制体上

 

 

什么是Collider

现在你的GameObject已经被物理系统所知(因为Rigidbody),你需要告诉物理系统GameObject的哪个部分是“可靠的”。这是通过碰撞者(Colliders)完成的。

碰撞器是简单的形状,如方形或圆形,物理系统将其作为GameObject的近似形状,进行碰撞计算。

 

让我们从Ruby GameObject开始:

1. 在Prefab模式下打开Ruby Prefab。

2. 在“检查器”中,单击“ Add Component.

3. 搜索“ Box Collider 2D ”,并添加此组件。 注意:再次,请记住使用此组件的2D版本!

4. 现在,您将在“场景”视图中看到Ruby周围的绿色轮廓:

这就是对撞机的形状 - 它现在是物理系统的Ruby形状。

 

保存预制件。

6. 现在对MetalBox Prefab做同样的事情:

  • 双击预制件将其打开。

  • 添加Box Collider 2D组件。

  • 保存预制件。

  • 退出预制模式。

注意:您尚未在框中添加Rigidbody组件 - 这是正确的。这是因为它不需要通过物理移动,它只需要一个Collider,所以有一个Rigidbody的GameObjects将与它进行交互。

 

现在按Play,尝试将Ruby移动到盒子周围。

角色抖动并旋转!有点鬼畜......

旋转问题:你需要告诉物理系统不要旋转GameObject。它可能是“真正的”物理学会做的,但在这个2D游戏中它不起作用。  Rigidbody 2D组件有一个设置:

1。检查Ruby是否在Prefab模式下打开。

2. 在Inspector中,找到Rigidbody 2D组件。

3. 单击“ Constraints旁边的小箭头以展开该部分。

4. 启用Freeze Rotation 复选框,以确保Rigidbody不向Ruby添加任何旋转

提示:如果您在场景中而不是在Prefab上对Ruby实例进行了更改,请使用下拉Override菜单将更改应用于预制件。

现在准备修复Ruby的抖动问题:

为什么Ruby抖动?(思考....  字太多我直接机翻过来了...)

抖动的发生是因为物理系统使用仅包含碰撞器的场景的简化副本。 这个物理场景使物理系统的计算更简单,但物理系统需要:

  1. 只要带有刚体的GameObject在场景中移动,就可以在物理场景中移动GameObject的副本。

  2. 施加力并计算碰撞。

  3. 将场景中的GameObject移动到物理场景中计算的新位置。

在这种情况下,这会导致以下事件:

  1. 您在帧更新期间移动角色。

  2. 物理系统将其副本移动到新位置。

  3. 物理系统发现角色Collider现在位于另一个Collider(这里是盒子)里面并将其移回,因此它不再在盒子里面。

  4. 物理系统将Ruby GameObject与新位置同步。

你不断地将Ruby移到盒子里,而物理系统正在将她移回去。你告诉你的代码要做什么和物理系统做什么之间的斗争导致抖动。

要修复Ruby的抖动,你需要移动Rigidbody本身而不是GameObject Transform,并让物理系统将GameObject位置同步到Rigidbody位置。这样,物理系统可以在进入盒子之前停止移动,而不必已经进入盒子移动Ruby 。

为此,您需要修改Ruby Controller代码:

  1. public class RubyController : MonoBehaviour
  2. {
  3. Rigidbody2D rigidbody2d;
  4. // Start is called before the first frame update
  5. void Start()
  6. {
  7. rigidbody2d = GetComponent<Rigidbody2D>();
  8. }
  9. // Update is called once per frame
  10. void Update()
  11. {
  12. float horizontal = Input.GetAxis("Horizontal");
  13. float vertical = Input.GetAxis("Vertical");
  14. Vector2 position = rigidbody2d.position;
  15. position.x = position.x + 3.0f* horizontal * Time.deltaTime;
  16. position.y = position.y + 3.0f * vertical * Time.deltaTime;
  17. rigidbody2d.MovePosition(position);
  18. }
  19. }

 

让我们看看每行代码:

  • Rigidbody2D刚体2d; 这将创建一个名为rigidbody2d的新变量来存储刚体并从脚本内的任何位置访问它。

  • rigidbody2d = GetComponent <Rigidbody2D>(); 这是在start函数内部,所以它只在游戏开始时执行一次。它要求Unity给我们一个Rigidbody2D,它附加到我们的脚本附加到的同一个GameObject,这是我们的角色。

  • 在Update函数中,您替换了Vector2 position = transform.position; 使用Vector2 position = rigidbody2d.position ; 这意味着您不再使用Transform位置,而是使用Rigidbody。

  • 以同样的方式,而不是用transform.position = position 设置新位置; 你现在正在使用rigidbody2d.MovePosition(position); 这会将Rigidbody移动到你想要的位置,但是如果它在那个运动中与另一个Collider发生碰撞,它将在中途停止。

现在,当您单击“ 播放”时,您将看到您的角色已停止抖动!

但Ruby仍然太早停止,而且看起来并不好看。那是因为碰撞器的大小不适合图像。

调整碰撞器的大小

如果你查看场景视图,你会看到盒子的碰撞器和Ruby(它们周围的绿色矩形)远远超出你认为GameObject的“实体”部分。 例如,盒子的阴影位于Collider内部,因此它被物理系统认为是固体

要调整对撞机的大小:

1。 双击MetalBox预制件(或单击层次结构中MetalBox右侧的箭头)以进入预制模式

2. 在Inspector中,找到Box Collider组件。

3. 单击“ 编辑碰撞” 按钮

单击“ 编辑碰撞”时,“碰撞”将在“场景”视图中更改,以在侧面显示四个小方块。您可以单击并拖动它们以调整Collider的大小。如果您错过了单击并且小点消失,只需返回检查器并重新单击“ 编辑碰撞器” 按钮。 调整Collider的大小,使其看起来像这样

你为什么不把它做成盒子的大小?嗯,那是因为你的角色需要能够“躲在”盒子后面才能让它看起来更好(否则盒子在地面看起来会很平坦)。

5. 保存更改。

6. 为Ruby GameObject完成相同的过程,调整其Collider的大小,使其看起来像这样:

Collider只能覆盖Ruby的腿,因为角色需要能够在碰撞前稍微移动到GameObject之上 - 这有助于使游戏更加可信。

7. 保存更改。

8. 单击“ 播放” ,然后尝试在框中移动Ruby。现在它应该看起来很好并且表现得像你期望的那样。(完成后请记得再次按“播放”,退出“播放模式”。)

添加Tilemap碰撞

现在你的角色与我们所有有碰撞器的游戏对象发生碰撞。但她仍然可以在水上行走 - 你需要让她与水瓦片碰撞,所以她不能走在他们身上。但你怎么能这样做?

您可以将一个Collider添加到空GameObject并调整其大小以覆盖水。但这很容易出错,如果您想要将水重新绘制为更大,更小或不同的形状,则必须手动更换对撞机。请记住,Tilemaps可以让您轻松快速地改变世界。

值得庆幸的是,Tilemaps还可以拥有碰撞器。每个Tile都可以存储它是否应该碰撞,Tilemap Collider将为所有设置为碰撞的Tiles创建一个Collider。

要设置Tilemap Collider: 1。在Hierarchy中,选择Tilemap GameObject。

2. 在“检查器  Inspector”中,单击“ 添加组件  Add Component 按钮。

3. 搜索“ Tilemap Collider 2D ”并选择此组件。您将看到这会在场景视图中为所有切片添加绿色对撞方格:

这是因为现在所有的Tiles都设置为碰撞。

4. 在“项目”窗口中,转到“Tile”文件夹。选择所有非水的瓷砖。您可以单击一个,然后按住Shift 并单击要包括的最后一个平铺以全部选中它们

5. 在Inspector中,找到Collider Type 属性并将其从Sprite (现在)更改为None。

现在,您选择的Tiles不再被视为碰撞者。如果在层次结构中选择Tilemap,您将在“场景”视图中看到只有水砖具有绿色方块。

6. 保存更改。 7. 单击“ 播放” 进入“播放模式”并尝试让Ruby在水上行走 - 她现在应该与边界碰撞。

优化Tilemap Collider

设置Tilemap Collider还有最后一小步。目前,每个磁贴都是一个单独的碰撞器,您可以在“场景”视图中看到。 这很好,但它会产生两个问题:

  • 它在物理系统的计算上更重; 如果你有一个大世界,它可以开始放慢你的游戏速度。

  • 它可以在瓷砖之间的边界上产生小问题。由于它们是两个并排的碰撞器,并且它们之间存在微小的间隙,因此计算中的微小不精确可能导致罕见的碰撞仍然发生。

为解决这些问题,Unity提供了一个名为Composite Collider 2D 的组件。这会将所有碰撞器放在物体上(或物体的子物体上)并从中制造一个大碰撞器。 让我们添加和配置这个组件:

1。 在Hierarchy中,选择Tilemap GameObject。 2. 在“检查器”中,单击“ 添加组件” 按钮。 3. 搜索“ Composite Collider 2D ”并选择此组件。

您将看到这会自动添加Rigidbody 2D,因为复合Collider需要Rigidbody 2D才能正常工作。

4. 在Tilemap Collider 2D组件中,启用Used By Composite 复选框。 5. 在Rigidbody 2D组件中,将Rigidbody Body Type 属性设置为Static 。 将此设置为静态将阻止您的世界移动。它还有助于物理系统优化计算,因为它现在知道Rigidbody无法移动。

现在,水砖周围的碰撞器是一个大的矩形

如果您绘制新的水砖,Unity会自动更新Tilemap的Composite Collider以包含这些新的Colliders。

在本教程中,您有:

  • 探讨了Unity中物理系统的基础知识

  • 添加了一个Rigidbody组件,使物理系统处理对象

  • 添加了碰撞器以使对象碰撞在一起

在下一个教程中,您将扩展您对物理系统的使用,以检测与游戏对象(例如,可收集的健康包)的角色碰撞。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/134856
推荐阅读
相关标签
  

闽ICP备14008679号