https://learn.unity.com/tutorial/world-interactions-collectibles?uv=2019.2&projectId=5c6166dbedbc2a0021b1bc7c#5ce41cf0edbc2a4c003f9bc0
这是官网教程,资源可以在Assort Store上下载。
这个教程真的很有用帮到了很多。
这里简单记录一下可以学到的一些有用的东西,写的有些乱,主要是自己能看懂就好了。
1.比较浮点数是否相等
由于浮点数存储的问题比较两个浮点数是否相等需要使用一些方法
Mathf.Approximately(A, B)
这个方法比较浮点数A和B是否相等,相等返回true,否则返回false。
2.获取向量的长度
使用向量自带的属性magnitude,如
Vector2 move = new Vector2(4, 6);
move.magnitude //获取向量的模
3.使用TileMap
https://learn.unity.com/tutorial/world-design-tilemaps?uv=2019.2&projectId=5c6166dbedbc2a0021b1bc7c#5cdd60deedbc2a12d5ac2be0 这是官方的教程
在2D Game Object里面有TileMap这个物体。
然后在Asset里任意一个文件右键点击Create找到Tile创建,为了方便可以建立一个Tiles文件夹,在里面创建。注意在Hierachy窗口里创建不了,它不是游戏物体。以下是创建的Tile,给其一张Sprite作为其的内容。
TileMap将我们的场景分为一块一块的,Tile就是每一块填充的内容。
从windows -》2D 里面打开Tile Palette 窗口,这就像是调色板,用来绘图的Tile元素放在这里,然后从这里选择要使用哪个图像来绘制TileMap的什么地方。
如图在TilePalette选择不同的Tile,使用其工具栏不同的功能,如画笔、橡皮擦等,然后选择TileMap,在Scene场景中绘制。注意如果图片没有填充满,那么应该找到Tile的Sprite,更改其Pixels Per Unit,让其适合每个单元格子。
当然如果你要的Tile太多一个一个导入未免太过麻烦,可以将切割好的图集一次拖入TilePalette面板,将其一次全部创建。
当然注意地图的渲染顺序,将其Order in Layer调小确保其始终是背景。如下:
4.场景内物体的显示顺序
如果我们在场景内放置一个物体,比如一个箱子,那么它与角色靠近时的显示就非常关键了,我们不希望就是两张图片互相遮盖的这种效果,如:
而更希望其类似真实世界的效果,这其实就是更改渲染顺序。
我们要打开Edit -》Project Setting 窗口,选择Graphics。更改其Transparency Sort Mode模式为Custom Axis。然后更改Transparency Sort Axis里面的x、y、z为0、1、0。也就是渲染顺序基于图片的y轴。当两个图片有重叠的时候y轴数值大的渲染在上面。
但是这样设置还不够,我们还需要设置角色的Sprite Renderer组件的Sprite Sort Point,将其更改为Pivot,也就是比较Pivot的y轴数值来更改渲染数据。
这个点的位置可以在Sprite里面设置
也可以在Sprite Editor里设置在任何你想要的位置。将角色和场景中物体的Pivot位置都设置在底部正中间或者其它你认为合理的位置。
5.禁止物体的旋转
Rigidbody 2D 里面Constraints 下面的Freeze Rotation Z打上勾,禁止绕着Z轴的旋转即可。
6.碰撞检测时的抖动
之所以会出现这种情况是因为在Update函数里面移动物体,你将物体移动到一个新的位置,物理系统的拷贝随着物体一起移动,然后物理系统发现进入另一个物体的Collider,物理系统退回之前的状态并使物体同步,然后将物体同步出去。你持续不断的向另一个物体移动,物理系统持续不断的退回。于是就出现抖动。想要改变这种情况,就将物体移动代码放入FixedUpdate函数里面,使用rigidbody 2D自己的函数移动,而不是直接更改物体的position,如下:
public class RubyController : MonoBehaviour
{
Rigidbody2D rigidbody2d;
float horizontal;
float vertical;
// Start is called before the first frame update
void Start()
{
rigidbody2d = GetComponent();
}
// Update is called once per frame
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
}
void FixedUpdate()
{
Vector2 position = rigidbody2d.position;
position.x = position.x + 3.0f * horizontal * Time.deltaTime;
position.y = position.y + 3.0f * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
}
实时上那些与物理系统相关的代码要尽量放在FixUpdate里面执行。
注意有个小细节Collider不是包裹整个物体的,比如人物是包裹人物下半身就可以了,这样看上去更加真实一点。
7.给TileMap添加Collider
单击我们的TileMap物体,添加一个组件 TileMap Collider 2D,就会在Scene看到有绿色的格子出现在我们创建的TileMap但是我们并不想要全部覆盖的,只需要覆盖比如水域等地方,这个如何设置呢?
在我们创建的Tile 上有一个Collider Type的属性,单击后就可以改变这个属性,图中是None表示不会添加碰撞检测,更改为Sprite就会添加碰撞检测,将你想要添加碰撞检测的Tile设置为Sprite就好了。
这样其实已经可以较好的工作了,但是有两个问题,一是分成一个一个的Collider会对性能造成影响,二是一块一块的Collider之间也是有微小的间隙的可能造成一些不必要的Bug。那么如何修改呢?
需要在TileMap上添加另一个组件Composite Collider 2D,同时勾选TileMap Collider 2D上的Used By Composite属性就好。这样之后就可以把连在一起的Collider给整合起来。当然最好可以将Rigidbody上的Body Type 选择为Static这样降低计算量,毕竟我们的背景不移动。
8.设置角色血量
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
Mathf.Clamp这个函数非常适合在设置血量的时候使用,因为血量的变化不会超过设定的范围。
9.设置地图上掉血的区域
一般我们使用OnTriggerEnter2D函数,然后给这个物体设置一个Collider 勾选作为Trigger就好了,但是有时候设置好也不起作用,此时可以设置Rigidbody 2D组件上的Sleeping Mode设置为Never Sleep。
另外想这样的2D物体我们将其放大或者缩小图片也会跟着拉伸,那么如何设置让图片重复出现呢?
这个我们要修改对应的Sprite将其Mesh Type改为Full Rect
这样修改后我们在场景上选择对应的物体,同时选择左上角的Rect Tool对物体进行拉伸的时候就会看到相应的效果,注意不要选择成旁边的Scale Tool。
10.动画播放
步骤:
首先在要播放动画的物体上添加Animator组件,这个组件有一个Controller属性是放入一个Animator Controller由其根据我们输入的条件来决定播放什么动画。创建一个Controller拖入这个属性,然后在里面填入要播放的Animation。
如何创建我们的Animation,可以打开Window - 》 Animation -》Animation窗口在里面单击Create创建一个Animation Clip将要播放的Sprite拖入然后调整其采样频率即可。
如图我们有一个机器人向左走的逐帧动画。我们创建向右走的逐帧动画也很简单一样的步骤,只需要添加一个Property。
我们添加了一个Flip.x的property并勾选上这样播放的时候每一帧的动画都会与之前按x轴翻转一下,这样向左走就变成了向右走。
在这个物体的Animator窗口,如果一个物体有太多动画那么可以创建一个Blend Tree来方便管理,比如这里有Robot向上下左右走的四个动画。
这是Robot 的Blend Tree的设置,选择Blend Type为2D Simple Direction也就是一个二维的方向,由2个参数来控制如何播放动画。后面把四个动画添加上。这样当Move X和Move Y的值改变的时候那个红点就会移动向相应的动画,从而播放不同的动画。
注意Move X 和Move Y 是我们先在Animator里面的Parameters里面设置好,然后选择的。
这样我们可以在脚本里面获取Animator组件,使用SetFloat函数来设置这两个的数值,从而播放不同的动画。
11.Layer的设置
在Project setting里面Physics 2D和Physics里面都有,底部的三角里面勾选上的两个会互相碰撞。这样我们设置碰撞检测的话就更加容易,不需要判断碰撞到的物体的Layer。
12.Rigidbody
Rigidbody这个组件有一个simulated可以给其赋值为false这样物理系统就不再运作。就好像把物体的active设置为false一样方便。
13.摄像机跟随主角
之前是使用脚本控制摄像机获取主角位置。这里学到一个新方法,使用Package。
加载Cinemachine 。安装好后顶部会出现这个选项。
点击打开菜单,选择Create 2D Camera,点击后会在Hierarchy 窗口中出现一个默认名称为CM Vcam1的物体。我们可以从其上的Lens来调整摄像机距离和其他设置。
然后将其上的Follow设置为Ruby。这样镜头就可以跟随角色移动。我们可以给镜头添加边界让其不要显示边界以外的区域。
在底部点击Add Extension,选择Cinemachine Confiner。注意这个组件根据指定的边界让镜头的边缘停止在边界上,所以要再创建一个空物体,添加一个Polygon Collider 2D组件来自己画出边界。然后将这个物体添加到这个组件上的Bounding Shape 2D里面。
注意我们添了一个包围整个TileMap的Collider作为摄像机的边界,但是这样会将物体排斥在外边,因为物体的Collider不能进入另一个Collider这个的解决办法是取消这个边界的Collider与所有其他物体的碰撞检测就可以了。
14.血条的制作
使用遮罩,然后修改遮罩的Rect Transform 组件的rect.width值来更改血量的显示。
基本设置,遮罩下的血条要设置为和遮罩一样大且其Anchors设置在遮罩的左上角。然后遮罩添加Mask组件不显示遮罩层的图片。然后将遮罩层的Pivot设置在左侧中间,这样做是为了设置缩放的时候不至于从左右两侧减少。
然后根据血量在脚本里面设置相应的值即可。
15.对话框的制作
使用canvas的world space模式,让其显示在世界空间中,注意更改canvas 的缩放。不要直接更改其长宽。
16.音乐的播放
2D的音乐会作为背景音乐,要想出现真实世界的效果就需要使用3D的音乐效果。此时注意Audio listener的位置。另外,如果一个物体被摧毁其上的音乐会戛然而止,最好让其他的物体播放其摧毁时的音乐,把自己的Audio Clip传递过去就行。