Frist Game:Sunnyland

1、安装软件与导入素材

下载

https://unity.cn/releases

默认显示方式

window -> layout -> default

SampleScene :

Project -> 文件目录

Scene ->游戏画面

asset store -> 素材商店

在asset store下载素材 sunnyland

shift + sapace 放大窗口

2、编辑素材与Til

1.背景导入

每个格子16像素: Pixels Per Unit 16px

2.绘制瓷砖式地图

新建瓦片图层:左上角/右键 > 2D object>Tilemap

调出画板: window > 2D > Tile palette




unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#


建立瓦片文件夹管理素材

编辑素材:素材16像素/格, 编辑 Sprite Editor

切割素材:Slice >automatic自动 (效果不好,无法分出每格)

>Grid By Cell Size自定义

第一行x:16 y: 16

Apply 确认

将素材拖拽进画板Tile palette开始绘制

遇见问题:编辑完地图保存项目后,打开发现素材丢失 (为了找解决方案找了半个小时qaq)

原因:不在一个场景

解决方案:assets > scenes > scene.unity

3、图层(layer)与角

Main camera中的Size可调整视野大小

图层排序:sorting layer

图层名称排序越在下面,越在前面

order in layer 数字越大越在前

右键->2D object -> sprite(精灵)

sprite:表示在 2D 游戏中使用的精灵对象。

精灵

将角色素材拖拽到 sprite中

Add Component:

Rigibody 2D 2D刚体

Box Collider 2D碰撞体(记得Edit Collider去调整人物的绿色框不要太大)

Tilemap Collider 2D 地图碰撞格子

遇到的几个问题

1.狐狸大小-> 设置图片的 unit -> 16

2.无法移动 -> 要点到箭头才能拖动

4、角色移动

在Player中Add Component->New Scripts(脚本),命名为PlayerControler

可以创建专门的Scripts文件夹来放Scripts

打开代码文件创建一个刚体


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_02


保存后将Rigidbody 2D拖拽进Rb中绑定player(角色)来实现更改角色


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_03


Input.GetAxis 函数:用于确定移动方向

Input.GetAxis("Horizontal")表示在X轴上移动,

Input.GetAxis("Vertical")代表在z轴上移动,

可以从Edit——Project Setting——input中查看相关的设置

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerControler : MonoBehaviour
{
    //声明刚体变量
    public Rigidbody2D rb;
    //声明速度
    public float speed;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    //Update函数在游戏运行中时刻调用
    void Update()
    {
        Movement();
    }

    //角色移动
    void Movement()
    {
        float horizontalmove;
        //Horizontal是u3d的水平虚拟轴,即左右,
        //GetAxis为得到-1到1的数值
        horizontalmove = Input.GetAxis("Horizontal");

        if(horizontalmove != 0)
        {
            //velocity:此属性用于设置或返回刚体的速度值,vector2表示用于2D
            rb.velocity = new Vector2(horizontalmove * speed, rb.velocity.y);
        }
    }
}

注意事项:

1.在游戏过程中更改的变量不会在结束时保存,

若需保存游戏内的更改,可以先在游戏时Copy Component,


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_04


在结束后粘贴即可(如下)


unity sprite2D导入序列帧自动创建clip unity2d导入素材_ci_05


2.2D角色需要在刚体中固定Z轴,否则会晕头转向(笑)


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_06


5、角色方向与跳跃

角色方向:


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_07


Scale是缩放比例:用Transform.localScame调用

//GetAxisRwa可得到-1,0,1三个数值
float facedicretion = Input.GetAxisRaw("Horizontal");       //左右转向

//判断左右转向
   if(facedicretion != 0)
   {
            //localScale是三维的缩放
            transform.localScale = new Vector3(facedicretion,1,1);
   }

注意事项:

1.人物移动时的卡顿问题:

将TileMap在现有基础上加一个CompositeCollider2D组件,并把原来的TileMapCollider2D的

Used By Composite钩上,这样每一个瓦片的碰撞框会合并到一起,然后将刚体中的Body Type

设置为静态后即可解决。


unity sprite2D导入序列帧自动创建clip unity2d导入素材_ci_08


2.针对不同电脑帧率不同的问题:

将void Updatee() -> void FixedUpdate()

将rb.velocity = new Vector2(horizontalmove * speed, rb.velocity.y);

-> rb.velocity = new Vector2(horizontalmove * speed *Time.deltaTime, rb.velocity.y);

其中Time.deltaTime为百分比时间,可防止跳帧现象

