3-8. 蜜蜂 - 基本的移动逻辑和动画

动画

切割图片,制作动画,注意:锚点在中心点

注意:beeFly 和 beeChase 使用相同的动画,但是速度不一样

代码

Enemy

因为 蜜蜂 的行动方式与 野猪、蜗牛 都不一样,它是在空中飞的,所以它检测玩家和移动的方式都是不一样的,所以我们需要对 Enemy 中 FoundPlayer、OnDrawGizmosSelected、Move 这三个方法都进行重写,将它们标记成 virtual

另外,蜜蜂移动的时候需要一个目标点,所以还需要在 Enemy 中再增加一个 GetNewPoint 方法

Bee

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

public class Bee : Enemy
{
    [Header("移动范围")]
    public float patrolRadius;

    protected override void Awake()
    {
        base.Awake();
        patrolState = new BeePatrolState();
    }

    public override bool FoundPlayer()
    {
        var obj = Physics2D.OverlapCircle(transform.position, checkDistance, attackLayer);
        if (obj)
        {
            attacker = obj.transform;
        }
        return obj;
    }

    public override void OnDrawGizmosSelected()
    {
        // 画出警戒区大小
        Gizmos.DrawWireSphere(transform.position, checkDistance);

        // 画出巡逻范围大小
        Gizmos.color = Color.green;
        if (spwanPoint == Vector3.zero)
        {
            Gizmos.DrawWireSphere(transform.position, patrolRadius);
        }
        else
        {
            Gizmos.DrawWireSphere(spwanPoint, patrolRadius);
        }
    }

    public override Vector3 GetNewPoint()
    {
        // 算出随机角度
        float randomAngle = Random.Range(0f, 2f * Mathf.PI);
        // 算出随机向量
        Vector2 randomVector2 = new Vector2(Mathf.Cos(randomAngle), Mathf.Sin(randomAngle));
        // 算出随机半径
        float radius = Random.Range(0.0f, patrolRadius);

        return spwanPoint + (Vector3) (randomVector2 * radius);
    }

    public override void Move()
    {
        
    }
}

蜜蜂检测玩家的方式,是通过一个圆圈的范围进行检测

所以绘制检测范围的时候也需要使用圆圈来进行检测,蜜蜂的巡逻范围也是一个圆圈,用不同的颜色标识出来

蜜蜂需要一个目标点,目标点应该是在绿色的巡逻范围内,所以使用随机角度乘以随机距离,再加上出身点位置,获取目标点

蜜蜂的 Move 不需要实现,直接在 BeePatrolState.PhysicsUpdate 里面实现

BeePatrolState

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

public class BeePatrolState : BaseState
{
    private Vector3 target;
    private Vector3 moveDir;

    public override void OnEnter(Enemy enemy)
    {
        currentEnemy = enemy;
        currentEnemy.currentSpeed = currentEnemy.normalSpeed;
        currentEnemy.anim.SetBool("walk", true);

        // 进入巡逻状态的时候,先设置一个目标点
        target = currentEnemy.GetNewPoint();
    }

    public override void LogicUpdate()
    {
        // 发现 player 切换到 chase 
        if (currentEnemy.FoundPlayer())
        {
            currentEnemy.SwitchState(NPCState.Chase);
        }

        if ((currentEnemy.transform.position - target).sqrMagnitude < 0.1f)
        {
            // 说明到达目标点了
            currentEnemy.wait = true;
            target = currentEnemy.GetNewPoint();
        }

        // 移动方向 = 目标位置 - 当前位置
        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)
        {
            currentEnemy.rb.velocity = moveDir * currentEnemy.currentSpeed;
        }
        else
        {
            // 否则需要停下来
            currentEnemy.rb.velocity = Vector2.zero;
        }
    }

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

在 OnEnter 的时候,需要设置当前对象、速度、动画,此外还要获取一个目标点

在 LogicUpdate 的时候,发现玩家进入追逐状态,到达目的的时候进入等待状态,算出移动的方向并调整朝向

在 PhysicsUpdate 的时候,修改蜜蜂刚体的速度,如果受伤、死亡、等待的话速度变0

在 OnExit 的时候,取消动画

设置变量

Layer

Sprite Renderer

Rigidbody2D

蜜蜂不要受到重力影响,否则会掉下去

Animator

PhysicsCheck

蜜蜂是在空中飞的,可以穿墙,所以不需要设置物理监测参数

Bee

Capsule Collider 2D

蜜蜂只需要触发器,不需要碰撞体,因为它可以穿墙

项目相关代码

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

标签:20240226_1214

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