欢迎光临散文网 会员登陆 & 注册

Unity学习笔记10二维游戏开发

2021-11-30 08:14 作者:挽秋_z  | 我要投稿

精灵Sprite

概念

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按照特定方式排列起来,模拟顶视角,斜视角。

等距透视视图

1,等距透视是一种平行透视

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会自动的将建好的骨骼绑定到角色

上。创建新的动画,点击录制按钮,建两个关键帧,在关键帧处运动骨骼后保存,运行游戏即可看到关键帧的效

果。











Unity学习笔记10二维游戏开发的评论 (共 条)

分享到微博请遵守国家法律