当前位置: 首页 > news >正文

Unity 实验功能实现:天敌捕食猎物(含对象池 + 点击交互)

        在虚拟仿真项目开发中,经常需要实现类似 天敌捕食猎物 的交互实验功能。本文将介绍如何用 Unity 实现一个完整的 猎物生成 + 捕食控制 + 点击反馈 的系统,并结合对象池、事件回调等常见开发技巧,最终实现高效可复用的实验功能。

🎯 功能需求

  • 猎物批量生成:按照配置数量生成猎物,避免重复 Instantiate 带来的性能消耗。

  • 点击反馈:用户点击猎物时,触发缩放动画等视觉反馈。

  • 猎物回收:猎物被捕食后自动回收,复用到对象池中。

  • 天敌控制:不同的天敌(Predator)可通过按钮触发捕食行为。

  • 实验流程演示:支持点击交互、提示信息清除与重新开始。


🧩 核心脚本实现

下面展示几个主要的脚本(均已加上详细备注,便于理解和学习)。

1. IHuntable 接口(猎物通用规范)

/// <summary>
/// 可捕食对象接口(猎物基类接口)
/// 用于解耦 PredatorController 与具体的猎物实现。
/// 所有猎物(如 PreyController)必须实现该接口,才能被天敌识别和捕食。
/// </summary>
public interface IHuntable
{/// <summary>/// 当猎物被点击时调用/// - 负责触发点击反馈(例如高亮、闪烁、缩放等视觉效果)。/// - 由猎物自身实现,保证不同猎物可以有不同反馈。/// </summary>void OnClicked();/// <summary>/// 重置猎物状态(对象池复用时调用)/// - 用于恢复初始状态,例如位置、颜色、动画状态等。/// - 避免频繁销毁/实例化造成性能浪费。/// </summary>void ResetPrey();/// <summary>/// 第一次被点击的时间(秒)/// - 用于统计和记录捕食数据。/// - 由实现类维护(通常在第一次 OnClicked 时赋值)。/// - PredatorController 在 ConsumePrey 时可以读取该值,用于分析。/// </summary>float FirstClickTime { get; }
}

👉 这样可以保证所有“猎物”类都有统一的点击与回收逻辑。


2. Prey.cs(猎物类,负责点击与反馈)

using UnityEngine;
using UnityEngine.EventSystems;
using System;
using System.Collections;/// <summary>
/// Prey 脚本:
/// - 实现了 IHuntable(可捕猎接口)和 IPointerClickHandler(UI点击接口)
/// - 提供点击反馈(缩放动画)
/// - 支持对象池回收(ResetPrey)
/// - 提供点击时间记录(FirstClickTime)
/// </summary>
[RequireComponent(typeof(Collider))] // 确保物体身上有 Collider,用于鼠标/点击检测
public class Prey : MonoBehaviour, IHuntable, IPointerClickHandler
{/// <summary>/// 静态事件:当任意 Prey 被点击时触发/// 外部可以通过订阅 OnPreyClicked 来获取点击的 Prey 对象/// </summary>public static event Action<Prey> OnPreyClicked;/// <summary>/// 第一次被点击的时间(记录点击时间点)/// -1 表示未点击过/// </summary>public float FirstClickTime { get; private set; } = -1f;[Header("点击视觉反馈")][Tooltip("点击时缩放比例")]public float clickScale = 1.3f; [Tooltip("反馈持续时间(秒)")]public float feedbackDuration = 0.15f;/// <summary>/// 原始缩放,用于恢复大小/// </summary>private Vector3 _originalScale;/// <summary>/// 是否已经被点击过/// </summary>private bool _isClicked = false;private void Awake(){// 确保物体带有 Collider(否则点击检测无效)if (GetComponent<Collider>() == null)gameObject.AddComponent<BoxCollider>();// 记录初始缩放_originalScale = transform.localScale;}#region IHuntable 实现/// <summary>/// 当猎物被点击时调用/// - 记录点击时间/// - 标记为已点击/// - 播放点击反馈动画/// </summary>public void OnClicked(){if (!_isClicked){FirstClickTime = Time.time; // 记录点击时间_isClicked = true;          // 防止重复记录}// 停止所有可能的点击反馈协程(避免叠加)StopAllCoroutines();StartCoroutine(ClickFeedback());}/// <summary>/// 点击视觉反馈协程/// - 等待一段时间后恢复原始缩放/// </summary>private IEnumerator ClickFeedback(){// 点击瞬间放大transform.localScale = _originalScale * clickScale;// 等待指定时间yield return new WaitForSeconds(feedbackDuration);// 恢复原始缩放transform.localScale = _originalScale;}/// <summary>/// 对象池回收时重置猎物状态/// - 恢复缩放/// - 重置点击状态/// - 重新激活对象/// </summary>public void ResetPrey(){_isClicked = false;FirstClickTime = -1f;transform.localScale = _originalScale;gameObject.SetActive(true);}#endregion#region 点击事件/// <summary>/// UI 点击接口实现(支持 EventSystem 点击)/// </summary>public void OnPointerClick(PointerEventData eventData) => TriggerClick();/// <summary>/// 鼠标点击事件(非 UI 点击,也能触发)/// </summary>private void OnMouseDown() => TriggerClick();/// <summary>/// 触发点击逻辑:/// - 先广播事件(通知外部)/// - 再执行自身的点击反馈/// </summary>private void TriggerClick(){OnPreyClicked?.Invoke(this); // 通知外部有 Prey 被点击OnClicked();                 // 播放反馈效果}#endregion
}

