九、怪物行为逻辑

一、怪物正常行为

1、导入资源

2、创建怪物预制体

新建一个空物体,作为父级、怪物作为子级

3、导入怪物动画

在怪物身上添加角色控制器和动画组件

此时怪物会有碰撞不会穿模

创建一个动画控制器,放入攻击状态和正常状态

并设置一个Bool值,为攻击

注:模型动画预览时,需要拖入子物体模型,不能放入父级物体

如图所示:

如果模型是预制体,那么只能拖入模型,不能放入父级

如果模型与父级是同一个预制体,那么拖入父级也就相当于一个整体的人物模型

二、AI寻路组件

1、地图烘焙

2、挂载AI组件和代码

注意:

敌人可能会出现进入玩家的身体里的情况

解决方法:

AI组件中有一个停止距离,敌人的脚本中有一个攻击距离,二者之间需要有一个大小值

第一种情况:敌人的攻击距离大于停止距离,则先停止后攻击,不会进入身体中

第二种情况:敌人的攻击距离小于停止距离,则会出现一直进入身体的Bug

写敌人的逻辑时需要注意一下。

3、代码

注:使怪物始终朝向玩家,必须设置锁定Y轴的代码

否则会出现,敌人身体倾斜

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public enum BossState
{
    idle,
    attack,
    run
}
public class EnemyControl : MonoBehaviour
{
    private BossState CurrentState= BossState.idle;//枚举状态
    private Animator Anim;//怪物动画控制器
    private NavMeshAgent Agent;//导航网格代理
    private float HpNow = 100;
    private bool ISDead = false;
    private Transform player;//玩家位置
    

    public float IdleDis = 100.0f;//站立寻敌范围
    public float AttackDis = 3.0f;//攻击距离
    public float HpMax = 100.0f;
	//声音管理组件
	public AudioSource AudioSource1;
	//播放声音大小
	public float SoundValue = 1.0f;
	//第一个攻击声音
	public AudioClip AudioClip1;


	private void Start() 
	{
        HpNow = HpMax;
		Anim = GetComponent<Animator>(); 
        Agent = GetComponent<NavMeshAgent>();
        player = GameObject.FindWithTag("Player").transform;
	}
	private void Update()
	{
        LookAtPlayer();
        EnemyState();
	}
    /// <summary>
    /// 始终朝向玩家
    /// </summary>
    public void LookAtPlayer()
    {
        if (!ISDead)
        {
            Vector3 PlayerPos = player.position;
            PlayerPos.y = transform.position.y;
            transform.LookAt(PlayerPos);
        }
    }
    /// <summary>
    /// 切换怪物状态
    /// </summary>
    public void EnemyState()
    {
        if (!ISDead)
        {
            float Distance1=Vector3.Distance(transform.position, player.position);
            switch (CurrentState)
            {
                //静止状态
                case BossState.idle:
                    Anim.Play("RunTree");
                    Anim.SetFloat("MoveSpeed", 0f);
                    Anim.SetBool("Attack", false);
                    Agent.isStopped = true;
                    if(Distance1> AttackDis && Distance1 <= IdleDis)
                    {
                        CurrentState=BossState.run;
                    }
                    break;
                //追踪状态
                case BossState.run:
                    Agent.isStopped = false;
                    Agent.SetDestination(player.position);
                    Anim.SetFloat("MoveSpeed", 1f);
                    Anim.SetBool("Attack", false);
                    if (Distance1 > IdleDis)
                    {
                        CurrentState= BossState.idle;
                    }
                    else if (Distance1 <= AttackDis)
                    {
                        CurrentState = BossState.attack;
                    }
                    break;
                //攻击状态
                case BossState.attack:
                    Agent.isStopped=true;
                    BossAttack();
                    if (Distance1 > AttackDis)
                    {
                        CurrentState= BossState.run ;
                    }
                    else
                    {
                        Anim.SetFloat("MoveSpeed", 0f);
                    }

					break;
            }
        }
    }
    //Boss攻击
    public void BossAttack()
    {
        if (Anim.GetBool("Attack"))
        {
            return;
        }

        Anim.SetBool("Attack", true);

    }
    //播放声音,在动画事件中调用
    public void PlayAttackSound()
    {
        AudioSource1.PlayOneShot(AudioClip1, SoundValue);

    }
}

4、混合树

将敌人的Idle和Run状态混合

混合度、播放速度、镜像

二者的区别是Play没有过度;CrossFade有过度

三、添加敌人音效

技巧:在动画事件上添加攻击音效,这样只会在敌人攻击时播放

1、代码

声明部分

2、动画事件

四、敌人伤害

1、实现原理

和之前一样,也是在动画事件中进行调用,在挥砍的那一瞬间调用

在此项目中,使用一个攻击点和一个预制体(触发器)进行实例化,判断触发伤害

动画事件和触发器一起使用

还有一种方法使用射线检测

2、制作点和实例化物体

把空物体放置在子物体下,不然会出现实例化位置移动

建一个空物体挂载代码,并制作成预制体

注意:此处选择小写的gameobject,为此物体

在实例化出来后,一定时间内销毁此物体

在玩家的每一个攻击中实例化此物体

3、伤害

写一个随机值

五、怪物受击特效

实现原理:实例化音效和特效在一个点,点挂载到玩家的身上

1、创建实例化位置

挂载到敌人的身上

创建一个空物体,添加代码和音效,音效设置为启用时播放

即可在实例化的时候 产生攻击特效和音效

2、代码

首先,实例化的物体要写消失条件

在敌人的受击方法中,添加实例化并播放受击动画

3、动画连接

相关推荐
枯萎穿心攻击5 小时前
响应式编程入门教程第二节:构建 ObservableProperty<T> — 封装 ReactiveProperty 的高级用法
开发语言·unity·c#·游戏引擎
Luna-player10 小时前
黑布淡入淡出效果
经验分享·游戏
X_StarX13 小时前
【Unity笔记02】订阅事件-自动开门
笔记·学习·unity·游戏引擎·游戏开发·大学生
霸王•吕布17 小时前
游戏引擎中顶点着色&像素着色
游戏引擎·顶点着色器·像素着色器·顶点颜色·顶点uv·顶点法向
Thomas_YXQ20 小时前
Unity URP法线贴图实现教程
开发语言·unity·性能优化·游戏引擎·unity3d·贴图·单一职责原则
徐子竣1 天前
[学习记录]Unity-Shader-几何着色器
unity·游戏引擎·着色器
EQ-雪梨蛋花汤1 天前
【Part 3 Unity VR眼镜端播放器开发与优化】第四节|高分辨率VR全景视频播放性能优化
unity·音视频·vr
TESmart碲视1 天前
HKS201-M24 大师版 8K60Hz USB 3.0 适用于 2 台 PC 1台显示器 无缝切换 KVM 切换器
单片机·嵌入式硬件·物联网·游戏·计算机外设·电脑·智能硬件
翻滚吧键盘1 天前
查看linux中steam游戏的兼容性
linux·运维·游戏
与火星的孩子对话2 天前
Unity进阶课程【六】Android、ios、Pad 终端设备打包局域网IP调试、USB调试、性能检测、控制台打印日志等、C#
android·unity·ios·c#·ip