1、2D摄像机与分辨率自适应
首先,需要先确认开发分辨率。以移动平台为例,主流的分辨率为16:9,我们暂定开发分辨率为1136x640。
先设置Orthographic正交摄像机,这里面Size的含义是屏幕的一半,也就是640/2=320。由于Sprite默认的Pixels per Unit设置的是100,所以320/100=3.2。
如果Unity当前分辨率大于开发分辨率,它会自动缩放,如果当前分辨率小于开发分辨率,就需要我们手动处理,动态调节Game窗口Free Aspect来自适应分辨率,保证显示区域在屏幕区域中。
2、Sprite动画
Unity提供的动画系统非常强大,2D游戏和3D游戏中的动画控制原理是相同的,而且都可以在Unity中编辑动画,不过只能编辑一些简易的动画,如果对2D动画有更高的要求,可以尝试使用Unity官方插件Anima2D。
3、创建Tile地图
00、简介:
Unity提供了全套的Tile工具来编辑2D地图。使用Tile编辑地图,可以极大的减少内存占用。
美术人员只需要提供地图小格式元素,并且保证可以相互拼接接口,策划人员最终将这些小格子元素编辑拼在一起,灵活的拼接可以生成很多不同的2D地图。
01、创建Tile
- 创建Tile之前,需要和美术确认每个Tile的大小,一般是32或64。如下图,因为资源的大小是32,所以这里的Pixels per Unit(每单位的像素数)需要设置成32。
- 接着,在Hierarchy视图中创建2D Object–>Tilemap 游戏对象。Grid就是Tile的画布,它可以设置画布每个单元的大小。由于前面Pixels per Unit我们已经设置成了32,所以Cell Size默认为1就可以了。Cell Gap可以设置每个单元之间的间距,一般设置成0就好。Cell Swizzle用于设置Grid的布局朝向,而XYZ表示斜角为45°的2D游戏。
- Grid对象下面就是Tilemap了。它可以设置动画帧率、锚点、朝向等信息。对象上的TileMap Renderer组件和Sprite Renderer很像,可以设置排序和遮罩。
- 接着将可编辑的Sprite汇总在Tile Palette面板中。点击Windows–>2D–>Tile Palette。如下图所示,Creat new Palette可以创建多个调色板。可能游戏中每个场景风格不一样,多Palette面板就可以把相同风格的Tile汇总在一起,最后将需要编辑的Sprite资源直接拖入这个面板就可以自动生成Tile了。同一场景中可能有多个Tilemap,例如背景层和前景层,在Active TileMap下拉框中选择当前场景创建的所有Tilemap,方便相互切换编辑。调色板的元素也是可以编辑的,单击右上角的Edit按钮即可。如果想要删除一些不想要的Tile,可以点击上方的橡皮檫来删除它,最后按Command+s键保存即可。
02、编辑Tile
准备工作已经就绪,下面开始编辑Tile。善用Tile Palette工具栏,可更快捷的编辑Tile,Tile Palette工具栏中,工具从左到右依次如下:
点选工具 | 可以选择某一个Tile |
---|---|
移动工具 | 选定一个Tile,可使用移动工具移动其位置 |
画笔工具 | 选择一个Tile,即可在Scene视图中刷新它的区域 |
区域工具 | 按下鼠标左键可同时刷多个区域 |
吸图工具 | 吸取Scene中某个Tile的图,方便下次使用新吸取的图来编辑 |
橡皮工具 | Scene中删除不需要的Tile |
批量填充工具 | 大规模填充Tile |
03、多Tile编辑与排序
- 在普通的2D游戏场景中,至少是需要2个Tile层,我们称它为前景层和后景层。比如一棵树,上半部分是树叶(前景层),下半部分是树干(后景层),这样人物在这棵树附近上下移动的时候,走到树下面应该自己挡住树干,走到树上面应该是树叶挡住自己。
- 在Hierarchy视图中可以创建多个Tilemap,在Tile Palette面板中可以切换当前需要编辑的Tilemap,在Scene视图下面可以选择Focus On Tilemap,这样就可以凸出显示正在编辑的Tilemap了。
- 要排序的话,可以设置Order in Layer。将Tilemap背景层设置成0,人物SpriteRenderer设置成1,前景层设置为2,这样控制人物在屏幕中移动时,它就会渲染在这两个层之间了。
04、拓展Tile Palette
- Unity提供了Tile Parette的拓展编辑功能,可以重写画笔的任意行为。可以添加画笔类型,新的画笔要继承GridBrush,如果画笔需要复用,还支持可添加配置参数的画笔。
- 详见unity3D游戏开发(第2版)P180
05、2D碰撞检测
- 任何的碰撞现象都有两个载体,一个是发起碰撞的,另一个是接受碰撞的,所以我们首先要明确哪些物体是可以接受碰撞的,Collider 2D并不依赖Sprite组件,就好比一个空气墙,普通的Collider2D包括矩形、圆形、不规则边界、多边形和胶囊形,其中胶囊形一般用于主角,其他形状用于场景或动态阻挡等。
- Tilemap Collider 2D专门用于Tile的碰撞体,但是有时候它把中间不需要使用碰撞的也圈起来了,在它的基础上可以再添加一组Composite Collider 2D组件,这样就会自动将多余的碰撞区域去掉。
06、Rigidbody 2D
Rigidbody 2D表示2D刚体组件,它表示当前物体启动物理引擎,如果需要控制主角移动,并且会被上面介绍的Collider 2D组件阻挡住,就必须给它绑定上Rigidbady 2D组件。Body Type共有3个类型:
- Dynamic:表示动态刚体,完全模拟物理效果,碰到Collider 2D会被挡住,碰到任意Rigidbody 2D都会产生物理效果。它再空中会根据中立自动落下来,它的效率是最低的,仅适合主角使用。(功能最全,效率最低)
- Kinematic:运动学,它只能和选中Dynamic复选框的Rigidbody发生碰撞效果,如果需要碰撞事件,比如OnCollisionEnter2D(),或者Kinematic和Kinematic碰撞,两者必须有一个选中Use Full Kinematic Contacts复选框。Kinematic和Static碰撞,Kinematic必须被选中Use Full Kinematic Contacts复选框,否则碰撞事件也就没有了。Kinematic适合做主角被攻击时的碰撞检测。比如主角被别的物体击飞,发生击飞的物体可以设置Kinematic。因为主角已经是Dynamic了,可以正常触发碰撞效果,如果使用Kinematic的话,效率比Dynamic要好。(简单的说,这种类型没有碰撞的效果,只能触发碰撞事件)
- Static:静态,只能和Dynamic发生碰撞效果,和Kinematic只能发生碰撞事件,(需要保证Kinematic必须勾选Use Full Kinematic Contacts复选框,它的效率是最高的)
还需要注意的是,如果需要移动或旋转带Rigidbody2D的组件时,不能直接修改它的Transform.position,而是要使用rigidbody2D.position或者Rigidbody2D.rotation。
using UnityEngine;
public class Player : MonoBehaviour
{
public GameObject hero;
private SpriteRenderer heroRenderer;
private Rigidbody2D herorigidbody2D;
// Start is called before the first frame update
void Start()
{
heroRenderer = hero.GetComponent<SpriteRenderer>();
herorigidbody2D = hero.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
//处理方向键
if (Input.GetKey(KeyCode.W))
{
PlayerMove(Vector2.up);
}
else if (Input.GetKey(KeyCode.S))
{
PlayerMove(Vector2.down);
}
else if (Input.GetKey(KeyCode.A))
{
PlayerMove(Vector2.left, true);
}
else if (Input.GetKey(KeyCode.D))
{
PlayerMove(Vector2.right, false);
}
}
void PlayerMove(Vector2 position,bool flipx=false)
{
//由于移动人物图片需要翻转,所以可以设置heroRenderer.flipX来镜像图片
heroRenderer.flipX = flipx;
//绑定Rigidbody以后,不能再使用transform.position赋值
herorigidbody2D.position += (position * 0.1f);
}
/// <summary>
/// 更直观的看到哪里发生了碰撞
/// </summary>
private void OnCollisionStay2D(Collision2D collision)
{
foreach (ContactPoint2D item in collision.contacts)
{
//绘制线
Debug.DrawLine(item.point, transform.position, Color.red);
//InverseTransformPoint()方法可以计算出碰撞的方向
var direction = transform.InverseTransformPoint(item.point);
if (direction.x > 0)
{
print("右碰撞");
}
else if (direction.x < 0)
{
print("左碰撞");
}
else if (direction.y > 0)
{
print("上碰撞");
}
else if (direction.y < 0)
{
print("下碰撞");
}
}
}
}
07、Effectors 2D
Unity提供了一组物理效果,它可以给Collider 2D对象添加一种特殊的物理效果组件。
PlatformEffector2D | 一种特殊地面,如有些2D游戏有一个台子,从下面能跳上去,但是站在上面却掉不下去 |
---|---|
SurfaceEffector2D | 像传输带一样带摩擦的缓慢移动 |
PointEffector2D | 类似炸弹一样,爆炸后可以把周围的东西向四周炸开 |
Buoyancy Effector2D | 模拟水中浮力效果 |
AreaEffector2D | 区域力,例如物体从空中掉下来,进入某个区域相互弹跳的效果 |
08、取消显示警告
#pragma warning disable 0618