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

告别枯燥理论!用Unity脚本生命周期与预制体玩转一个“会变身的敌人”

用Unity打造会变身的敌人脚本生命周期与预制体的实战应用在游戏开发中敌人AI的行为设计往往是新手开发者最感兴趣也最容易感到困惑的部分。Unity的脚本生命周期和预制体系统为这类需求提供了强大支持但教科书式的讲解常常让学习者陷入枯燥的理论泥潭。本文将带你通过一个会变身的敌人案例在实战中掌握这些核心概念。1. 项目准备与基础设置首先创建一个新的3D项目命名为ShapeShiftingEnemy。在Hierarchy中创建一个Plane作为地面并添加一个Directional Light保证场景光照。接着创建一个Capsule作为玩家角色为其添加Character Controller组件以便移动控制。玩家控制脚本如下public class PlayerController : MonoBehaviour { private CharacterController controller; public float moveSpeed 5f; void Start() { controller GetComponentCharacterController(); } void Update() { float horizontal Input.GetAxis(Horizontal); float vertical Input.GetAxis(Vertical); Vector3 move new Vector3(horizontal, 0, vertical); controller.SimpleMove(move * moveSpeed); } }接下来创建敌人预制体在场景中创建一个Sphere命名为BaseEnemy为其添加Rigidbody组件取消勾选Use Gravity创建EnemyController脚本并附加到Sphere上将整个Sphere拖入Project窗口的Prefabs文件夹创建预制体2. 敌人行为的状态设计我们的敌人将根据与玩家距离变换三种形态警戒形态距离10米缓慢移动黄色外观追击形态距离5-10米快速移动红色外观狂暴形态距离5米闪现移动黑色外观并带有粒子特效首先在EnemyController脚本中定义状态枚举和基础变量public enum EnemyState { Alert, Chase, Berserk } [SerializeField] private EnemyState currentState; private Transform playerTransform; private Renderer enemyRenderer; private float stateChangeCooldown 1f; private float lastStateChangeTime;3. 脚本生命周期的实战应用Unity的脚本生命周期方法是我们控制敌人行为的关键。在EnemyController中实现核心方法void Awake() { enemyRenderer GetComponentRenderer(); Debug.Log(Enemy awakened - 初始化组件); } void OnEnable() { playerTransform GameObject.FindGameObjectWithTag(Player).transform; Debug.Log(Enemy activated - 获取玩家引用); } void Start() { currentState EnemyState.Alert; UpdateAppearance(); Debug.Log(Enemy ready - 初始状态设置); } void Update() { if(Time.time lastStateChangeTime stateChangeCooldown) { CheckDistanceToPlayer(); } MoveAccordingToState(); } void OnDisable() { Debug.Log(Enemy deactivated - 清理资源); } void OnDestroy() { Debug.Log(Enemy destroyed - 最终清理); }提示生命周期方法的执行顺序非常重要。Awake最早调用适合组件初始化OnEnable在每次激活时调用Start在首次帧更新前调用一次。4. 状态切换与外观更新实现状态检测和外观变化逻辑void CheckDistanceToPlayer() { float distance Vector3.Distance(transform.position, playerTransform.position); EnemyState newState distance 5f ? EnemyState.Berserk : distance 10f ? EnemyState.Chase : EnemyState.Alert; if(newState ! currentState) { currentState newState; UpdateAppearance(); lastStateChangeTime Time.time; } } void UpdateAppearance() { switch(currentState) { case EnemyState.Alert: enemyRenderer.material.color Color.yellow; break; case EnemyState.Chase: enemyRenderer.material.color Color.red; break; case EnemyState.Berserk: enemyRenderer.material.color Color.black; // 狂暴状态特效将在下一节实现 break; } }5. 预制体变体的高级应用为了让狂暴状态更震撼我们将使用预制体变体(Prefab Variant)在Project窗口右键BaseEnemy预制体选择Create Variant命名为BerserkEnemy打开BerserkEnemy变体添加Particle System组件配置粒子系统为黑色烟雾效果在EnemyController中添加变体生成逻辑public GameObject berserkVariant; private GameObject currentVariant; void SpawnBerserkVariant() { if(currentVariant ! null) return; currentVariant Instantiate(berserkVariant, transform.position, transform.rotation); currentVariant.transform.SetParent(transform); Destroy(GetComponentRenderer()); } void RevertToBaseForm() { if(currentVariant null) return; Destroy(currentVariant); enemyRenderer gameObject.AddComponentRenderer(); UpdateAppearance(); }在UpdateAppearance方法中补充变体切换void UpdateAppearance() { switch(currentState) { // ...其他状态处理 case EnemyState.Berserk: SpawnBerserkVariant(); break; default: RevertToBaseForm(); // ...其他状态颜色设置 break; } }6. 不同状态的移动行为为敌人添加符合各状态特点的移动方式public float alertSpeed 2f; public float chaseSpeed 5f; public float berserkSpeed 8f; public float berserkTeleportInterval 3f; private float lastTeleportTime; void MoveAccordingToState() { switch(currentState) { case EnemyState.Alert: PatrolRandomly(); break; case EnemyState.Chase: ChasePlayer(); break; case EnemyState.Berserk: if(Time.time lastTeleportTime berserkTeleportInterval) { TeleportTowardsPlayer(); } else { ChasePlayer(); } break; } } void PatrolRandomly() { // 简单随机巡逻逻辑 transform.Translate(Vector3.forward * alertSpeed * Time.deltaTime); if(Random.value 0.01f) { transform.Rotate(0, Random.Range(-90, 90), 0); } } void ChasePlayer() { Vector3 direction (playerTransform.position - transform.position).normalized; float speed currentState EnemyState.Chase ? chaseSpeed : berserkSpeed; transform.Translate(direction * speed * Time.deltaTime); } void TeleportTowardsPlayer() { Vector3 randomOffset Random.insideUnitSphere * 3f; randomOffset.y 0; transform.position playerTransform.position - (playerTransform.forward * 2f) randomOffset; lastTeleportTime Time.time; }7. 敌人受伤与死亡处理完善敌人的生命系统和死亡动画public int maxHealth 100; private int currentHealth; public GameObject deathEffect; void Start() { currentHealth maxHealth; // ...其他初始化 } public void TakeDamage(int damage) { currentHealth - damage; if(currentHealth 0) { Die(); } else { StartCoroutine(FlashDamage()); } } IEnumerator FlashDamage() { Color originalColor currentState EnemyState.Berserk ? Color.black : currentState EnemyState.Chase ? Color.red : Color.yellow; enemyRenderer.material.color Color.white; yield return new WaitForSeconds(0.1f); enemyRenderer.material.color originalColor; } void Die() { Instantiate(deathEffect, transform.position, Quaternion.identity); Destroy(gameObject); }为死亡效果创建一个新的预制体创建Particle System配置为爆炸效果添加Audio Source播放死亡音效创建DeathEffect脚本控制效果持续时间public class DeathEffect : MonoBehaviour { public float lifetime 2f; void Start() { Destroy(gameObject, lifetime); } }8. 完整敌人控制脚本整合所有功能的完整EnemyControllerusing UnityEngine; public class EnemyController : MonoBehaviour { public enum EnemyState { Alert, Chase, Berserk } [Header(状态设置)] public EnemyState currentState; public GameObject berserkVariant; public float stateChangeCooldown 1f; [Header(移动参数)] public float alertSpeed 2f; public float chaseSpeed 5f; public float berserkSpeed 8f; public float berserkTeleportInterval 3f; [Header(战斗属性)] public int maxHealth 100; public GameObject deathEffect; private Transform playerTransform; private Renderer enemyRenderer; private GameObject currentVariant; private int currentHealth; private float lastStateChangeTime; private float lastTeleportTime; void Awake() { enemyRenderer GetComponentRenderer(); } void OnEnable() { playerTransform GameObject.FindGameObjectWithTag(Player).transform; } void Start() { currentState EnemyState.Alert; currentHealth maxHealth; UpdateAppearance(); } void Update() { if(Time.time lastStateChangeTime stateChangeCooldown) { CheckDistanceToPlayer(); } MoveAccordingToState(); } void CheckDistanceToPlayer() { float distance Vector3.Distance(transform.position, playerTransform.position); EnemyState newState distance 5f ? EnemyState.Berserk : distance 10f ? EnemyState.Chase : EnemyState.Alert; if(newState ! currentState) { currentState newState; UpdateAppearance(); lastStateChangeTime Time.time; } } void UpdateAppearance() { switch(currentState) { case EnemyState.Alert: RevertToBaseForm(); enemyRenderer.material.color Color.yellow; break; case EnemyState.Chase: RevertToBaseForm(); enemyRenderer.material.color Color.red; break; case EnemyState.Berserk: SpawnBerserkVariant(); break; } } void SpawnBerserkVariant() { if(currentVariant ! null) return; currentVariant Instantiate(berserkVariant, transform.position, transform.rotation); currentVariant.transform.SetParent(transform); Destroy(GetComponentRenderer()); } void RevertToBaseForm() { if(currentVariant null) return; Destroy(currentVariant); enemyRenderer gameObject.AddComponentRenderer(); } void MoveAccordingToState() { switch(currentState) { case EnemyState.Alert: PatrolRandomly(); break; case EnemyState.Chase: ChasePlayer(); break; case EnemyState.Berserk: if(Time.time lastTeleportTime berserkTeleportInterval) { TeleportTowardsPlayer(); } else { ChasePlayer(); } break; } } void PatrolRandomly() { transform.Translate(Vector3.forward * alertSpeed * Time.deltaTime); if(Random.value 0.01f) { transform.Rotate(0, Random.Range(-90, 90), 0); } } void ChasePlayer() { Vector3 direction (playerTransform.position - transform.position).normalized; float speed currentState EnemyState.Chase ? chaseSpeed : berserkSpeed; transform.Translate(direction * speed * Time.deltaTime); } void TeleportTowardsPlayer() { Vector3 randomOffset Random.insideUnitSphere * 3f; randomOffset.y 0; transform.position playerTransform.position - (playerTransform.forward * 2f) randomOffset; lastTeleportTime Time.time; } public void TakeDamage(int damage) { currentHealth - damage; if(currentHealth 0) { Die(); } else { StartCoroutine(FlashDamage()); } } IEnumerator FlashDamage() { Color originalColor currentState EnemyState.Berserk ? Color.black : currentState EnemyState.Chase ? Color.red : Color.yellow; if(enemyRenderer ! null) { enemyRenderer.material.color Color.white; yield return new WaitForSeconds(0.1f); enemyRenderer.material.color originalColor; } } void Die() { Instantiate(deathEffect, transform.position, Quaternion.identity); Destroy(gameObject); } void OnDrawGizmos() { Gizmos.color Color.red; Gizmos.DrawWireSphere(transform.position, 5f); Gizmos.color Color.yellow; Gizmos.DrawWireSphere(transform.position, 10f); } }9. 玩家攻击系统的实现为了让玩家能够攻击敌人我们需要实现简单的攻击系统创建Attack脚本附加到玩家角色public class Attack : MonoBehaviour { public float attackRange 3f; public int attackDamage 20; public KeyCode attackKey KeyCode.Space; void Update() { if(Input.GetKeyDown(attackKey)) { TryAttack(); } } void TryAttack() { RaycastHit hit; if(Physics.Raycast(transform.position, transform.forward, out hit, attackRange)) { EnemyController enemy hit.collider.GetComponentEnemyController(); if(enemy ! null) { enemy.TakeDamage(attackDamage); } } } }为玩家添加攻击动画可选导入攻击动画资源设置Animator Controller添加攻击状态在Attack脚本中触发动画播放10. 项目优化与扩展思路完成基础功能后我们可以考虑以下优化和扩展性能优化使用对象池管理敌人实例优化粒子系统的性能消耗实现敌人的LOD细节层次系统功能扩展添加更多变身形态隐身、分裂等实现敌人的团队协作AI添加特殊技能冷却系统设计变身状态下的特殊攻击方式视觉效果增强使用Shader实现更炫酷的变身效果添加状态转换时的过渡动画实现基于物理的布料模拟这个会变身的敌人案例展示了Unity核心概念在实际开发中的综合应用。通过将脚本生命周期与预制体系统结合我们创造出了富有动态变化的敌人行为远比静态敌人更有挑战性和趣味性。

相关文章:

告别枯燥理论!用Unity脚本生命周期与预制体玩转一个“会变身的敌人”

用Unity打造会变身的敌人:脚本生命周期与预制体的实战应用在游戏开发中,敌人AI的行为设计往往是新手开发者最感兴趣也最容易感到困惑的部分。Unity的脚本生命周期和预制体系统为这类需求提供了强大支持,但教科书式的讲解常常让学习者陷入枯燥…...

【DeepSeek集成测试黄金标准】:20年专家亲授5大避坑指南与自动化落地框架

更多请点击: https://intelliparadigm.com 第一章:DeepSeek集成测试黄金标准的演进与核心价值 集成测试在大语言模型工程化落地过程中已从“验证功能可用”跃迁为“保障推理一致性、上下文鲁棒性与安全边界的三位一体质量门禁”。DeepSeek系列模型&…...

紧急预警:DeepSeek代码生成中未公开的3类逻辑漂移现象(附自动化检测脚本+修复模板)

更多请点击: https://intelliparadigm.com 第一章:紧急预警:DeepSeek代码生成中未公开的3类逻辑漂移现象(附自动化检测脚本修复模板) 近期在多轮生产级代码审计中发现,DeepSeek-R1(v2.5&#x…...

Windows Cleaner:终极免费系统清理工具,彻底解决C盘空间不足问题

Windows Cleaner:终极免费系统清理工具,彻底解决C盘空间不足问题 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服! 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 你是否经常遇到C盘爆红、…...

03 - 变量与数据类型

03 - 变量与数据类型 变量是编程里最基础的概念,相当于你往电脑里存东西的"容器"。这章我们把变量的命名规则、Python 的几种基本数据类型都过一遍。 变量是什么 说白了,变量就是一个有名字的盒子。你往里面放个东西,以后想用这个…...

DAIR-V2X-V数据集深度评测:与KITTI、nuScenes比,它到底强在哪?

DAIR-V2X-V数据集深度评测:与KITTI、nuScenes比,它到底强在哪? 当技术团队着手开发面向中国道路的自动驾驶系统时,数据集的选择往往成为第一个关键决策点。过去十年间,KITTI和nuScenes等国际数据集一直是行业标杆&…...

用Python复现Nature论文:仅需100次循环数据,提前预测锂电池寿命(附完整代码与数据集)

用Python实战预测锂电池寿命:从数据特征到模型部署全解析锂电池作为现代能源存储的核心组件,其寿命预测一直是工业界和学术界关注的焦点。传统方法往往需要等待电池出现明显容量衰减才能进行判断,而最新研究表明,通过分析早期循环…...

实战对比:用直方图均衡化与CLAHE拯救你的背光/过曝照片(附Python完整代码)

拯救逆光废片:直方图均衡化与CLAHE的实战效果对比每次旅行回来整理照片时,总会有几张因为光线问题几乎要删除的废片——要么是逆光下的人脸黑得看不清五官,要么是天空过曝失去所有云层细节。这些照片往往记录着重要时刻,直接删除实…...

OpenRASP原理与实战:Java应用层实时防护技术详解

1. 为什么我宁愿花三天部署OpenRASP,也不愿再写第五个自定义WAF过滤器去年冬天,我在给一家做在线教育SaaS平台做安全加固时,连续踩了三个坑:第一次用NginxLua写了套SQL注入规则,结果学生提交的“SELECT * FROM courses…...

在模型广场灵活选型让我找到了更适合代码生成的Taotoken模型

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 在模型广场灵活选型让我找到了更适合代码生成的Taotoken模型 开发代码辅助工具时,选择合适的模型是平衡效果与成本的关…...

Claude端到端测试设计终极清单:覆盖17类非功能需求(含延迟敏感度分级、幻觉熔断阈值、多轮对话状态持久化验证)

更多请点击: https://kaifayun.com 第一章:Claude端到端测试设计的演进逻辑与核心范式 Claude端到端测试并非静态产物,而是随模型能力边界拓展、交互场景复杂化及可靠性要求升级而持续演化的工程实践。其演进逻辑根植于三个关键张力&#xf…...

从模糊到电影级景深:Midjourney + Topaz Gigapixel联调方案(含LUT预设包+PSD分层模板)

更多请点击: https://codechina.net 第一章:从模糊到电影级景深:Midjourney Topaz Gigapixel联调方案(含LUT预设包PSD分层模板) 当Midjourney生成的图像存在主体边缘柔化、背景层次缺失或分辨率不足等问题时&#xf…...

用图神经网络做缺陷定位,准确率比传统方法高出30%

在现代软件工程的复杂迷宫中,缺陷定位始终是测试团队面临的核心挑战。想象这样一个场景:一个电商系统在特定压力条件下偶发订单丢失,日志中只留下泛泛的超时错误,问题可能深藏在上百个微服务的调用链、分布式事务的竞态条件或某个…...

工业云脑:06 现在就能干:树莓派边缘盒子+PLC,10分钟缺陷检测小案例

06 现在就能干:树莓派边缘盒子+PLC,10分钟缺陷检测小案例 今天第九篇06小节——现在就能干:树莓派边缘盒子+PLC,10分钟缺陷检测小案例。新手照着做10分钟就能跑起来,老手一看就知道这玩意儿省了多少钱。以前想上AI检测,得花几万块买专业边缘盒子;现在?树莓派5(RPi 5)…...

多模型聚合平台如何助力网站AIB测试与选型

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 多模型聚合平台如何助力网站AIB测试与选型 对于网站产品经理而言,首页文案的生成质量直接影响用户的第一印象和转化率。…...

Android Root检测绕过:从逆向分析到Frida分层Hook实战

1. 这不是“绕过root检测”,而是理解检测逻辑后的精准干预在安卓逆向工程的实际工作中,“过root检测”这个说法本身就容易引发误解——它听起来像某种黑箱魔法,仿佛只要套用某个脚本、加载某个插件,就能让App对设备状态“视而不见…...

HiveWE终极指南:快速掌握魔兽争霸III现代化地图编辑器

HiveWE终极指南:快速掌握魔兽争霸III现代化地图编辑器 【免费下载链接】HiveWE A Warcraft III world editor. 项目地址: https://gitcode.com/gh_mirrors/hi/HiveWE 还在为传统魔兽争霸III地图编辑器缓慢的加载速度和复杂的操作界面而烦恼吗?Hiv…...

JWT弱密钥爆破实战:从HS256签名原理到CTF权限提升

1. 这不是密码学考试,而是一场“密钥猜谜”实战JWT(JSON Web Token)在现代Web系统中早已不是可选项,而是默认配置。登录成功后返回一串形如eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsIm5hbWUiOiLnlKjliYkiLCJpYX…...

万星easy-vibe:描述需求即发布 零基础无需学语法

开源Easy-Vibe是一套开源AI编程学习方案,把学习顺序从先学语法再做项目翻转为直接做项目。文章拆解了项目驱动、提示词编写、AI编辑器和多Agent协作的完整流程,解释了为什么想法比语法更重要。 github上datawhalechina/easy-vibe:它在GitHub…...

LoRa物联网与动态基线算法在养殖体温监测中的实战应用

1. 项目概述:为什么我们需要一个智能体温监测系统?在规模化养殖场里干了十几年,我见过太多因为体温异常没被及时发现而导致的损失。一头育肥猪突然不吃食,等饲养员第二天巡栏发现时,可能已经高烧好几天,继发…...

因果推断与机器学习融合:量化分析社会运动中镇压与抗议的动态关系

1. 项目概述:当数据科学遇见社会运动如果你研究过社会运动,尤其是那些看似突然爆发、席卷全国的抗议浪潮,你可能会被一个核心问题困扰:国家机器的镇压,究竟是浇灭火焰的冷水,还是火上浇油的催化剂&#xff…...

NanaZip:现代Windows文件压缩问题的终极解决方案

NanaZip:现代Windows文件压缩问题的终极解决方案 【免费下载链接】NanaZip The 7-Zip derivative intended for the modern Windows experience 项目地址: https://gitcode.com/gh_mirrors/na/NanaZip 还在为Windows文件压缩工具界面老旧、功能单一而烦恼吗&…...

总线式智能提示灯系统设计:从恒流驱动到模块化架构

1. 项目概述:从传统到智能的剧场提示灯系统革新在剧场、演播室或者大型活动现场的后台,如果你待过,一定对那套“红灯停,绿灯行”的提示灯系统不陌生。导演或舞台监督通过对讲机喊“Standby”(准备)&#xf…...

Elden Ring帧率解锁终极指南:从60帧到144+的完整教程

Elden Ring帧率解锁终极指南:从60帧到144的完整教程 【免费下载链接】EldenRingFpsUnlockAndMore A small utility to remove frame rate limit, change FOV, add widescreen support and more for Elden Ring 项目地址: https://gitcode.com/gh_mirrors/el/Elden…...

LeagueAkari:英雄联盟终极自动化助手革命性指南

LeagueAkari:英雄联盟终极自动化助手革命性指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 你是否在英雄联盟游戏中反复经历这…...

通过Taotoken实现Hermes Agent自定义模型供应商接入

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过Taotoken实现Hermes Agent自定义模型供应商接入 Hermes Agent是一个流行的AI智能体开发框架,它支持通过配置自定义…...

PvZ Toolkit终极指南:三步掌握植物大战僵尸最强修改器

PvZ Toolkit终极指南:三步掌握植物大战僵尸最强修改器 【免费下载链接】pvztoolkit 植物大战僵尸 PC 版综合修改器 项目地址: https://gitcode.com/gh_mirrors/pv/pvztoolkit PvZ Toolkit是一款专为植物大战僵尸PC版设计的综合修改器工具,能够让你…...

微信小程序项目实战:从npm安装Vant Weapp到解决样式冲突的完整避坑指南

微信小程序工程化实战:Vant Weapp集成与样式冲突解决方案全解析 第一次在小程序里引入Vant Weapp时,我对着满屏错位的组件样式发呆了半小时——原本优雅的按钮变成了扭曲的色块,表单元素叠在一起像抽象画。这不是个例,根据社区反…...

DeepSeek代码风格检查避坑指南(内部审计报告首次披露:37个被忽略的合规红线)

更多请点击: https://intelliparadigm.com 第一章:DeepSeek代码风格检查的合规性本质与审计背景 DeepSeek代码风格检查并非单纯的技术偏好约束,而是嵌入研发治理链条中的合规性控制节点。其本质是将编程实践与组织级安全策略、行业监管要求&…...

网飞成立 AI 动画工作室,开启流媒体“原生 AI 制片时代”,中外布局逻辑有何不同?

1. Netflix“偷跑”在影视巨头关于 AIGC 的军备竞赛中,Netflix 再次加速。据外媒 TheVerge 报道,网飞于今年 3 月成立了名为 "INKubator" 的工作室,这是全球流媒体巨头中首个以生成式人工智能为核心的动画制作部门。此动作引发全球…...