👉 该脚本负责猎物点击后的反馈(缩放效果)和回收逻辑。


3. InsertAnimation.cs(捕食动画配置)

using UnityEngine;
using System;/// <summary>
/// InsertAnimation
/// —— 用于配置“天敌”与其相关的动画、猎物生成信息
/// —— 作为数据容器供 PredatorController 使用
/// </summary>
[Serializable] // 可序列化,能在 Inspector 中显示
public class InsertAnimation
{[Header("配置名称(唯一标识)")][Tooltip("该配置的唯一名称标识,例如:'七星瓢虫配置',用于区分不同天敌的设置")]public string name;[Header("天敌对象")][Tooltip("天敌在场景中的 GameObject,例如:七星瓢虫的模型对象")]public GameObject mainHunter;[Header("猎物生成的父物体")][Tooltip("猎物生成时的父级 Transform,方便统一管理猎物位置与层级")]public Transform root;[Header("猎物预制体")][Tooltip("猎物的预制体(Prefab),用于实例化新的猎物对象")]public Prey preyPrefab;[Header("天敌爬行动画")][Tooltip("天敌的 Animation 组件,用于播放移动、捕食等动画")]public Animation predatorAni;
}

👉 通过 ScriptableObject 或 Inspector 配置不同天敌及其动画效果。


4.PredatorController.cs(天敌控制器)

