Unity实现怪物巡逻追击玩家

来源于一个因为某些原因做废了的Demo,但是里面的东西还是挺多的。

这里实现了一个怪物自动追击玩家,丢失目标后,自动返回其原点的功能:

实现思路:

首先,需要用到Unity自带的NavMeshAgent组件,也就是自动寻路组件

然后思路是分为两个部分,思考和移动,首先怪物会思考与玩家的位置,并在满足与玩家的某些交互条件的时候自动切换到相应的状态,也就是将思考结果付之行动。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.AI;

/* 
 *琦玉老师的二弟子
 */

namespace Control{//NameSpace_Start--------------------------------------------------------------------------------------------------------

public class Ctrl_EnemyAi : MonoBehaviour {
        //Class_Start--------------------------------------------------------------------------------------------------------

        //1.思考
        //2.移动
        private NavMeshAgent agent;
        private GameObject Player;
        private Vector3 BoringPosition;
        private Ctrl_Enemy_ShuXing EnemyShuXing;
        public float RotateSpeed;

        private void Awake()
        {
            agent = this.GetComponent<NavMeshAgent>();
            EnemyShuXing = this.GetComponent<Ctrl_Enemy_ShuXing>();
            BoringPosition = this.transform.position;
            Player = GameObject.FindGameObjectWithTag("Player");
        }

        private void Start()
        {
            StartCoroutine("FindPlayer");
            StartCoroutine("Moving");
        }

        /// <summary>
        /// 寻找玩家协程
        /// </summary>
        /// <returns></returns>
        IEnumerator FindPlayer()
        {
            while (true)
            {
                yield return new WaitForSeconds(0.45f);

                Vector3 PlayerPosition = Player.transform.position;

                if (EnemyShuXing.CurrentState!=Global.GlobalParameter.EnemyState.Dealth)
                {
                    //得到与主角的距离
                    float Distance = Vector3.Distance(transform.position, PlayerPosition);
                    //距离判断
                    if (Distance <= 2.3f)
                    {
                        //攻击状态
                        EnemyShuXing.CurrentState = Global.GlobalParameter.EnemyState.Attack;
                    }
                    else if (Distance <=8f)
                    {
                        //追击状态
                        EnemyShuXing.CurrentState = Global.GlobalParameter.EnemyState.walking;
                    }
                    else
                    {
                        //返回出生位置,Idle
                        EnemyShuXing.CurrentState = Global.GlobalParameter.EnemyState.LostTarget;
                    }

                }

            }
        }

        IEnumerator Moving()
        {
            while (true)
            {
                yield return null;
                switch (EnemyShuXing.CurrentState)
                {

                    case Global.GlobalParameter.EnemyState.walking:                        
                        agent.SetDestination(Player.transform.position);
                        break;
                    case Global.GlobalParameter.EnemyState.LostTarget:
                        agent.SetDestination(BoringPosition);
                        if (Vector3.Distance(BoringPosition, this.transform.position) <= 2.3f)
                        {
                            EnemyShuXing.CurrentState = Global.GlobalParameter.EnemyState.idle;
                        }                      
                        break;
                    default:
                        break;
                }
            }
        }

        private void Update()
        {
            if (EnemyShuXing.CurrentState == Global.GlobalParameter.EnemyState.Attack)
            {
                transform.rotation = Quaternion.Lerp(transform.rotation,Quaternion.LookRotation(Player.transform.position-this.transform.position),RotateSpeed* Time.deltaTime);
            }
        }

        //Class_End--------------------------------------------------------------------------------------------------------
    }
}//NameSpace_End--------------------------------------------------------------------------------------------------------

 

  • 12
    点赞
  • 121
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是一个简单的Unity状态机,用于实现巡逻追击和死亡行为: ```csharp public class EnemyStateMachine : MonoBehaviour { public Transform[] patrolPoints; // 巡逻点 public float patrolSpeed = 3f; // 巡逻速度 public float chaseSpeed = 5f; // 追击速度 public float chaseRange = 10f; // 追击范围 public float attackRange = 2f; // 攻击范围 public float attackRate = 1f; // 攻击间隔 public int attackPower = 10; // 攻击力 public float deathDelay = 3f; // 死亡延迟 private Animator animator; // 动画控制器 private NavMeshAgent agent; // 导航代理 private Transform player; // 玩家 private int patrolIndex = 0; // 巡逻点索引 private float lastAttackTime = 0f; // 上次攻击时间 private bool isDead = false; // 是否死亡 private void Start() { animator = GetComponent<Animator>(); agent = GetComponent<NavMeshAgent>(); player = GameObject.FindGameObjectWithTag("Player").transform; // 假设玩家标签为"Player" } private void Update() { if (isDead) return; float distance = Vector3.Distance(transform.position, player.position); // 如果玩家在攻击范围内并且攻击间隔已经过去,就攻击玩家 if (distance <= attackRange && Time.time - lastAttackTime >= attackRate) { Attack(); lastAttackTime = Time.time; } // 如果玩家追击范围内,就追击玩家 else if (distance <= chaseRange) { Chase(); } // 否则巡逻 else { Patrol(); } } private void Patrol() { agent.speed = patrolSpeed; animator.SetBool("isWalking", true); animator.SetBool("isRunning", false); agent.SetDestination(patrolPoints[patrolIndex].position); if (agent.remainingDistance <= agent.stoppingDistance) { patrolIndex = (patrolIndex + 1) % patrolPoints.Length; } } private void Chase() { agent.speed = chaseSpeed; animator.SetBool("isWalking", false); animator.SetBool("isRunning", true); agent.SetDestination(player.position); } private void Attack() { animator.SetBool("isAttacking", true); player.GetComponent<PlayerHealth>().TakeDamage(attackPower); // 假设玩家有一个叫做PlayerHealth的组件来处理扣血 Invoke("ResetAttack", 1f); // 1秒后重置攻击状态 } private void ResetAttack() { animator.SetBool("isAttacking", false); } public void Die() { if (isDead) return; animator.SetBool("isDead", true); isDead = true; agent.enabled = false; Invoke("DestroySelf", deathDelay); } private void DestroySelf() { Destroy(gameObject); } } ``` 该脚本需要挂载在敌人对象上,并且需要设置巡逻点和一些参数。在巡逻追击和攻击时,分别设置动画状态和目标位置,攻击时还需要调用玩家组件的TakeDamage方法。在死亡时,设置动画状态为死亡并在一段延迟后销毁自身。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值