php怎样做网站,制作网站免费建站,素材下载网,台州网站开发建设✅作者简介#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者#xff0c;修心和技术同步精进。 #x1f34e;个人主页#xff1a;Java Fans的博客 #x1f34a;个人信条#xff1a;不迁怒#xff0c;不贰过。小知识#xff0c;大智慧。 #x1f49e;当前专栏… ✅作者简介2022年博客新星 第八。热爱国学的Java后端开发者修心和技术同步精进。 个人主页Java Fans的博客 个人信条不迁怒不贰过。小知识大智慧。 当前专栏Java案例分享专栏 ✨特色专栏国学周更-心性养成之路 本文内容Unity中实现预制体自动巡逻与攻击敌人的完整实现指南 文章目录 前言1. 巡逻功能1.1 引入命名空间1.2 定义 Patrol 类1.3 声明公共变量1.4 声明私有变量1.5 Start 方法1.6 Update 方法1.7 设置随机巡逻点的逻辑1.8 巡逻等待的协程1.9 巡逻功能总结 2. 发现敌人2.1 类声明2.2 声明公共变量2.3 声明私有变量2.4 Update 方法2.5 MoveToEnemy 方法2.6 发现敌人总结 3. 攻击敌人3.1 类声明3.2 声明公共变量3.3. 声明私有变量3.4. Update 方法3.5 Attack 方法3.6 攻击敌人总结 4. 整合逻辑4.1 定义枚举类型4.2 声明当前状态4.3 Update 方法4.3.1 巡逻状态4.3.2 追逐状态4.3.3 攻击状态 4.4 整合逻辑总结 总结 前言 在当今游戏开发领域自动化行为技术的应用已经成为游戏开发者们追求的热门话题。无论是为了增加游戏的趣味性、提升游戏体验还是为了减轻开发者的工作负担实现预制体自动化行为已经成为许多游戏项目的必备功能之一。本文将深入探讨如何在Unity游戏引擎中实现预制体自动巡逻并攻击敌人的全过程。 在游戏开发中预制体是一种非常常见的游戏对象它们可以被重复使用并在场景中多次实例化。然而让预制体具备自主行为、能够在游戏世界中自主移动、探索并与敌人交互是一项具有挑战性的任务。本文将引导读者逐步实现预制体的自动化行为包括目标位置到达后的随机巡逻、敌人发现与追击、攻击等关键步骤。 通过本文的指导读者将深入了解自动化行为背后的技术原理学习如何利用Unity强大的功能和工具为游戏角色赋予更加智能和自主的行为。无论是想要开发一款冒险游戏、射击游戏还是策略游戏本文都将为您提供宝贵的指导和灵感帮助您实现游戏中角色的自动化行为为玩家带来更加丰富和有趣的游戏体验。
1. 巡逻功能 预制体在到达目标位置后会在设定的范围内随机选择一个点作为新的目标位置并移动到该点。
using UnityEngine;
using UnityEngine.AI;public class Patrol : MonoBehaviour
{public Transform centerPoint; // 巡逻的中心点public float patrolRadius 10f; // 巡逻半径public float patrolWaitTime 2f; // 巡逻停留时间private NavMeshAgent agent;private Vector3 targetPosition;void Start(){agent GetComponentNavMeshAgent();SetRandomPatrolPoint();}void Update(){if (!agent.pathPending agent.remainingDistance 0.5f){StartCoroutine(PatrolWait());}}// 设置随机的巡逻点void SetRandomPatrolPoint(){Vector3 randomDirection Random.insideUnitSphere * patrolRadius;randomDirection centerPoint.position;NavMeshHit hit;NavMesh.SamplePosition(randomDirection, out hit, patrolRadius, 1);targetPosition hit.position;agent.SetDestination(targetPosition);}// 巡逻点到达后的等待IEnumerator PatrolWait(){yield return new WaitForSeconds(patrolWaitTime);SetRandomPatrolPoint();}
}这段代码是一个 Unity 脚本主要用于实现一个 AI 角色的巡逻行为。下面是对代码的逐行解释
1.1 引入命名空间
using UnityEngine;
using UnityEngine.AI;UnityEngine 是 Unity 的核心命名空间包含大多数常用类。 UnityEngine.AI 是用于处理导航和 AI 行为的命名空间包含 NavMeshAgent 类。
1.2 定义 Patrol 类
public class Patrol : MonoBehaviour定义一个名为 Patrol 的公共类继承自 MonoBehaviour。这使得 Patrol 可以被附加到 Unity 的游戏对象上并具有 Unity 生命周期方法如 Start 和 Update。
1.3 声明公共变量
public Transform centerPoint; // 巡逻的中心点
public float patrolRadius 10f; // 巡逻半径
public float patrolWaitTime 2f; // 巡逻停留时间centerPoint: 一个 Transform 类型的公共变量用于定义巡逻的中心点AI 角色的巡逻范围中心。 patrolRadius: 一个 float 类型的公共变量定义 AI 角色巡逻的半径默认为 10。 patrolWaitTime: 一个 float 类型的公共变量定义 AI 角色在每个巡逻点停留的时间默认为 2 秒。
1.4 声明私有变量
private NavMeshAgent agent;
private Vector3 targetPosition;agent: 一个 NavMeshAgent 类型的私有变量用于获取和控制 AI 角色的导航行为。 targetPosition: 一个 Vector3 类型的私有变量用于存储 AI 角色当前巡逻的目标位置。
1.5 Start 方法
void Start()
{agent GetComponentNavMeshAgent();SetRandomPatrolPoint();
}Start 方法在游戏开始时被调用。 agent GetComponent(): 获取附加在该游戏对象上的 NavMeshAgent 组件并将其赋值给 agent 变量。 SetRandomPatrolPoint(): 调用 SetRandomPatrolPoint 方法初始化 AI 的巡逻目标点。
1.6 Update 方法
void Update()
{if (!agent.pathPending agent.remainingDistance 0.5f){StartCoroutine(PatrolWait());}
}Update 方法在每一帧被调用。 if (!agent.pathPending agent.remainingDistance 0.5f): 检查 AI 角色是否已经到达目标位置remainingDistance 小于 0.5 表示接近目标。pathPending 表示当前是否还有路径计算未完成。 StartCoroutine(PatrolWait()): 如果到达目标位置则启动一个协程调用 PatrolWait 方法。
1.7 设置随机巡逻点的逻辑
void SetRandomPatrolPoint()
{Vector3 randomDirection Random.insideUnitSphere * patrolRadius;randomDirection centerPoint.position;NavMeshHit hit;NavMesh.SamplePosition(randomDirection, out hit, patrolRadius, 1);targetPosition hit.position;agent.SetDestination(targetPosition);
}Vector3 randomDirection Random.insideUnitSphere * patrolRadius;: 生成一个在球体内的随机方向并乘以 patrolRadius以得到一个随机方向的偏移量。 randomDirection centerPoint.position;: 将随机偏移量添加到巡逻中心点的坐标确定目标位置。 NavMeshHit hit;: 声明一个 NavMeshHit 变量用于接收导航网格采样结果。 NavMesh.SamplePosition(randomDirection, out hit, patrolRadius, 1);: 在 randomDirection 位置附近采样找到一个有效的导航网格位置并将结果存储在 hit 中。 targetPosition hit.position;: 将有效的目标位置赋值给 targetPosition。 agent.SetDestination(targetPosition);: 将 AI 角色的目标位置设置为新的巡逻点使其开始移动。
1.8 巡逻等待的协程
IEnumerator PatrolWait()
{yield return new WaitForSeconds(patrolWaitTime);SetRandomPatrolPoint();
}IEnumerator PatrolWait(): 定义一个协程方法允许使用 yield return。 yield return new WaitForSeconds(patrolWaitTime);: 暂停协程执行等待 patrolWaitTime 秒。 SetRandomPatrolPoint();: 等待结束后调用 SetRandomPatrolPoint 方法设置新的巡逻目标点。
1.9 巡逻功能总结 这段代码实现了一个 AI 角色在指定中心点周围巡逻的行为。它会在每个目标点停留一定时间后再随机选择新的目标点并利用 Unity 的导航系统NavMesh来处理移动。这样可以创建一个简单的巡逻行为适用于 NPC非玩家角色在游戏中的导航。
2. 发现敌人 在巡逻过程中如果在一定范围内发现敌人使用 Physics.OverlapSphere 或者 Physics.Raycast预制体会停止巡逻并向敌人移动。
public class DetectEnemy : MonoBehaviour
{public float detectionRadius 15f; // 发现敌人的范围public LayerMask enemyLayer; // 敌人的图层private GameObject enemyTarget;void Update(){Collider[] hitColliders Physics.OverlapSphere(transform.position, detectionRadius, enemyLayer);if (hitColliders.Length 0){enemyTarget hitColliders[0].gameObject;MoveToEnemy();}}void MoveToEnemy(){NavMeshAgent agent GetComponentNavMeshAgent();agent.SetDestination(enemyTarget.transform.position);}
}这段 Unity 脚本代码实现了一个 AI 角色检测敌人并朝向敌人移动的功能。下面是对代码逐行的解释
2.1 类声明
public class DetectEnemy : MonoBehaviour定义一个名为 DetectEnemy 的公共类继承自 MonoBehaviour。这意味着该类可以被附加到 Unity 中的游戏对象并能够使用 Unity 的生命周期方法。
2.2 声明公共变量
public float detectionRadius 15f; // 发现敌人的范围
public LayerMask enemyLayer; // 敌人的图层detectionRadius: 一个公共变量类型为 float用于定义 AI 角色检测敌人的半径默认为 15。 enemyLayer: 一个公共变量类型为 LayerMask用于指定哪些图层被视为敌人。这使得该 AI 角色能够仅检测特定类型的对象。
2.3 声明私有变量
private GameObject enemyTarget;enemyTarget: 一个私有变量类型为 GameObject用于存储检测到的敌人对象的引用。
2.4 Update 方法
void Update()
{Collider[] hitColliders Physics.OverlapSphere(transform.position, detectionRadius, enemyLayer);if (hitColliders.Length 0){enemyTarget hitColliders[0].gameObject;MoveToEnemy();}
}Update 方法在每一帧被调用用于检查和更新 AI 角色的状态。 Collider[] hitColliders Physics.OverlapSphere(transform.position, detectionRadius, enemyLayer);: 使用 Physics.OverlapSphere 方法在 AI 角色的位置transform.position周围创建一个球体以 detectionRadius 为半径检测所有与 enemyLayer 图层相交的碰撞体即敌人。返回的碰撞体存储在 hitColliders 数组中。 if (hitColliders.Length 0): 检查是否检测到了任何敌人即 hitColliders 数组的长度是否大于 0。 enemyTarget hitColliders[0].gameObject;: 如果检测到敌人获取第一个敌人的引用并将其赋值给 enemyTarget 变量。 MoveToEnemy();: 调用 MoveToEnemy 方法指示 AI 角色朝向敌人移动。
2.5 MoveToEnemy 方法
void MoveToEnemy()
{NavMeshAgent agent GetComponentNavMeshAgent();agent.SetDestination(enemyTarget.transform.position);
}void MoveToEnemy(): 定义一个私有方法用于处理朝向敌人移动的逻辑。 NavMeshAgent agent GetComponent();: 获取附加在该游戏对象上的 NavMeshAgent 组件并将其赋值给 agent 变量以便使用导航功能。 agent.SetDestination(enemyTarget.transform.position);: 将 AI 角色的目标位置设置为 enemyTarget即敌人的当前位置使 AI 角色开始向敌人移动。
2.6 发现敌人总结 这段代码实现了一个基本的敌人检测系统允许 AI 角色在指定半径内检测到敌人并朝向第一个检测到的敌人移动。它利用 Unity 的物理系统Physics.OverlapSphere和导航系统NavMeshAgent来实现这一功能。这个脚本可以用于游戏中 AI 角色的敌人追踪行为。
3. 攻击敌人 当预制体靠近敌人一定距离时执行攻击动作。
public class AttackEnemy : MonoBehaviour
{public float attackRange 2f; // 攻击范围public float attackCooldown 1.5f; // 攻击冷却时间private float lastAttackTime;void Update(){if (enemyTarget ! null Vector3.Distance(transform.position, enemyTarget.transform.position) attackRange){if (Time.time lastAttackTime attackCooldown){Attack();lastAttackTime Time.time;}}}void Attack(){// 攻击行为例如减去敌人生命值Debug.Log(Attacking the enemy!);}
}这段 Unity 脚本代码实现了一个 AI 角色攻击敌人的功能。下面是对代码逐行的解释
3.1 类声明
public class AttackEnemy : MonoBehaviour定义一个名为 AttackEnemy 的公共类继承自 MonoBehaviour。这意味着该类可以被附加到 Unity 的游戏对象上并能够使用 Unity 的生命周期方法。
3.2 声明公共变量
public float attackRange 2f; // 攻击范围
public float attackCooldown 1.5f; // 攻击冷却时间attackRange: 一个公共变量类型为 float用于定义 AI 角色攻击的有效范围默认为 2单位通常为米。 attackCooldown: 一个公共变量类型为 float用于定义攻击之间的冷却时间默认为 1.5 秒。
3.3. 声明私有变量
private float lastAttackTime;lastAttackTime: 一个私有变量类型为 float用于记录上一次攻击的时间。这有助于管理攻击的冷却时间。
3.4. Update 方法
void Update()
{if (enemyTarget ! null Vector3.Distance(transform.position, enemyTarget.transform.position) attackRange){if (Time.time lastAttackTime attackCooldown){Attack();lastAttackTime Time.time;}}
}Update 方法在每一帧被调用用于检查 AI 角色的攻击条件。
if (enemyTarget ! null Vector3.Distance(transform.position, enemyTarget.transform.position) attackRange):
首先检查 enemyTarget 是否为 null确保 AI 角色已经有目标。
使用 Vector3.Distance 方法计算 AI 角色与敌人之间的距离。如果距离小于或等于 attackRange则表示敌人在攻击范围内。 if (Time.time lastAttackTime attackCooldown): 检查当前时间是否大于等于上一次攻击时间加上冷却时间。如果满足条件表示可以进行下一次攻击。 Attack();: 调用 Attack 方法执行攻击动作。 lastAttackTime Time.time;: 更新 lastAttackTime 为当前时间以记录本次攻击的时间。
3.5 Attack 方法
void Attack()
{// 攻击行为例如减去敌人生命值Debug.Log(Attacking the enemy!);
}void Attack(): 定义一个私有方法用于处理攻击行为。 在方法中通过 Debug.Log 输出信息表示正在攻击敌人。这一行代码只是示例实际游戏中可以替换为减少敌人生命值、播放攻击动画、音效等攻击逻辑。
3.6 攻击敌人总结 这段代码实现了 AI 角色在一定范围内检测敌人并进行攻击的功能。它使用冷却机制来控制攻击的频率确保 AI 不会在攻击之间过于频繁地进行攻击。这个脚本可以与敌人检测和移动脚本结合使用以实现完整的 AI 行为模式。
4. 整合逻辑 将巡逻、发现敌人和攻击的逻辑整合在一个脚本或通过多个脚本管理使得预制体能在巡逻、发现敌人、追逐敌人和攻击之间进行状态切换。你可以使用状态机来更清晰地管理这些状态的切换。
public enum AIState { Patrol, Chase, Attack }
public AIState currentState AIState.Patrol;void Update()
{switch (currentState){case AIState.Patrol:Patrol();if (DetectEnemy())currentState AIState.Chase;break;case AIState.Chase:ChaseEnemy();if (IsInAttackRange())currentState AIState.Attack;break;case AIState.Attack:AttackEnemy();if (!IsInAttackRange())currentState AIState.Chase;break;}
}这段 Unity 脚本代码实现了一个简单的 AI 状态机用于控制 AI 角色在不同状态下的行为。这种设计模式可以帮助开发者管理复杂的角色行为使其在不同情境下表现出不同的反应。以下是对代码逐行的解释
4.1 定义枚举类型
public enum AIState { Patrol, Chase, Attack }public enum AIState: 定义一个公共枚举类型 AIState用于表示 AI 角色的不同状态。 枚举包含三个状态 Patrol: 巡逻状态。 Chase: 追逐状态。 Attack: 攻击状态。
4.2 声明当前状态
public AIState currentState AIState.Patrol;public AIState currentState: 声明一个公共变量 currentState用于存储 AI 角色的当前状态。 AIState.Patrol: 初始化 currentState 为 Patrol表示 AI 角色开始时处于巡逻状态。
4.3 Update 方法
void Update()
{switch (currentState){case AIState.Patrol:Patrol();if (DetectEnemy())currentState AIState.Chase;break;case AIState.Chase:ChaseEnemy();if (IsInAttackRange())currentState AIState.Attack;break;case AIState.Attack:AttackEnemy();if (!IsInAttackRange())currentState AIState.Chase;break;}
}Update 方法在每一帧被调用用于检查并执行 AI 角色的行为。
switch (currentState): 根据 currentState 的值执行不同的代码块。
4.3.1 巡逻状态
case AIState.Patrol:Patrol();if (DetectEnemy())currentState AIState.Chase;break;Patrol();: 调用 Patrol 方法执行巡逻行为。 if (DetectEnemy()): 检测是否发现敌人如果发现切换状态为 Chase追逐。
4.3.2 追逐状态
case AIState.Chase:ChaseEnemy();if (IsInAttackRange())currentState AIState.Attack;break;ChaseEnemy();: 调用 ChaseEnemy 方法执行追逐敌人的行为。 if (IsInAttackRange()): 检查是否在攻击范围内如果是切换状态为 Attack攻击。
4.3.3 攻击状态
case AIState.Attack:AttackEnemy();if (!IsInAttackRange())currentState AIState.Chase;break;AttackEnemy();: 调用 AttackEnemy 方法执行攻击行为。 if (!IsInAttackRange()): 检查是否不再处于攻击范围内。如果不在攻击范围内切换状态为 Chase追逐重新开始追逐敌人。
4.4 整合逻辑总结 这段代码实现了一个简单的 AI 状态机使得 AI 角色能够根据当前的状态执行相应的行为巡逻、追逐或攻击敌人。通过使用状态机AI 能够更灵活地管理行为便于扩展和维护。具体的巡逻、追逐和攻击行为需要在其他方法如 Patrol、ChaseEnemy 和 AttackEnemy中实现。
总结 通过使用Unity中的NavMeshAgent实现预制体的随机巡逻结合Physics.OverlapSphere检测敌人并触发追击状态以及在距离足够近时执行攻击动作我们成功地实现了预制体的自动化行为。通过合理的状态切换逻辑管理预制体的行为我们为游戏角色赋予了智能和自主性使其能够在游戏世界中自主探索、发现敌人并进行攻击。这种综合应用不仅提升了游戏的交互性和挑战性也为开发者们提供了实现自动化行为的有效方法为游戏开发注入了新的活力和可能性。 码文不易本篇文章就介绍到这里如果想要学习更多Java系列知识点击关注博主博主带你零基础学习Java知识。与此同时对于日常生活有困扰的朋友欢迎阅读我的第四栏目《国学周更—心性养成之路》学习技术的同时我们也注重了心性的养成。