3-9. 蜜蜂 - 追击和攻击的实现

动画

动画状态机改成这样

当 run = true 的时候,从 beeFly 立马切换到 beeChase

当 run = false 的时候,从 beeChase 立马切换到 beeFly

当 hurt 触发的时候,从 Any State 立马切换到 beeHurt,当 beeHurt 完整播放一次之后,进入 Exit

当 attack 触发的时候,从 Any State 立马切换到 beeAttack,当 beeAttack 完整播放一次之后,进入 Exit

当 dead = true 的时候,从 Any State 立马切换到 beeDead

代码

BeeChaseState

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static UnityEngine.GraphicsBuffer;

public class BeeChaseState : BaseState
{
    private Attack attack;
    private Vector3 target;
    private Vector3 moveDir;
    private bool isAttack;
    private float attackRateCounter = 0;

    public override void OnEnter(Enemy enemy)
    {
        currentEnemy = enemy;
        currentEnemy.currentSpeed = currentEnemy.chaseSpeed;
        currentEnemy.anim.SetBool("run", true);
        attack = enemy.GetComponent<Attack>();

        currentEnemy.lostTimeCounter = currentEnemy.lostTime;
    }

    public override void LogicUpdate()
    {
        if (currentEnemy.lostTimeCounter <= 0)
        {
            currentEnemy.SwitchState(NPCState.Patrol);
        }

        // attacker.position 是指玩家脚底的位置,这不是我们想要的,所以在 y 轴上要加 1.5
        target = new Vector3(currentEnemy.attacker.position.x, currentEnemy.attacker.position.y + 1.5f, 0);

        // 判断攻击距离
        if ((target - currentEnemy.transform.position).magnitude <= attack.attackRange)
        {
            // 可以播放攻击动画了
            isAttack = true;

            // 先让蜜蜂停下来
            if (!currentEnemy.isHurt)
            {
                currentEnemy.rb.velocity = Vector2.zero;
            }

            // 计时器
            attackRateCounter -= Time.deltaTime;
            if (attackRateCounter <= 0)
            {
                currentEnemy.anim.SetTrigger("attack");
                attackRateCounter = attack.attackRate;
            }
        }
        else
        {
            // 超出攻击范围
            isAttack = false;
        }

        // 移动方向 = 目标位置 - 当前位置
        moveDir = (target - currentEnemy.transform.position).normalized;
        if (moveDir.x > 0)
        {
            currentEnemy.transform.localScale = new Vector3(
                -1 * Mathf.Abs(currentEnemy.transform.localScale.x),
                currentEnemy.transform.localScale.y,
                currentEnemy.transform.localScale.z
            );
        }
        else if (moveDir.x < 0)
        {
            currentEnemy.transform.localScale = new Vector3(
                Mathf.Abs(currentEnemy.transform.localScale.x),
                currentEnemy.transform.localScale.y,
                currentEnemy.transform.localScale.z
            );
        }
    }

    public override void PhysicsUpdate()
    {
        if (!currentEnemy.isHurt && 
            !currentEnemy.isDead && 
            !currentEnemy.wait &&
            !isAttack)
        {
            currentEnemy.rb.velocity = moveDir * currentEnemy.currentSpeed;
        }
        // 追击过程中是没有 wait 等待的
    }

    public override void OnExit()
    {
        currentEnemy.anim.SetBool("run", false);
    }
}

OnEnter 的时候,设置敌人、设置速度、播放追逐动画、初始化 Attack 组件(因为 Attack 组件上面有个范围,在范围内的时候需要停下来攻击)、初始化 lostTimeCounter(避免蜜蜂刚进入追逐状态,立马就退出变回巡逻状态)

LogicUpdate 的时候,如果 lostTimeCounter 变 0 了,说明蜜蜂失去目标,返回到巡逻状态。接着蜜蜂和玩家的距离小于攻击范围的时候,就会停下来,并按 attackRate 标识的秒数攻击一次玩家。这个攻击动画需要注意一下,在蜜蜂伸出刺的时候,需要出现触发器,这个触发器上面也要绑定一个 Attack 组件。超出范围之后不进行攻击。同样移动的时候,也需要注意朝向

PhysicsUpdate 的时候,与巡逻时候一样,修改蜜蜂的速度。需要注意一下,攻击的时候也不能动

OnExit 的时候,就把动画状态机从 chase 改回到 patrol 即可

Bee

Bee 的 Awake 里面需要初始化 chaseState

属性

Attack

Character

Attack Point

项目相关代码

代码仓库:https://gitee.com/nbda1121440/2DAdventure.git

标签:20240226_1343

posted @   hellozjf  阅读(98)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示