最终效果
文章目录
最终效果系列目录前言导入AI导航系统导航烘培添加羊源码完结
系列目录
【制作100个unity游戏之24】unity制作一个3D动物AI生态系统游戏1(附项目源码)
【制作100个unity游戏之24】unity制作一个3D动物AI生态系统游戏2(附项目源码)
【制作100个unity游戏之24】unity制作一个3D动物AI生态系统游戏3(附项目源码)
前言
欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第24篇中,我们将探索如何用unity制作一个3D动物AI生态系统游戏,我会附带项目源码,以便你们更好理解它。
导入AI导航系统
导航系统基础介绍可以看我之前的文章:【Unity游戏开发教程】零基础带你从小白到超神29——导航系统
如果你用的是unity2022及以上,可能需要先导入AI导航组件
导航烘培
配置地形为静态可行走导航
点击烘培
如果要添加动态障碍物,可以使给物体添加动态导航(NavMeshObstacle组件)
添加羊
代码简单控制羊的随机行为
// 定义动物状态的枚举类型public enum AnimalState{ Idle, // 空闲状态 Moving // 移动状态}// 必须附加到具有 NavMeshAgent 组件的游戏对象上[RequireComponent(typeof(NavMeshAgent))]public class Animal : MonoBehaviour{ [Header("Wander")] public float wanderDistance = 50f; // 动物一次移动的距离 public float walkSpeed = 5f; // 动物的行走速度 public float maxWalkTime = 6f; // 动物行走的最大时间 [Header("Idle")] public float idleTime = 5f; // 动物休息的时间 protected NavMeshAgent navMeshAgent; // 存储 NavMeshAgent 组件的引用 protected AnimalState currentState = AnimalState.Idle; // 存储当前动物的状态,默认为 Idle private void Start() { InitialiseAnimal(); // 初始化动物 } // 初始化动物 protected virtual void InitialiseAnimal() { navMeshAgent = GetComponent<NavMeshAgent>(); // 获取 NavMeshAgent 组件的引用 navMeshAgent.speed = walkSpeed; // 设置动物的行走速度 currentState = AnimalState.Idle; // 将当前状态设置为 Idle UpdateState(); // 更新动物的状态 } // 更新动物的状态 protected virtual void UpdateState() { switch (currentState) { case AnimalState.Idle: // 如果当前状态是 Idle HandleIdleState(); // 处理空闲状态 break; case AnimalState.Moving: // 如果当前状态是 Moving HandleMovingState(); // 处理移动状态 break; } } // 获取距离起点一定距离内的随机 NavMesh 位置 protected Vector3 GetRandomNavMeshPosition(Vector3 origin, float distance) { Vector3 randomDirection = Random.insideUnitSphere * distance; // 在球形区域内生成一个随机方向 randomDirection += origin; // 将随机方向与起点相加,计算出随机点的位置 NavMeshHit navMeshHit; if (NavMesh.SamplePosition(randomDirection, out navMeshHit, distance, NavMesh.AllAreas)) { // 如果找到了 NavMesh 上的可行走位置,返回该位置 return navMeshHit.position; } else { // 否则递归调用函数,继续查找新的随机位置 return GetRandomNavMeshPosition(origin, distance); } } // 处理空闲状态 protected virtual void HandleIdleState() { StartCoroutine(WaitToMove()); // 等待一段时间后转换到移动状态 } // 等待一段时间后转换到移动状态 private IEnumerator WaitToMove() { float waitTime = Random.Range(idleTime / 2, idleTime * 2); // 随机生成等待时间 yield return new WaitForSeconds(waitTime); // 等待一段时间 Vector3 randomDestination = GetRandomNavMeshPosition(transform.position, wanderDistance); // 获取随机位置 navMeshAgent.SetDestination(randomDestination); // 设置 NavMeshAgent 的目标位置 SetState(AnimalState.Moving); // 将状态设置为 Moving } // 处理移动状态 protected virtual void HandleMovingState() { StartCoroutine(WaitToReachDestination()); // 等待到达目的地后转换到空闲状态 } // 等待到达目的地后转换到空闲状态 private IEnumerator WaitToReachDestination() { float startTime = Time.time; // 记录开始移动的时间 while (navMeshAgent.remainingDistance > navMeshAgent.stoppingDistance) // 当还未到达目的地时循环 { if (Time.time - startTime >= maxWalkTime) // 如果超过了最大行走时间 { navMeshAgent.ResetPath(); // 重置路径 SetState(AnimalState.Idle); // 将状态设置为 Idle yield break; // 结束函数的执行 } yield return null; // 等待下一帧 } // 到达目的地后将状态设置为 Idle SetState(AnimalState.Idle); } // 将动物的状态设置为指定的状态 protected void SetState(AnimalState newState) { if (currentState == newState) // 如果新状态与当前状态相同,直接返回 { return; } currentState = newState; // 更新当前状态 OnStateChanged(newState); // 触发状态改变事件 } // 状态改变事件的处理函数 protected virtual void OnStateChanged(AnimalState newState) { UpdateState(); // 更新动物的状态 }}
添加羊,配置参数
效果
源码
源码在最后一期
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,以便我第一时间收到反馈,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~