Unity 3D 基础(五)动画、协程与碰撞检测
本篇核心知识点往返巡逻、滚轮控制相机远近、鼠标射线点击移动、动画帧事件、序列帧动画、协程 IEnumerator、协程等待指令、Time.timeScale 对协程影响、碰撞检测三阶段函数、触发器检测三阶段函数、对象池实现与子弹复用、碰撞与触发器区分、协程项目实战场景一、两点往返巡逻 AI 实现1 概念角色在两个目标点位循环往复移动抵达点位后等待固定时长再切换移动目标依靠距离判断是否到达目标通过速度变量控制启停。2 特性 / 规则两点间距离小于 0.5 判定为抵达目标点抵达后停止移动开启计时器等待计时结束切换目标移动时使用世界坐标系平移防止旋转后朝向错乱无父物体坐标干扰纯世界坐标计算位移。3 语法 代码片段坐标距离计算、世界空间平移、计时器累加核心片段// 两点距离计算 float dis Vector3.Distance(transform.position, targetPos); // 世界坐标系移动 transform.Translate(dir * moveSpeed * Time.deltaTime, Space.World); // 计时器累加 timer Time.deltaTime;4 相关知识点对比计时器写法对比Update 持续累加计时器 VS 协程延时等待Update 计时器占用帧循环多逻辑叠加易杂乱协程等待分离延时逻辑无需持续浮点变量。5 模块拓展多点巡逻改造List 存储路径点索引循环切换目标人物朝向优化移动时调用 transform.LookAt 对准目标点位物理角色适配Rigidbody 移动替换 Translate在 FixedUpdate 执行位移。二、鼠标滚轮控制第三人称相机拉近拉远1 概念相机与玩家保持偏移向量通过鼠标滚轮修改相机与角色的距离标量归一化偏移向量重新计算相机位置实现视野缩放并限制最大最小距离防止穿模。2 特性 / 规则初始偏移向量在 Start 一次性记录滚轮增量修改距离使用 Mathf.Clamp 约束距离区间向量 magnitude 获取两点间长度归一化保留方向、修改长度每一帧执行 LookAt 持续看向玩家。3 语法 代码片段向量模长、归一化、滚轮输入、区间限制核心片段// 获取偏移向量长度 float curDis offset.magnitude; // 向量归一化 Vector3 dir offset.normalized; // 读取滚轮输入 float scroll Input.GetAxis(Mouse ScrollWheel); // 数值区间限制 curDis Mathf.Clamp(curDis, minDis, maxDis);4 相关知识点对比直接赋值距离 VS Lerp 缓动距离直接赋值缩放生硬无过渡Lerp 插值画面平滑手感更舒适。5 模块拓展障碍物检测射线检测相机与玩家中间物体自动拉远相机动态灵敏度距离越近滚轮缩放灵敏度降低缩放缓冲Time.deltaTime 平滑滚轮变化幅度。三、鼠标射线点击地面控制人物移动1 概念鼠标左键按下时从主相机发射射线检测地面碰撞层获取点击世界坐标锁定角色 Y 轴高度避免陷地复用巡逻移动逻辑前往点击点位。2 特性 / 规则射线仅检测地面指定 Layer过滤其他物体点击点位仅替换 X、Z 坐标角色 Y 坐标保持不变移动逻辑统一使用世界坐标系平移修正朝向错乱 Bug。3 语法 代码片段屏幕射线生成、层级掩码过滤、坐标锁定 Y 轴片段// 创建屏幕射线 Ray ray Camera.main.ScreenPointToRay(Input.mousePosition); // 层级掩码仅检测地面层 int groundMask 1 LayerMask.NameToLayer(Ground); // 锁定Y轴防止人物陷地 Vector3 moveTarget new Vector3(hit.point.x, transform.position.y, hit.point.z);4 相关知识点对比屏幕坐标转换 VS 射线拾取ScreenToWorldPoint固定 Z 深度无碰撞检测Raycast带碰撞筛选精准拾取地面、物体。5 模块拓展边界判断限制点击范围禁止人物移出地图动画联动移动播放行走动画抵达切换站立NavMesh 寻路替换直接平移自动绕开障碍物。四、动画帧事件 Animation Event1 概念在动画指定关键帧绑定函数动画播放至该帧自动执行对应逻辑解决动画表现与业务逻辑不同步问题如挥刀扣血、技能生成子弹。2 特性 / 规则绑定的脚本必须和 Animator/Animation 挂载在同一个物体高版本 Unity 移除帧事件传参功能低版本支持简单参数传递菱形标识为关键帧向下箭头标识为帧事件标记触发函数无返回值无参数新版。3 语法 代码片段帧事件绑定函数标准写法// 帧事件调用函数必须挂载在带Animator的物体上 public void AttackHit(){ // 打击扣血、生成特效逻辑 }4 相关知识点对比帧事件触发逻辑 VS 代码计时同步动画帧事件精准绑定动画帧无需手动计算动画时长代码计时依赖动画总时长缩放速度后容易错位。5 模块拓展音效同步帧事件调用 AudioSource 播放打击音效粒子生成关键帧实例化打击特效碰撞开关跳跃落地帧开启地面碰撞判定。五、序列帧动画1 概念连续切换多张 Sprite 贴图依靠人眼视觉暂留形成动画效果分为编辑器自动生成动画、纯代码切换贴图两种实现方式。2 特性 / 规则图片资源导入类型设置为 Sprite代码实现依靠计时器按固定间隔切换图片索引取模运算实现贴图数组循环播放。3 语法 代码片段计时器切换 Sprite、循环索引片段// 计时器累加 timer Time.deltaTime; if(timer frameInterval){ // 循环切换贴图索引 curIndex (curIndex 1) % spriteArr.Length; spRenderer.sprite spriteArr[curIndex]; timer 0; }4 相关知识点对比编辑器 Animation 序列帧 VS 代码控制序列帧编辑器快速制作无需代码适合简单循环动效代码控制灵活控制播放、暂停、单次循环适配动态逻辑。5 模块拓展UI 序列帧Image 组件替换 Sprite 实现弹窗动画播放控制布尔变量控制动画暂停 / 播放变速动画根据游戏速度修改帧切换间隔。六、协程 IEnumerator1 概念协程运行在 Unity 主线程可将一段逻辑拆分至多帧执行支持中途暂停、延时恢复用来处理延时、分段执行需求不属于多线程。2 特性 / 规则函数返回值固定为 IEnumerator依靠 yield return 实现中断开启、关闭协程方式必须成对匹配普通 WaitForSeconds 受 Time.timeScale 影响Realtime 不受暂停影响主线程内执行可正常操作 GameObject、Transform 等引擎 API。3 语法 代码片段协程定义、开启、关闭、等待指令片段void Start(){ StartCoroutine(DelayLogic()); } // 协程标准定义 IEnumerator DelayLogic(){ yield return new WaitForSeconds(3f); yield return new WaitForSecondsRealtime(1f); yield return null; } // 开启协程 Coroutine cor StartCoroutine(DelayLogic()); // 关闭指定协程 StopCoroutine(cor); // 关闭物体全部协程 StopAllCoroutines();4 相关知识点对比WaitForSeconds VS WaitForSecondsRealtimeWaitForSeconds跟随游戏时间缩放游戏暂停时等待冻结WaitForSecondsRealtime基于真实系统时间暂停 UI、弹窗动画专用。5 模块拓展带参协程协程函数传入参数动态控制延时、文本嵌套协程yield return StartCoroutine (子协程) 实现多层分段逻辑实战场景抽奖动画延时发放奖励、子弹延时回收、打字机逐字输出。七、碰撞检测与触发器系统1 概念碰撞体是物理边界载体分为实体碰撞阻挡穿透、触发器可穿透仅检测进出各自提供 Enter/Stay/Exit 三阶段回调函数。2 特性 / 规则实体碰撞生效条件双方挂载 Collider至少一方挂载 RigidbodyCollider 取消 Is Trigger。触发器生效条件双方挂载 Collider至少一方挂载 Rigidbody任意一个 Collider 勾选 Is Trigger。核心关系触发器是碰撞体身上的布尔属性同一碰撞体不能同时为碰撞与触发器。3 语法 代码片段碰撞、触发器三阶段回调片段// 实体碰撞回调 private void OnCollisionEnter(Collision col){} private void OnCollisionStay(Collision col){} private void OnCollisionExit(Collision col){} // 触发器回调 private void OnTriggerEnter(Collider other){} private void OnTriggerStay(Collider other){} private void OnTriggerExit(Collider other){}4 相关知识点对比实体碰撞 VS 触发器实体碰撞产生物理阻挡、反弹用于墙体、赛车撞击触发器无物理阻挡用于拾取道具、范围伤害、索敌区域。5 模块拓展间隔持续伤害OnTriggerStay 内搭配协程防止每帧重复扣血层级过滤射线 / 范围探测搭配 LayerMask忽略无关物体近战判定CapsuleCollider 触发器做近距离攻击范围。八、对象池子弹复用1 概念预先缓存游戏物体依靠 SetActive 显隐实现复用减少频繁 Instantiate、Destroy 产生 GC 卡顿大量子弹、投射物场景专用优化方案。2 特性 / 规则使用 List 容器存储所有实例化物体获取物体优先读取池内未激活对象无空闲则新建并存入池子回收物体不销毁仅隐藏等待下次调用搭配协程实现子弹飞行延时自动回收。3 语法 代码片段池子取物、协程延时回收核心片段// 遍历池子获取空闲物体 foreach(var bullet in bulletPool){ if(!bullet.activeSelf){ bullet.SetActive(true); return bullet; } } // 协程延时回收 IEnumerator RecycleObj(GameObject obj){ yield return new WaitForSeconds(flyTime); obj.SetActive(false); }4 相关知识点对比对象池复用 VS 直接实例销毁直接实例销毁大量生成时 GC 频繁帧率波动卡顿对象池仅初始化少量实例无频繁 GC性能稳定。5 模块拓展多类型对象池Dictionary 分类存储不同子弹、道具预制体预加载池子Start 一次性生成固定数量物体运行不动态创建容量限制设置池子最大上限避免内存无限占用。