跳跃:通过刚体来更改角色的Y轴

可以在刚体里调整重力


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_09


//跳跃
    public float jumpforce;

        //跳跃功能(Jump)
        if(Input.GetButtonDown("Jump"))         //如果检测到Jump按键(即空格)被按下
        {
            rb.velocity = new Vector2(rb.velocity.x,jumpforce * Time.deltaTime);
        }
    }
}

代码还存在跳跃不灵敏的问题未修改;

手感优化

官方手册里的


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_10


有关于按键手感的优化说明

FixedUpdate()每秒固定刷新帧数


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_11


6、实现动画效果(Animation与Animator)

<1>添加组件Animator,再创建一个Animator Controller命名为Player


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_12


再将Animator Controller拖拽到


unity sprite2D导入序列帧自动创建clip unity2d导入素材_unity_13


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_14


在Animation窗口中创建Idle(原地站立)的动画,再从素材包中找到idle的动画全部

(多选的方法:选中一个目标,按下shift再选择最后一个目标,就可以完成多选了)

拖拽到时间轴,可以拉长时间轴或调整samples来改变播放速度。


unity sprite2D导入序列帧自动创建clip unity2d导入素材_ci_15


中可点击Player后看见角色添加的动画


unity sprite2D导入序列帧自动创建clip unity2d导入素材_Powered by 金山文档_16


,再添加跑动的动画


unity sprite2D导入序列帧自动创建clip unity2d导入素材_unity_17


再让Idle和Run之间建立联系


unity sprite2D导入序列帧自动创建clip unity2d导入素材_unity_18


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_19


再给箭头设置条件


unity sprite2D导入序列帧自动创建clip unity2d导入素材_Powered by 金山文档_20


声明动画变量Anim,再将Animator拖拽到Anim中


unity sprite2D导入序列帧自动创建clip unity2d导入素材_ci_21


在脚本里添加代码


unity sprite2D导入序列帧自动创建clip unity2d导入素材_unity_22


7、跳跃动画

1、先用跟上节一样的原理给player添加jumping和falling的动画

2、在Animator中设置好触发条件


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_23


编写脚本,再在Update中调用即可

//转换动画
    void SwitchAnim()
    {
        anim.SetBool("idle", false);
        if (anim.GetBool("jumping") && rb.velocity.y < 0)                        //检测到jumping为true并且Y轴速度小于0(下落)
        {
            //触发下落动画
            anim.SetBool("jumping" , false);
            anim.SetBool("falling", true);
        }
        else if(coll.IsTouchingLayers(ground))                                  //如果接触地面
        {
            //触发站立动画
            anim.SetBool("falling", false);
            anim.SetBool("idle", true);
        }
    }

8、修复移动卡顿错误和优化代码

(1)给Player添加圆形碰撞体


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_24


调整两个碰撞体的大小


unity sprite2D导入序列帧自动创建clip unity2d导入素材_c#_25


(2)


unity sprite2D导入序列帧自动创建clip unity2d导入素材_Powered by 金山文档_26


因为rb与anim的值不需要反复更改,所以不需让他显示在Unity中

实现方法:


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_27


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_28


9、镜头控制Cinemachine

1、给Main Camera添加脚本


unity sprite2D导入序列帧自动创建clip unity2d导入素材_unity_29


2、


unity sprite2D导入序列帧自动创建clip unity2d导入素材_Powered by 金山文档_30


后将Player拖拽进此


unity sprite2D导入序列帧自动创建clip unity2d导入素材_Powered by 金山文档_31


unity sprite2D导入序列帧自动创建clip unity2d导入素材_Powered by 金山文档_32


即可实现摄像头跟随移动

3、在GameObject中打开Cinemashine创建2D摄像头,然后


unity sprite2D导入序列帧自动创建clip unity2d导入素材_ci_33


调整Dead Zone Width可锁定不跟踪范围


unity sprite2D导入序列帧自动创建clip unity2d导入素材_ci_34


4.锁定移动镜头范围


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_35


10、物品收集 & Prefabs

实现收集樱桃和宝石:

1、创建精灵


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_36


,给Cherry添加Animator组件,用前面创建角色的方法将樱桃实体化

2、给樱桃添加碰撞体Box,勾选Is Trigger(一个碰撞检测用的开关,不要让它有碰撞效果的意思)


unity sprite2D导入序列帧自动创建clip unity2d导入素材_游戏引擎_37


