前言
欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第23篇中,我们将探索如何制作一个类似于七日杀和森林的生存游戏。
本篇内容会比较多,我会分几篇来实现,感兴趣的可以关注一下,以免错过内容更新。
本节主要实现添加小动物,动画控制,简单的动物AI,添加可拾取物品,并实现简单的拾取功能。
添加小动物
模型
这里我找了个小鸭子,素材可以选择自己喜欢的
https://sketchfab.com/3d-models/duckling-5416523b63be499ba352a2566e652849
不知道导入的模型如何配置,可以看我这篇文章:
unity中导入下载的3D模型及albedo/baseColor、normal 、AO/Occlus、metallic、roughness贴图纹理设置
动画
Idles为新建的子状态机
动物AI脚本
public class AI_Movement : MonoBehaviour { Animator animator; // 动画组件 [Header("移动属性")] public float moveSpeed = 0.2f; // 移动速度 Vector3 stopPosition; // 停止移动时的位置 float walkTime; // 移动时间 float walkCounter; // 移动计时器 int walkDirection; // 移动方向 bool isWalking; // 是否在移动 [Header("待机属性")] public int stateCount;//状态数量 float waitCounter; // 等待计时器 float waitTime; // 等待时间 private int nextState;//下一个状态 [Header("动画状态属性")] private readonly int hashRandomWalk = Animator.StringToHash("isWalking");//行走状态属性 private readonly int hashRandomIdle = Animator.StringToHash("Idle");//待机状态属性 void Start() { animator = GetComponent<Animator>(); // 获取动画组件 // 随机设置移动和停止的时间 walkTime = Random.Range(3, 6); waitTime = Random.Range(5, 7); waitCounter = waitTime; walkCounter = walkTime; ChooseDirection(); // 随机选择方向 } void Update() { if (isWalking) // 如果正在移动 { animator.SetBool(hashRandomWalk, true); // 设置动画为奔跑状态 walkCounter -= Time.deltaTime; // 计时器减少 switch (walkDirection) { case 0: transform.localRotation = Quaternion.Euler(0f, 0f, 0f); // 调整角度为正前方 transform.position += transform.forward * moveSpeed * Time.deltaTime; // 向前移动 break; case 1: transform.localRotation = Quaternion.Euler(0f, 90f, 0f); // 调整角度为右方 transform.position += transform.forward * moveSpeed * Time.deltaTime; // 向前移动 break; case 2: transform.localRotation = Quaternion.Euler(0f, -90f, 0f); // 调整角度为左方 transform.position += transform.forward * moveSpeed * Time.deltaTime; // 向前移动 break; case 3: transform.localRotation = Quaternion.Euler(0f, 180f, 0f); // 调整角度为后方 transform.position += transform.forward * moveSpeed * Time.deltaTime; // 向前移动 break; } if (walkCounter <= 0) // 如果移动时间到达 { stopPosition = new Vector3(transform.position.x, transform.position.y, transform.position.z); // 记录结束时的位置 isWalking = false; // 停止移动 // 停止移动 transform.position = stopPosition; animator.SetBool(hashRandomWalk, false); nextState = Random.Range(0, stateCount); animator.SetInteger(hashRandomIdle, nextState); // 重置等待计时器 waitCounter = waitTime; } } else // 如果没有在移动 { waitCounter -= Time.deltaTime; // 等待计时器减少 if (waitCounter <= 0) // 如果等待时间到达 { ChooseDirection(); // 随机选择方向 } } } public void ChooseDirection() // 随机选择方向 { walkDirection = Random.Range(0, 4); isWalking = true; walkCounter = walkTime; } }
挂载脚本和配置参数,记得添加刚体和碰撞体
效果
添加石头
石头模型
https://assetstore.unity.com/packages/3d/props/exterior/stones-40329
添加碰撞体和刚体
拾取物品
修改InteractableObject代码
public bool isPickUp;//是否可拾取 //拾取物品 public void PickUp(){ Destroy(gameObject); }
石头挂载脚本,配置参数
修改SelectionManager调用拾取功能
//拾取物品 void PickUpItem(Transform selectionTransform) { var interactableObject = selectionTransform.GetComponent<InteractableObject>(); //拾取物品 if (Input.GetKeyDown(KeyCode.E) && interactableObject.isPickUp) { interactableObject.PickUp(); } }
效果(后补)
源码
源码不出意外的话我会放在最后一节