using UnityEngine;
using System.Collections.Generic;
using TMPro;
using System.Globalization;
using Random = UnityEngine.Random;/// <summary>
/// 天敌控制器(PredatorController)
/// 功能:
/// 1. 控制天敌捕食猎物的过程(包含点击触发、移动路径、捕食逻辑)
/// 2. 支持对象池,减少频繁创建/销毁 Prey 对象
/// 3. 提供捕食关系表(可扩展,不同天敌对应不同猎物)
/// 4. 显示提示信息(如耗时)
/// </summary>
public class PredatorController : MonoBehaviour
{[Header("天敌配置")][Tooltip("插入的动画和猎物配置(Prefab、动画、根节点等)")]public InsertAnimation config;[Header("移动参数")][Tooltip("天敌最小移动速度")]public float minSpeed = 0.1f;[Tooltip("天敌最大移动速度")]public float maxSpeed = 0.2f;private float _speed; // 当前速度public bool isMove;        // 是否正在移动private int _moveStep;     // 当前移动阶段private Vector3 _targetPos; // 当前目标位置private Vector3[] _targetPath; // 天敌移动的路径点数组private int _maxPathPoints;    // 路径点数量private int _nowOpt;           // 当前路径点索引private Prey _clickPrey;       // 被点击的猎物(天敌追逐目标)private float _timeUsed; // 捕食过程耗时// 管理 Prey 的对象池private readonly List<Prey> _preyList = new(); // 当前活跃的猎物列表private readonly Queue<Prey> _preyPool = new(); // 可复用的猎物对象池/// <summary>/// 捕食关系表(可扩展:天敌种类 -> 可捕食的猎物列表)/// 示例: predatorPreyTable["七星瓢虫"] = new List<string> { "蚜虫", "白粉虱" };/// </summary>public Dictionary<string, List<string>> predatorPreyTable = new();private void OnEnable(){// 订阅 Prey 点击事件Prey.OnPreyClicked += HandlePreyClicked;}private void OnDisable(){// 取消订阅,避免内存泄漏Prey.OnPreyClicked -= HandlePreyClicked;}/// <summary>/// 开始狩猎,生成指定数量的猎物/// </summary>public void BeginHunt(int count){_preyList.Clear();_speed = Random.Range(minSpeed, maxSpeed); // 随机速度_maxPathPoints = Random.Range(2, 6);       // 随机路径点数量// 对象池生成猎物for (var i = 0; i < count; i++){Prey prey;if (_preyPool.Count > 0){// 从池中取出已有的猎物prey = _preyPool.Dequeue();prey.ResetPrey();}else{// 池中没有,则实例化新的猎物prey = Instantiate(config.preyPrefab, config.root);}// 随机放置猎物位置prey.transform.localPosition = new Vector3(Random.Range(-0.2f, 0.2f),0,Random.Range(-0.2f, 0.2f));_preyList.Add(prey);prey.gameObject.SetActive(true);}// 重置状态_timeUsed = 0;_moveStep = 0;isMove = false;TipManager.instance.ClearTip();}/// <summary>/// 处理猎物点击事件/// </summary>private void HandlePreyClicked(Prey prey){if (isMove) return;              // 如果天敌正在移动,不响应if (!_preyList.Contains(prey)) return; // 必须是当前活跃猎物_clickPrey = prey;_targetPos = prey.transform.localPosition;// 生成移动路径_targetPath = GetPath(_maxPathPoints, config.mainHunter.transform.localPosition, _targetPos);// 进入移动状态isMove = true;_nowOpt = 0;_moveStep = 0;// 播放天敌移动动画config.predatorAni["七星瓢虫-爬"].speed = 5;config.predatorAni.Play("七星瓢虫-爬");}private void Update(){if (config != null)MainFlow();}/// <summary>/// 天敌移动与捕食主流程/// </summary>private void MainFlow(){if (!isMove) return;var frameMove = Time.deltaTime * _speed; // 当前帧的移动步长Vector3 nextPos;switch (_moveStep){// 阶段 0:天敌沿路径移动,追逐点击的猎物case 0:{_timeUsed += Time.deltaTime;nextPos = _targetPath[_nowOpt];// 移动天敌MoveHunter(nextPos, frameMove);// 如果到达路径点if (config.mainHunter.transform.localPosition == nextPos){_nowOpt++;// 到达终点,进入捕食阶段if (_nowOpt >= _targetPath.Length){_moveStep = 1;ConsumePrey(_clickPrey);return;}}// 显示用时(取两位小数)TipManager.instance.ShowTip((Mathf.Round(_timeUsed * 100f) / 100f).ToString());break;}// 阶段 1:没有猎物了,停止case 1 when _preyList.Count == 0:isMove = false;config.predatorAni.Stop();return;// 阶段 1:继续追逐下一个猎物case 1:{nextPos = _preyList[0].transform.localPosition;MoveHunter(nextPos, frameMove);if (config.mainHunter.transform.localPosition == nextPos){ConsumePrey(_preyList[0]);}break;}}}/// <summary>/// 控制天敌移动(位置 + 朝向)/// </summary>private void MoveHunter(Vector3 target, float moveStep){var pos = config.mainHunter.transform.localPosition;// 移动到目标位置config.mainHunter.transform.localPosition = Vector3.MoveTowards(pos, target, moveStep);// 平滑旋转,朝向目标config.mainHunter.transform.localRotation = Quaternion.Lerp(config.mainHunter.transform.localRotation,Quaternion.LookRotation(target - pos),5f * Time.deltaTime);}/// <summary>/// 捕食猎物:从列表移除并回收到对象池/// </summary>private void ConsumePrey(Prey prey){if (_preyList.Contains(prey))_preyList.Remove(prey);prey.gameObject.SetActive(false); // 隐藏_preyPool.Enqueue(prey);          // 回收进对象池// 输出调试信息Debug.Log($"捕食 {prey.name},首次捕食时间 {prey.FirstClickTime}");}/// <summary>/// 生成路径点(起点 → 终点,中间有随机扰动)/// </summary>private static Vector3[] GetPath(int count, Vector3 start, Vector3 end){var path = new Vector3[count];var dx = Mathf.Abs(start.x - end.x) / (count + 1);var dy = Mathf.Abs(start.y - end.y) / (count + 1);var dz = Mathf.Abs(start.z - end.z) / (count + 1);// 逐点生成路径for (var i = 0; i < path.Length - 1; i++){path[i].x = start.x >= end.x ? start.x - (i + 1) * dx : start.x + (i + 1) * dx;path[i].y = start.y >= end.y ? start.y - (i + 1) * dy : start.y + (i + 1) * dy;path[i].z = start.z >= end.z ? start.z - (i + 1) * dz : start.z + (i + 1) * dz;}// 最后一个点是终点path[^1] = end;// 给中间点加一些随机偏移(避免路径完全直线)for (var i = 0; i < path.Length - 1; i++)path[i].x += Random.Range(-0.3f, 0.3f);return path;}
}

