【游戏开发实战】使用Unity 2019制作仿微信小游戏飞机大战(九):敌机受击与爆炸

零、教程目录

使用Unity 2019制作仿微信小游戏飞机大战教程已完结。
文章目录如下:
《第一篇:开始游戏界面》
《第二篇:搭建基础游戏框架》
《第三篇:战斗界面UI》
《第四篇:主角飞机序列帧动画》
《第五篇:主角飞机的飞行控制》
《第六篇:根据配置随机生成敌机》
《第七篇:主角飞机碰撞与爆炸》
《第八篇:主角飞机开炮》
《第九篇:敌机受击与爆炸》
《第十篇:敌机血量与得分》
《第十一篇:核弹掉落与全屏炸机》
《第十二篇:敌机开炮》
《第十三篇:游戏暂停、结束与重新开始》

一、前言

嗨,大家好,我是新发。相信很多人玩过微信小游戏经典的飞机大战,如下:
在这里插入图片描述
想重温或体验微信这款经典的飞机大战的同学可以点这里:https://gamemaker.weixin.qq.com/ide#/
在这里插入图片描述

在网上已经有一些人已经出了Unity的制作教程,但是比较陈旧,里面使用了已经弃用的组件和写法,用了很陈旧的NGUI版本,如果使用Unity 2019或以上版本打开会各种报错,对新入门Unity的同学不大友好。

于是,我决定写一个全新的教程:《使用Unity2019制作仿微信小游戏飞机大战》,会使用最新的写法,并且使用尽量简洁的设计与代码来完成。

本教程的工程已上传到Github,感兴趣的同学自行下载学习。
喜欢的同学记得给个星星~
Github地址:https://github.com/linxinfa/UnityAircraftFight
在这里插入图片描述
Unity游戏开发有任何问题的,都欢迎在评论区留言,我都会看到的,并会进行认真解答,希望能帮助到想学Unity开发的同学,共勉。

二、本篇目标

敌机受击与爆炸。
本篇的效果:
在这里插入图片描述

三、主角子弹Tag

添加一个PlayerBulletTag
在这里插入图片描述
将主角子弹预设的Tag设置为PlayerBullet
在这里插入图片描述

四、敌机动画状态机

在写敌机受击与爆炸的逻辑之前,我们需要先处理下敌机的动画状态机和帧事件。
以敌机2的动画位例。
在这里插入图片描述

1、动画变量

双击打开Enemy_2动画控制器。
在这里插入图片描述
添加两个Bool类型的变量:explodeunderattack
在这里插入图片描述

2、组织动画状态过渡

组织动画状态过渡如下,注意受击后要回到Normal状态。
在这里插入图片描述

3、设置过渡条件

设置NormalUndderAttack的过渡条件为underattacktrue,并去掉Has Exit Time的勾选。
在这里插入图片描述
设置NormalExplode的过渡条件为explodetrue,并去掉Has Exit Time的勾选。
在这里插入图片描述
同理另外两个敌机的动画也这样设置(注意敌机1没有受击动画)。

4、设置爆炸动画的帧事件

因为我们需要监听爆炸播放完毕的帧事件然后回收敌机,所以我们需要给敌机的爆炸动画添加帧事件。
以敌机2的爆炸动画为例,双击打开爆炸动画Enemy_2_Explode
在这里插入图片描述
此时会打开Animation窗口,在最后一帧的下一帧添加一个帧事件。
在这里插入图片描述
编辑帧事件的响应函数为OnAnimationEvent,字符串参数为explode_finish
在这里插入图片描述
另外,把动画帧率统一调成8帧每秒,不然动画帧率太快的话,爆炸的效果一下子就结束了。
在这里插入图片描述
同理,编辑另外两个敌机的爆炸动画帧事件。

五、敌机类添加碰撞处理

先给飞机基类BaseAircraft添加个碰撞体成员。

// BaseAircraft.cs

protected Collider2D m_collider;

protected virtual void Awake()
{
	// ...
    m_collider = GetComponent<Collider2D>();
}

然后实现敌机的碰撞处理函数,最终敌机脚本EnemyAircraft如下:

// EnemyAircraft.cs

using UnityEngine;
using System;

/// <summary>
/// 敌机类
/// </summary>
public class EnemyAircraft : BaseAircraft
{
    public float moveSpeed = 0;
    public Action backToPoolAction;
    private bool m_underAttack = false;

    protected override void Awake()
    {
        base.Awake();
        m_aniEvent.aniEventCb = (msg) =>
        {
            if ("explode_finish" == msg)
            {
                BackToPool();
            }
        };
    }

    /// <summary>
    /// 随机一个起始位置
    /// </summary>
    public void RandomStartPos()
    {
        var randomX = UnityEngine.Random.Range(0, Screen.width);
        m_selfTrans.position = Camera.main.ScreenToWorldPoint(new Vector3(randomX, Screen.height, 5));
    }

    private void Update()
    {
        // 敌机下落
        m_selfTrans.position += new Vector3(0, -moveSpeed * Time.deltaTime, 0);

        // 超过屏幕下面
        if (Camera.main.WorldToScreenPoint(m_selfTrans.position).y <= -50)
        {
            BackToPool();
        }
    }

    /// <summary>
    /// 碰撞处理
    /// </summary>
    /// <param name="other"></param>
    public override void OnTriggerEnter2D(Collider2D other)
    {
        if ("PlayerBullet" == other.tag)
        {
            --blood;
            if (blood > 0)
            {
                // 受击
                UnderAttack();
            }
            else
            {
                // 爆炸
                Explode();
            }
        }
    }

    private void LateUpdate()
    {
        if (m_underAttack)
        {
            m_underAttack = false;
            ani.SetBool("underattack", m_underAttack);
        }
    }

    /// <summary>
    /// 对象回收
    /// </summary>
    private void BackToPool()
    {
        ActiveSelf(false);
        if (null != backToPoolAction)
            backToPoolAction();
    }

    /// <summary>
    /// 激活
    /// </summary>
    public void ActiveSelf(bool active)
    {
        m_collider.enabled = active;
        m_selfGo.SetActive(active);
    }

    /// <summary>
    /// 受击
    /// </summary>
    public override void UnderAttack()
    {
        m_underAttack = true;
        ani.SetBool("underattack", m_underAttack);
    }

    /// <summary>
    /// 爆炸
    /// </summary>
    public override void Explode()
    {
        // 爆炸时,把碰撞体禁用
        m_collider.enabled = false;

        ani.SetBool("explode", true);
    }
}

六、运行测试

运行Unity,测试效果如下:
在这里插入图片描述

七、下篇预告

下篇讲敌机血量和得分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林新发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值