//拾取物品
    private void OnTriggerEnter2D(Collider2D collision)         //取消碰撞触发OnTrigger事件
    {
        if(collision.tag == "Collection")               //如果碰撞体的标签是Collection
        {
            Destroy(collision.gameObject);              //则销毁此物体
            Cherry += 1;
        }
    }

OnTriggerEnter2D:

  • Trigger触发,取消所有的物理碰撞,可以在触发时执行OnTrigger事件。
  • 想获得碰撞状态信息,又不想触发物理效果 使用OnTrigger
  • 至少一方勾选 Trigger触发器
  • 运动一方必须含有刚体

Prefabs预制件:

相当于模板,类与对象的关系

11、物理材质&空中跳跃

移动跳跃完美手感(终极版/可多段跳)

//跳跃
    void Jump()
    {
        if (isGround)
        {
            jumpCount = 2;
            isJump = false;
        }
        //第一段跳
        if (jumpPressed && isGround)     //在地面上跳跃
        {
            isJump = true;
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            jumpCount--;
            jumpPressed = false;
            jumpAudio.Play();                   //播放声音
        }
        //第二段跳
        else if (jumpPressed && jumpCount > 0 && !isGround)      //在天上
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            jumpCount--;
            jumpPressed = false;
            jumpAudio.Play();                   //播放声音
        }
    }

12、UI入门

UI ->Canvas :画布

1.添加Canvas ->添加Text->按F聚焦->blod,22,颜色

2.在代码中给Text修改值->赋值用到toString()

3.锁定UI位置->Text里Rect transform->左上角有个图形

13、敌人Enemy

1.添加敌人sprite,添加Enemy标签

2. 通过 private void OnCollisionEnter2D(Collision2D collision) 防范判断踩到敌人

遇到的问题:

添加了敌人未显示:添加层级,分层

14 受伤效果Hurt

1.添加碰撞逻辑 , 根据x的大小判断左右

2.设置弹出 rb.velocity = new Vector2(h, rb.velocity.y);

3.Mathf.Abs(rb.velocity.x) < 0.1 判断弹出是否结束,isHurt变量设置是否受伤状态

4.添加受伤动画 hurting 变量切换动画状态 anim.SetFloat("running", 0); 结束跑动状态

15 AI敌人移动

1.添加敌人控制代码

2.给敌人添加左右两个子object 确定左右节点

3. 代码中根据左右节点决定转向

  1. 拖到Perfabs 重复

问题: 滚动,原因是没有把Z轴固定

16 Animation Events动画事件

  1. 创建动画
    2. 编写 跳落地逻辑
    3. 在Idel结束帧后加入移动代码,保证动画播完

17 类的继承制作更多敌人

public class Enemy : MonoBehaviour
{
    //protected仅限父子类间使用
    protected Animator anim;
    protected AudioSource deathAudio;

    //虚方法
    protected virtual void Start()
    {
        anim = GetComponent<Animator>();
        deathAudio = GetComponent<AudioSource>();
    }

    //敌人死亡动画与音效
    public void Death()
    {
        Destroy(gameObject);
    }

    public void JumpOn()
    {
        anim.SetTrigger("death");
        deathAudio.Play();          //播放
    }
}

18 音效Audio

添加AudioSource

Play On Awarke 自动播放

Loop 是否循环

Stereo Pan 左右耳声音量

19 对话框Dialog

添加UI ->Panel

布局

添加 text

字体

围绕中心点拖动大小 option+拖动

触发Dialog

添加boxCollider -> trigger

添加代码

EnterDialog

player添加 tag

public GameObject enterDialog; //门

OnTriggerEnter2D //碰撞事件

OnTriggerExit2D //离开事件

制作动画

add Animation

点击录制按钮,设置不同帧的样式。

FixUpdate fixedDateTime

20 趴下效果Crouch

创建下蹲按钮

edit->project setting

右上角Gimoz 可以显示碰撞体

enabled 控制碰撞体是否启用

判断点周围是否重合

Physics2D.OverlapCircle

头顶添加一个object判断上方是否有碰撞物

21 场景控制SceneManager

1.回到起点

添加一个deadobject

添加deadLine Tag

重置游戏

using UnityEngine.SceneManagement;

//延时执行

Invoke("Restart", 2f);

//重新加载场景

SceneManager.LoadScene(SceneManager.GetActiveScene().name);

//关闭音源

GetComponent ().enabled = false;

index

file -> build Setting

加载到菜单

SceneManager.LoadScene("Menu");

25 主菜单MainMenu

1.新建Scene作为主菜单

2.添加panel作为背景,添加渐变动画

3.添加开始结束按钮,在on click()中选择函数