👉 PredatorController天敌的行为控制器,负责处理猎物点击后的捕食流程,包括移动路径规划、动画驱动、猎物消耗与回收。


5. HuntManager.cs(整体捕食控制)

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;/// <summary>
/// 天敌信息数据类
/// —— 绑定 UI 启动按钮 和 对应的天敌控制器
/// —— 用于在 HuntManager 中统一管理多个天敌
/// </summary>
[Serializable] // 可序列化,能在 Inspector 中显示
public class PredatorInfo
{[Header("开始按钮")][Tooltip("点击该按钮后,启动对应的天敌捕食流程")]public Button startButton;[Header("天敌控制器")][Tooltip("该按钮绑定的天敌控制器对象(PredatorController 脚本)")]public PredatorController predatorController;
}/// <summary>
/// HuntManager
/// —— 捕食管理器
/// —— 主要负责:
/// 1. 绑定按钮点击事件与天敌的捕食逻辑
/// 2. 控制猎物数量
/// 3. 调用 PredatorController 来启动捕食流程
/// </summary>
public class HuntManager : MonoBehaviour
{[Header("猎物数量")][Tooltip("每次点击按钮后,生成的猎物数量")]public int preyCount = 10;[Header("天敌信息列表")][Tooltip("所有需要控制的天敌信息(按钮 + 天敌控制器的绑定关系)")]public List<PredatorInfo> predators;/// <summary>/// 初始化时执行/// —— 遍历所有天敌信息,将按钮点击事件与对应的 StartHunt() 绑定/// </summary>private void Start(){foreach (var info in predators.Where(info => info.startButton != null && info.predatorController != null)){// 给每个按钮添加点击事件,启动对应天敌的捕食逻辑info.startButton.onClick.AddListener(() =>{StartHunt(info.predatorController);});}}/// <summary>/// 启动某个天敌的捕食流程/// —— 会重置其状态,并生成猎物/// </summary>/// <param name="predator">指定的天敌控制器</param>private void StartHunt(PredatorController predator){// 1. 停止天敌的移动与动画predator.isMove = false;if (predator.config != null && predator.config.predatorAni != null){predator.config.predatorAni.Stop();}// 2. 清空提示信息TipManager.instance.ClearTip();// 3. 启动捕食逻辑(生成猎物并进入捕食状态)predator.BeginHunt(preyCount);}
}

