Unity学习笔记10二维游戏开发
概念
1,结合到场景中的二维图片或者动画
2,游戏角色,鼠标指针,屏幕字符或者其他移动物体
3,最初表示硬件方式的图片混合技术
精灵的存储方式

上图是一个打包的精灵资源,包含很多子图片,游戏引擎可以对这些子图片进行切块,并且显示,来达到模拟二维
动画的目的,这个就是精灵的存储方式。
布告板Billboard
1,是在三维环境中使用的精灵
2,所在平面总是垂直于摄像机的视线,保证永远看到的都是正面
3,缩放图片的大小来模拟透视,可以旋转,和其他物体重叠或者被遮挡
4,可以代替几何加贴图的建模方式来极大提升引擎的效率
布告板应用范围
1,粒子系统(比如火,烟雾等),粒子系统中的每个粒子都是由布告板来构成的
2,三维物体(一般是一些小物体,小植物,草丛等)
3,角色的某些HUD(比如游戏中出现的"1-Up"/升级等效果,在头顶上出现的)
4,早期三维游戏的可拾取物体
简单实践
创建二维工程
可以显示在二维场景中的物体,每一个都是Sprite。
将精灵图片拖拽到场景中,系统会自动添加Sprite Renderer组件,这个组件可以自动的渲染精灵图。
多张图片混合成的大图片可以调整一下Sprite为Multiple,点击Sprite Editor可以对其进行编辑。
编辑界面的左上角的Slice可以切割图片,有三种类型,自动,按尺寸,按数量进行切割。切割后Apply
在二维场景中有层级的概念,在Sprite的属性里的Additional Settings中有两个参数,Sorting Layer指的是所在层
级,Order in Layer 指的是Sprite在这个层级当中的顺序,数值大的在前面。
精灵的Pixels Per Unit 指的是每一个Unity单位包含多少个像素,修改该数值可以调整图片的大小。
Filter Mode(滤波模式):像素游戏不进行滤波,使用Point。
新建一个动画,作为角色静止时的动画,可以将切割后图片直接拖拽进去,会自动生成动画。
建立两个脚本Bullet(子弹脚本)和Spawner(子弹控制脚本)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//子弹行为脚本
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Collider2D))]
//要求挂接这个脚本的物体包含这两个属性
public class NewBehaviourScript : MonoBehaviour
{
public float speed = 2f;//移动速度
private Rigidbody2D body;
// Start is called before the first frame update
void Start()
{
body = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
body.MovePosition(transform.position + speed * transform.right * Time.deltaTime);//right是向前的方向
//物体的移动,使用MovePosition向着某一个移动
}
private void OnCollisionEnter2D(Collision2D collision)//当与其他碰撞体发生碰撞的时候会调用该函数
{
if(collision.gameObject.tag=="enemy")//如果打到的物体带有敌人tag
{
GameObject.Destroy(collision.gameObject);//销毁敌人
GameObject.Destroy(gameObject);//销毁子弹
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//控制发射子弹的脚本
public class Spawner : MonoBehaviour
{
//此脚本是让玩家自动发射子弹
public float timeInterval = 3f;//每隔3秒发射子弹
float timer = 0f;//计时器,冻结时间
public GameObject bullet;//子弹预制件
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(timer>timeInterval)
{
Instantiate(bullet,transform);
timer = 0;//重置计时器的冻结时间
}
timer += Time.deltaTime;//每次叠加计时器的时间
}
}
在玩家角色上新建一个空物体,用来发射子弹,将Spawner脚本挂接上去,制作子弹预制件,将Bullet脚本挂接上
去。与上面的玩家动画类似,制作敌人待机动画。为敌人添加Box Collider 2D碰撞体,并且修改tag。
精灵类型的材质默认情况是一个Sprite类型的材质,不受光照的影响。
但也可以令其受光照的影响,新建一个材质,修改Shader类型为Sprite/Diffuse(漫反射光照),拖拽到某个物体
上,该物体会变暗,因为该物体需要受光照的影响,没有光照时,就会比较暗。可以建立光源照亮。
一般需要光照信息是在制作美术资源时就提前画好的。
瓦片地图Tilemap
作用:用于构造2D关卡,将瓦片tile按照特定方式排列起来,模拟顶视角,斜视角。
等距透视视图
2,摄像机处于游戏场景的斜上方并向下转动一定角度来观察游戏场景
3,游戏中的瓦片都斜向排列
关系

精灵是原料,
简单实践
创建瓦片地图:GameObject----2D-----Tilemap
在windows窗口中,有一个2D----Tile Palette(调色板)。调出来后,在左上角可以创建新的调色板,并且需要
选择保存的位置,在窗口的上面Active Tilemap可以选择对哪张地图进行编辑。
将选中的精灵资源拖拽进去,需要为这些调色板里的资源选择保存的位置。
选中调色板里的精灵,可以直接用笔刷的方式在地图里进行编辑,当图片的大小与地图的格子不符时,可以选中
Grid修改Cell size 的值。然后进行绘制即可。
可以创建多个Tilemap来进行绘制,关闭其中一个不影响其他的。可以实现多子地图类型的地图系统。
Tilemap也需要碰撞检测,可以为选中的tilemap添加Tilemap Collider 2D组件,添加该组件后,系统自动为该地
图里的每一个格子加上一个碰撞体,但效率太低,可以添加Composite Collider 2D组件(系统会自动同时添加
Rigidbody 2D组件,需要将其Body Type修改为Static类型,地图一般为静态),然后将Tilemap Collider 2D中的
Used By Composite勾选上,这时Tilemap的碰撞体就变成一个整体了。
进行测试:可以为敌人添加一个刚体组件,使其受重力影响,然后运行游戏,可以发现敌人落在了地图上。
二维角色
实现
1,和三维角色类似,都可以使用骨架,动画等;
2,使用精灵图片来实现
3,精灵保存所有可能的动作序列帧
4,绑定物理体
简单实践
使用自带的Robot资源,然后新建四个动画,,,
动画状态机中的Any State表示:特殊的状态单元,表示任意动画状态(就比如跳跃,在站立,走路,跑步状态下都可以进行)

Parameters:参数 Greater:大于 less:少于
新建两个参数,一是float类型的speed,用来控制角色的移动速度(以速度的值来控制角色在站立,跑步,走路状
态的转换),一个是bool类型的ground,用来表示角色是否在地面上,如果不是在地面上,就开始播放jump动
画。
然后将Any state转换到jump动画的线上添加ground条件

jump动画到idle动画添加

idle状态到walk状态

walk到run状态,speed大于0.1,,,其他状态的转换同理可知。运行游戏,修改speed和ground来测试状态机
force:力
新建一个角色控制脚本,拖拽给场景中的Robot
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Robot : MonoBehaviour
{
public float m_Maxspeed = 10f;//最大速度
public float m_jumpForce = 400f;
public LayerMask m_WhatIsGround;//地面的Layer类型
public Transform m_GroundCheck;//在角色的脚底挂接一个空物体来检查地面
const float k_GroundedRadius = 0.5f;//检查地面时做一个冗余,半径是0.5
public bool m_Grounded;//表示是否在地面上
private Animator m_Anim;//用来得到当前角色的Animator组件
private Rigidbody2D m_Rigidbody2D;
public bool m_FacingRight = true;//用来表示角色是否朝向右边
public bool m_Jump;//是否处于跳跃状态
// Start is called before the first frame update
private void Awake()
{
m_GroundCheck = transform.Find("GroundCheck");//找到名为GroundCheck的物体
m_Anim = GetComponent<Animator>();
m_Rigidbody2D = GetComponent<Rigidbody2D>();//得到角色身上的对应组件
}
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void FixedUpdate()
{
m_Grounded = false;//默认情况不在地面上
//OverlapCircleAll检查一下以一个点做一个圆,在这个圆内是否有其他物体(碰撞体)的存在,如果有,将其他物体的colliders返回
//有三个参数,第一个是中心点的位置,第二个是半径,第三个是Layer,可以将特定的Layer纳入检查范围,不一定检查所有的物体
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position,k_GroundedRadius,m_WhatIsGround);
for(int i=0;i<colliders.Length;++i)
{
if(colliders[i].gameObject!=gameObject)//如果不是当前物体的话,就表示碰撞到地面了
{
m_Grounded = true;
}
}
m_Anim.SetBool("ground", m_Grounded);//使用SetBool来修改ground的值为第二个参数
//下面代码控制角色的运动行为
float h = Input.GetAxis("Horizontal");//看玩家是否按下了左右键 Horizontal:水平的
if(!m_Jump)
{
m_Jump = Input.GetKeyDown(KeyCode.Space);//如果不是处于跳跃状态,检测玩家是否按下了空格键
}
Move(h, m_Jump);
m_Jump = false;
}
public void Move(float move,bool jump)//控制角色移动
{
if(m_Grounded)//如果在地面上
{
m_Anim.SetFloat("speed",Mathf.Abs(move));//Mathf.Abs()绝对值
m_Rigidbody2D.velocity = new Vector2(move*m_Maxspeed,m_Rigidbody2D.velocity.y);//velocity表示的是速度
if(move>0&&!m_FacingRight)//如果角色向右移动,但是角色没有朝向右边,则需要反转一下方向
{
Flip();
}
else if(move < 0 && m_FacingRight)//与上面相反的
{
Flip();
}
}
//如果不在地面上,处理关于跳跃的操作
if (m_Grounded && jump && m_Anim.GetBool("ground"))
{
//角色在地面上,并且玩家按下了跳跃键,并且动画机里的ground也是在地面
//GetBool得到“”里的参数
m_Grounded = false;
m_Anim.SetBool("ground",false);
m_Rigidbody2D.AddForce(new Vector2(0, m_jumpForce));//给角色一个向上的力
}
}
void Flip()
{
m_FacingRight = !m_FacingRight;//朝向求反
//反转操作
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
将参数What Is ground 修改为Everything(所有物体都检测)
然后给Robot添加一个空物体GroundCheck,并且需要将这个空物体放到地面的位置。(用来完成地面检测)。
然后拖拽到脚本中。
给Robot添加Rigidbody 2D和Capsule Collider 2D,然后点击Capsule Collider 2D中的edit collider,修改一下
Robot的碰撞检测范围,使其贴合游戏角色。
勾选Robot的Freeze Roation ,锁定Z方向的旋转自由度,使其不受摩擦力的影响

在将所有动画状态转换之间的Has Exit Time勾掉,这样动作的转换不会有延迟,转换立即发生,而不是等上一个
动画播放完成之后在转换。
重新绘制一下Tilemap

并为其添加Platform Effector 2D组件(平台效果),需要将里面的Use One Way(单向平台),需要和
Composite Collider 2D组件配合使用,需要将Used By Effector勾选上。运行游戏,测试是否可以跳跃到平台
上。
二维角色骨架系统
二维动画有两种形式,关键帧动画和骨骼动画,关键帧是通过保存一系列图片来生成动画(问题是保存的数据量很大,且角色很难和场景中的其他物体发生有效的交互。)

与三维骨骼动画类似
简单实践
骨骼动画是主流的动画控制方法。
需先在包管理器中安装2D Animation组件。
选中一个Sprite,点击Sprite Editor进行编辑

进入后选择骨骼编辑

点击Create bone 创建骨骼,在图片上进行绘制骨骼,在preview pose状态下,点击Visibility可以看到已经创建的骨骼层次。

Auto Geometry-->Generate for Selected自动生成网格,网格依附于骨骼而运动,并且网格相对于骨骼具有权,在Weight中,

Auto Weigth可以自动生成权重。
完成后放到场景中,为其添加Sprite Skin 组件,点击Create Bones,unity会自动的将建好的骨骼绑定到角色
上。创建新的动画,点击录制按钮,建两个关键帧,在关键帧处运动骨骼后保存,运行游戏即可看到关键帧的效
果。