NO.84——Unity官方案例Nightmare从0开始实现(二)

敌人

继续上一篇博客

基本配置
  • 资料包中给我们提供了三种类型的敌人,我们以Zombunny为例。将这个预制体拖至Hierachy层级面板中,设置层级为Shootable。
  • 添加刚体组件,配置跟玩家配置一样。
  • 添加胶囊碰撞体,胶囊碰撞体检测的是与子弹的碰撞。
  • 添加球形碰撞体,这个球形碰撞体检测的是玩家是否进入敌人攻击范围,因此把IsTrigger勾选上。
    在这里插入图片描述
什么是Collider?
  • 刚体如果想发生碰撞,一定需要碰撞体
  • 碰撞体决定了碰撞发生时的边界条件
  • 刚体决定了碰撞发生后物体的运动效果
  • 没有碰撞体的刚体,会在物理模拟中相互穿透
  • 只要一方是触发器,并且有刚体,不管另一方是出发器还是碰撞体,都会打印各自的触发器方法。
  • 一般,我们将触发器方法写在玩家碰到的物体上,玩家一般不参与触发方法,只写碰撞方法。
  • 当IsTrigger = false时,碰撞体根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/ Stay / Exit 函数。
  • 当IsTrigger = true时,碰撞体被物理引擎忽略,没有碰撞的效果,可以调用OnCollisionEnter/ Stay / Exit 函数。
自动导航
  • 在敌人物体上添加Nav Mesh Agent组件
    在这里插入图片描述
    在这里插入图片描述
    最后进行烘焙
敌人角色动画设置
  • 跟玩家的角色动画控制机类似,包含Idle , Move 和 Death三个状态。
  • 在这里我们设置Move为默认状态。
  • 在Parameters窗口添加两个Trigger参数,一个是PlayerDead,一个是Dead
  • 在状态机连接中设置过渡参数
    在这里插入图片描述
编写敌人移动脚步
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class EnemyMovement : MonoBehaviour
{
    Transform player;
    PlayerHealth playerHealth;
    EnemyHealth enemyHealth;
    NavMeshAgent nav;

    void Awake()
    {
        
        player = GameObject.FindGameObjectWithTag("Player").transform;
        playerHealth = player.GetComponent<PlayerHealth>();
        enemyHealth = GetComponent<EnemyHealth>();
        nav = GetComponent<NavMeshAgent>();
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {   
        if (enemyHealth.currentHealth > 0 && playerHealth.currentHealth >0)
        {
            //怪物身上nav组件对象
            nav.SetDestination(player.position);
        }  
        else
        {
            nav.enabled = false;
        }
    }
}

编写敌人攻击脚步
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyAttack : MonoBehaviour
{
    public float timeBetweenAttacks = 0.5f;
    public int attackDamage = 10;

    Animator anim;
    GameObject player;
    PlayerHealth playerHealth;
    EnemyHealth enemyHealth;

    bool playerInRange;
    float timer;

    void Awake()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        playerHealth = player.GetComponent<PlayerHealth>();
        enemyHealth = GetComponent<EnemyHealth>();
        anim = GetComponent<Animator>();
    }

    //分别用来处理进入和离开怪物的sphereCollider范围的时间
    //当角色离开出发器时,判断其是否为角色。
    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject == player)
        {
            playerInRange = true;  //角色在攻击范围
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (other.gameObject == player)
        {
            playerInRange = false;
        }
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        timer += Time.deltaTime;
        //控制攻击频率,timer累加到大于两个间隔 且 在攻击范围内
        if ((timer >= timeBetweenAttacks && playerInRange) && (enemyHealth.currentHealth > 0))
        {
            Attack();
        }
        if (playerHealth.currentHealth <=0)
        {
            anim.SetTrigger("PlayerDead");
        }
    }

    void Attack()
    {
        timer = 0f; //重置了计时器,这个计时器用于控制攻击的时间间隔
        //调用PlayerHealth脚本
        if (playerHealth.currentHealth > 0)
        {
            playerHealth.TakeDamage(attackDamage);
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值