👉 HuntManager 是核心调度器,负责启动猎物生成和捕食逻辑。


6.TipManager.cs(提示管理器)

using TMPro;
using UnityEngine;/// <summary>
/// TipManager —— 全局提示文本管理器
/// 用于在实验过程中显示或清空提示信息(例如捕食计时、提示文字)。
/// 采用单例模式,方便在其他脚本中通过 TipManager.instance 调用。
/// </summary>
public class TipManager : MonoBehaviour
{/// <summary>/// 静态单例引用,保证全局只有一个 TipManager。/// 其他脚本可通过 TipManager.instance 快速访问。/// </summary>public static TipManager instance;[Header("共用提示文本")]/// <summary>/// UI 上用于显示提示信息的 TMP_Text 组件。/// 可以在 Inspector 中绑定,例如场景中的 TextMeshProUGUI。/// </summary>public TMP_Text tipText;/// <summary>/// Unity 生命周期方法 —— 脚本实例化时调用。/// 设置单例引用,并初始化提示文本为空。/// </summary>private void Awake(){instance = this;if (tipText != null)tipText.text = "";}/// <summary>/// 显示提示信息。/// 在运行时调用该方法可更新提示文本内容。/// </summary>/// <param name="msg">需要显示的提示内容</param>public void ShowTip(string msg){if (tipText != null)tipText.text = msg;}/// <summary>/// 清空提示文本。/// 例如在重新开始实验或捕食流程结束时调用。/// </summary>public void ClearTip(){if (tipText != null)tipText.text = "";}
}

👉 TipManager负责界面提示(第一次捕食时间)。


⚙️脚本挂载:

1.创建一个名为【天敌捕食管理器】的空物体,挂载【HuntManager.cs】和【TipManager.cs

        在天敌信息列表中配置,创建一个按钮启动捕食功能,将创建好的【Predator】拖给按钮对应的天敌控制器,实现按钮与天敌的一对一控制。确保天敌上有爬行动画,否则注释对应的爬行动画功能。

2.创建一个名为【Predator】的空物体,挂载【PredatorController.cs】

3.猎物预制体上需要挂载【Prey.cs】,确保预制体上有【BoxCollider】组件用于交互。


🐞天敌捕食流程图:展示了 天敌启动 → 猎物生成 → 点击反馈 → 动画捕食 → 回收复用 的完整流程

HuntManager(按钮启动)│▼
PredatorController.BeginHunt()│▼
生成猎物(Prey对象池)│
点击猎物 → Prey.OnClicked()│                 ▲▼                 │
PredatorController.HandlePreyClicked()│
动画捕食(config.predatorAni)│▼
ConsumePrey() → 回收到对象池│▼
TipManager(提示更新)

🖼️ 效果演示

  1. 点击“开始捕食”按钮,指定天敌出动。

  2. 在场景中生成多个猎物(对象池管理)。

  3. 玩家可点击生成的猎物,触发缩放反馈及捕食行为。

  4. 天敌执行捕食动画,会记录第一次捕食所用的时间,待全部捕食完成。


💡 技术要点总结

  • 对象池复用:避免频繁销毁/实例化,提高性能。

  • 接口抽象:通过 IHuntable 保证所有猎物都有统一的交互逻辑。

  • 事件驱动:使用 OnPreyClicked,避免直接耦合逻辑,方便扩展。

  • UI 控制 + 场景交互结合:按钮启动天敌 → 猎物生成 → 点击反馈 → 动画播放,完整闭环。


🚀 应用场景

