代码源自游戏《A Place for the Unwilling》
开发《A Place for the Unwilling》游戏第一部要解决的问题就是让精灵可以围绕其它精灵前后移动,呈现出真实的深度感觉。SpriteRenderer组件有两个属性,可以改变场景中Sprite的渲染顺序。
Sorting Layer 用于设置不同层的Sprite渲染顺序
Order in Layer 用于设置在同一层中的Sprite渲染顺序
7
private
float
m_floorHeight;
8
private
float
m_spriteLowerBound;
9
private
float
m_spriteHalfWidth;
10
private
readonly
float
m_tan30 = Mathf.Tan(Mathf.PI /
5
);
12
void
Start()
13
{
14
SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>
();
15
m_spriteLowerBound = spriteRenderer.bounds.size.y *
0.5f
;
16
m_spriteHalfWidth = spriteRenderer.bounds.size.x *
0.5f
;
17
}
19
//
Use this condition for objects that don’t move in the scene.
20
#if
UNITY_EDITOR
21
void
LateUpdate()
22
{
23
//
Use this condition for objects that don’t move in the scene.
24
if
(!
Application.isPlaying)
25
{
26
//
Update the position in the Z axis:
27
transform.position =
new
Vector3
28
(
29
transform.position.x,
30
transform.position.y,
31
(transform.position.y - m_spriteLowerBound + m_floorHeight) *
m_tan30
32
);
33
}
34
}
35
#endif
37
void
OnDrawGizmos()
38
{
39
Vector3 floorHeightPos =
new
Vector3
40
(
41
transform.position.x,
42
transform.position.y - m_spriteLowerBound +
m_floorHeight,
43
transform.position.z
44
);
46
Gizmos.color =
Color.magenta;
47
Gizmos.DrawLine(floorHeightPos + Vector3.left * m_spriteHalfWidth, floorHeightPos + Vector3.right *
m_spriteHalfWidth);
48
}
首先需要设置的是“Floor Height”,该属性决定Sprite的下边界在Y方向的偏移。 在3D世界坐标中,它用于设置Sprite在场景中的Z深度。 如果一个Sprite的底部比其它Sprite更高,它将被渲染在其它Sprite后面。
然后存储Sprite高度与宽度的半值,以便对Z坐标进行一些简单的数学运算。在《A Place for the Unwilling》游戏中使用了30度的等距切角,但您也可以将Z坐标设为与Y坐标一致,不影响游戏效果。
这里使用OnDrawGizmos方法在当前的地面高度绘制一条线,以便可以在编辑器中设置为最终的精确位置。另外,对于有些游戏运行后永远不会移动的对象,可以使用“if(!Application.isPlaying)”和“#if UNITY_EDITOR”条件在运行时保存计算结果,因为可能会有上百个Sprite同时绑定该脚本。
以上设置完成后,就可以在场景中移动Sprite并保证渲染顺序正常了,但还有两种情况需要更多的设置。
在处理中心不在中间位置的Sprite时,需要将其分为几部分。以下面的建筑为例,由于它的底部是矩形,如果整个建筑仅设置一个Floor Height值,那角色将只能沿着它前方的那面行走,并且会遮挡角色!为了解决这个问题,就需要将建筑Sprite分为两个部分,并为每一边设置不同的地面,如下图:
IsoVector类:该类包含一些常用的方向向量(N,W,E,S,NE,NW,SE,SW),以及从自定义方向获取向量(反之亦然)的方法,或者获取给定方向的反向向量(例如输入南获取北)等。
本文介绍的内容不一定是最佳的解决方案,但也展现出了很好的学习思路,从最开始想到编写脚本调整Sprite的Z值来正确渲染一切对象,解决了一开始构建游戏场景的问题。随着继续扩展代码库,也丰富了一些自定义类来加入新功能,同时维护好项目结构。希望这篇文章对正在使用Unity开发这种等距游戏的开发者有帮助!
原文连接:
https://madewith.unity.com/en/stories/what-i-learned-from-trying-to-make-an-isometric-game-in-unity
原文作者:Martín Pane