该功能可以应用于:

  • 虚拟仿真教学(如食物链、生态实验)。

  • 游戏开发(捕猎玩法、反应力测试)。

  • 交互式科普展示。


📌 总结

通过本文,我们实现了一个完整的 天敌捕食猎物实验功能,涉及 UI 控制、对象池、点击反馈、动画控制 等多个常见开发要素。这不仅能直接应用到虚拟仿真实验中,也能为其他类似交互玩法提供参考。


文章转载自:

http://U5pOW1Z3.cwjsz.cn
http://uHo6OGLt.cwjsz.cn
http://NMJn1AxG.cwjsz.cn
http://f1CBTwTj.cwjsz.cn
http://hVzTQY8o.cwjsz.cn
http://OawMHyX6.cwjsz.cn
http://1EckkCsO.cwjsz.cn
http://zMvWIwuK.cwjsz.cn
http://usQ8ppoy.cwjsz.cn
http://ieFlrbEB.cwjsz.cn
http://Z8QaSEgB.cwjsz.cn
http://Egd5LTRa.cwjsz.cn
http://NDzXGGeT.cwjsz.cn
http://xGjhpzoC.cwjsz.cn
http://5EzOH63d.cwjsz.cn
http://R2if1fvb.cwjsz.cn
http://0RKVf5t7.cwjsz.cn
http://pcB2wcKc.cwjsz.cn
http://01ofj8oh.cwjsz.cn
http://jbnUzZKS.cwjsz.cn
http://LzdcF0dy.cwjsz.cn
http://WwDZiZfb.cwjsz.cn
http://CwYxRigj.cwjsz.cn
http://O97aRVEH.cwjsz.cn
http://axVGUamW.cwjsz.cn
http://cbr11AKr.cwjsz.cn
http://DFaKS0zx.cwjsz.cn
http://6UpX1tYZ.cwjsz.cn
http://K1YwCZ4m.cwjsz.cn
http://CUzprXET.cwjsz.cn
http://www.dtcms.com/a/387638.html

相关文章:

  • 【docker】——docker国内可用的源
  • React Zustand存储token报错解决方案
  • I/O 多路复用器(select、poll、epoll)与 Reactor 模式详解
  • pytorch自定义算子转tensorrt
  • Springboots上传文件的同时传递参数用对象接收
  • Next.js 中表单处理与校验:React Hook Form 实战
  • 国标GB28181视频平台EasyGBS如何解决安防视频融合与级联管理的核心痛点?
  • Web 页面 SEO 审计自动化 - 基于 n8n 和 Firecrawl
  • arcgis文件导出显示导出对象错误
  • PPT中将图片按比例裁剪
  • React + Zustand 状态管理
  • 复位开关芯片 EY412-A07E50国产低功耗延时芯片方案超低功耗
  • 动态规划-详解回文串系列问题
  • C语言基础学习(五)——进制
  • 如何在C#中将 Excel 文件(XLS/XLSX)转换为 PDF
  • 【Error】django-debug-toolbar不显示:Failed to load module script
  • Windows 版本 WDK 版本 Windows SDK Visual Studio各版本对应关系
  • WPF 快速布局技巧
  • K8S YAML 功能详解:让容器配置更灵活
  • CAD迷你看图下载安装教程(2025最新版)
  • 根据文本区域`textarea`的内容调整大小`field-sizing:content`
  • avcodec_send_packet闪退问题
  • ftrace的trace_marker使用
  • ★基于FPGA的通信基础链路开发项目汇集目录
  • SpringBoot中@Value注入失败问题解决
  • DotCore进程CPU飙高跟踪处理方案
  • PantherX2黑豹X2 armbian 编译rkmpp ffmpeg 实现CPU视频转码
  • 2、Logstash与FileBeat详解以及ELK整合详解(Logstash安装及简单实战使用)
  • ENVI系列教程(六)——自动采集控制点的 RPC 正射校正
  • 多可见光线索引导的热红外无人机图像超分辨率重建