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

Unity3D RPG游戏开发实战:从零搭建角色与场景交互系统(含源码)

1. Unity3D RPG游戏开发基础准备第一次打开Unity3D时很多人会被复杂的界面吓到。别担心我们先从最基础的设置开始。我建议使用2021 LTS版本这个版本稳定性好社区支持也完善。安装完成后记得在Hub里勾选Windows Build Support和Android Build Support即使你现在不做移动端开发后面可能会用到。创建新项目时选择3D Core模板。我习惯把项目命名为RPG_Demo_[日期]这样方便版本管理。进入编辑器后第一件事就是整理项目结构。右键点击Assets窗口创建以下文件夹Scenes存放游戏场景Scripts存放C#脚本Prefabs存放预制体Materials存放材质Textures存放贴图Animations存放动画控制器提示养成良好命名习惯很重要我见过太多项目因为命名混乱导致后期维护困难。建议使用下划线命名法比如Player_Model.fbx。2. 场景搭建与地形编辑2.1 基础地形创建在Hierarchy面板右键 - 3D Object - Terrain创建地形。我建议先把地形尺寸设为200x200单位这个大小适合大多数RPG游戏的开局区域。在Terrain组件中点击第一个图标设置地形高度第二个图标用于纹理绘制第三个图标用于树木和细节绘制地形时有个小技巧按住Shift键点击可以降低地形直接点击是抬高。纹理绘制时先添加基础草地纹理再叠加泥土和岩石纹理。我通常会创建4-5层纹理通过调整笔刷透明度实现自然过渡。2.2 场景物体布置从Asset Store下载免费的低多边形Low Poly资源包这类资源性能友好且风格统一。布置场景时要注意大型物体山体、建筑先放中型物体树木、岩石次之小型细节花草、碎石最后// 快速随机放置物体的脚本示例 public class ScatterObjects : MonoBehaviour { public GameObject prefab; public int count 50; public float radius 20f; void Start() { for(int i0; icount; i) { Vector3 pos transform.position Random.insideUnitSphere * radius; pos.y Terrain.activeTerrain.SampleHeight(pos); Instantiate(prefab, pos, Quaternion.Euler(0,Random.Range(0,360),0)); } } }3. 角色控制系统实现3.1 角色移动基础首先给角色添加Character Controller组件这比直接用Rigidbody更适合RPG游戏。创建PlayerController脚本public class PlayerController : MonoBehaviour { private CharacterController controller; public float moveSpeed 5f; public float rotationSpeed 10f; void Start() { controller GetComponentCharacterController(); } void Update() { float horizontal Input.GetAxis(Horizontal); float vertical Input.GetAxis(Vertical); Vector3 moveDirection new Vector3(horizontal, 0, vertical); moveDirection transform.TransformDirection(moveDirection); moveDirection * moveSpeed; controller.Move(moveDirection * Time.deltaTime); if(moveDirection ! Vector3.zero) { Quaternion toRotation Quaternion.LookRotation(moveDirection, Vector3.up); transform.rotation Quaternion.Slerp(transform.rotation, toRotation, rotationSpeed * Time.deltaTime); } } }3.2 相机跟随系统创建CameraController脚本实现第三人称跟随public class CameraController : MonoBehaviour { public Transform target; public float distance 5f; public float height 2f; public float damping 5f; void LateUpdate() { Vector3 desiredPosition target.position - target.forward * distance Vector3.up * height; transform.position Vector3.Lerp(transform.position, desiredPosition, Time.deltaTime * damping); transform.LookAt(target); } }4. 交互系统实现4.1 触发检测基础交互系统是RPG游戏的核心。我们先实现最基本的宝箱交互给宝箱添加Box Collider勾选Is Trigger创建Interactable脚本public class Interactable : MonoBehaviour { public GameObject interactionUI; public Animator chestAnimator; private bool canInteract false; void OnTriggerEnter(Collider other) { if(other.CompareTag(Player)) { interactionUI.SetActive(true); canInteract true; } } void OnTriggerExit(Collider other) { if(other.CompareTag(Player)) { interactionUI.SetActive(false); canInteract false; } } void Update() { if(canInteract Input.GetKeyDown(KeyCode.E)) { chestAnimator.SetTrigger(Open); // 这里可以添加物品掉落逻辑 } } }4.2 对话系统实现创建DialogueTrigger脚本public class DialogueTrigger : MonoBehaviour { public Dialogue dialogue; public GameObject dialogueUI; void OnTriggerEnter(Collider other) { if(other.CompareTag(Player)) { dialogueUI.SetActive(true); FindObjectOfTypeDialogueManager().StartDialogue(dialogue); } } }配套的DialogueManager脚本public class DialogueManager : MonoBehaviour { public Text nameText; public Text dialogueText; private Queuestring sentences; void Start() { sentences new Queuestring(); } public void StartDialogue(Dialogue dialogue) { nameText.text dialogue.name; sentences.Clear(); foreach(string sentence in dialogue.sentences) { sentences.Enqueue(sentence); } DisplayNextSentence(); } public void DisplayNextSentence() { if(sentences.Count 0) { EndDialogue(); return; } string sentence sentences.Dequeue(); StopAllCoroutines(); StartCoroutine(TypeSentence(sentence)); } IEnumerator TypeSentence(string sentence) { dialogueText.text ; foreach(char letter in sentence.ToCharArray()) { dialogueText.text letter; yield return null; } } void EndDialogue() { dialogueUI.SetActive(false); } }5. 敌人AI与战斗系统5.1 基础敌人AI创建EnemyAI脚本实现巡逻和追击public class EnemyAI : MonoBehaviour { public Transform[] patrolPoints; public float moveSpeed 3f; public float chaseSpeed 5f; public float chaseDistance 10f; public float attackDistance 2f; private int currentPoint 0; private Transform player; private bool isChasing false; void Start() { player GameObject.FindGameObjectWithTag(Player).transform; } void Update() { float distanceToPlayer Vector3.Distance(transform.position, player.position); if(distanceToPlayer chaseDistance) { isChasing true; } else { isChasing false; } if(isChasing) { if(distanceToPlayer attackDistance) { transform.position Vector3.MoveTowards(transform.position, player.position, chaseSpeed * Time.deltaTime); transform.LookAt(player); } else { // 攻击逻辑 } } else { Patrol(); } } void Patrol() { if(Vector3.Distance(transform.position, patrolPoints[currentPoint].position) 0.5f) { currentPoint (currentPoint 1) % patrolPoints.Length; } transform.position Vector3.MoveTowards(transform.position, patrolPoints[currentPoint].position, moveSpeed * Time.deltaTime); transform.LookAt(patrolPoints[currentPoint].position); } }5.2 简单战斗系统创建CombatSystem脚本public class CombatSystem : MonoBehaviour { public float attackRange 2f; public int attackDamage 10; public float attackCooldown 1f; private float lastAttackTime 0f; public LayerMask enemyLayer; void Update() { if(Input.GetMouseButtonDown(0) Time.time lastAttackTime attackCooldown) { Attack(); lastAttackTime Time.time; } } void Attack() { RaycastHit hit; if(Physics.Raycast(transform.position, transform.forward, out hit, attackRange, enemyLayer)) { EnemyHealth enemyHealth hit.collider.GetComponentEnemyHealth(); if(enemyHealth ! null) { enemyHealth.TakeDamage(attackDamage); } } } }配套的EnemyHealth脚本public class EnemyHealth : MonoBehaviour { public int maxHealth 30; private int currentHealth; public GameObject deathEffect; void Start() { currentHealth maxHealth; } public void TakeDamage(int damage) { currentHealth - damage; if(currentHealth 0) { Die(); } } void Die() { Instantiate(deathEffect, transform.position, Quaternion.identity); Destroy(gameObject); } }6. 项目优化与扩展6.1 性能优化技巧使用Occlusion Culling减少渲染负担对远处物体使用LODLevel of Detail系统合并静态物体使用Static Batching使用对象池管理频繁创建销毁的对象// 对象池示例 public class ObjectPool : MonoBehaviour { public GameObject prefab; public int initialSize 10; private QueueGameObject pool new QueueGameObject(); void Start() { for(int i0; iinitialSize; i) { GameObject obj Instantiate(prefab); obj.SetActive(false); pool.Enqueue(obj); } } public GameObject GetObject() { if(pool.Count 0) { GameObject obj pool.Dequeue(); obj.SetActive(true); return obj; } else { return Instantiate(prefab); } } public void ReturnObject(GameObject obj) { obj.SetActive(false); pool.Enqueue(obj); } }6.2 存档系统实现创建简单的存档系统public class SaveSystem : MonoBehaviour { public static void SaveGame(Vector3 playerPosition, int playerHealth) { PlayerPrefs.SetFloat(PlayerPosX, playerPosition.x); PlayerPrefs.SetFloat(PlayerPosY, playerPosition.y); PlayerPrefs.SetFloat(PlayerPosZ, playerPosition.z); PlayerPrefs.SetInt(PlayerHealth, playerHealth); PlayerPrefs.Save(); } public static (Vector3, int) LoadGame() { float x PlayerPrefs.GetFloat(PlayerPosX, 0); float y PlayerPrefs.GetFloat(PlayerPosY, 0); float z PlayerPrefs.GetFloat(PlayerPosZ, 0); int health PlayerPrefs.GetInt(PlayerHealth, 100); return (new Vector3(x,y,z), health); } }在实际项目中我发现最常遇到的问题就是角色卡在场景物体之间。解决这个问题的方法是给角色控制器添加一个小的物理材质设置适当的摩擦力。另外触发器事件有时会意外触发多次我通常会在脚本中添加一个简单的冷却计时器来解决这个问题。

相关文章:

Unity3D RPG游戏开发实战:从零搭建角色与场景交互系统(含源码)

1. Unity3D RPG游戏开发基础准备 第一次打开Unity3D时,很多人会被复杂的界面吓到。别担心,我们先从最基础的设置开始。我建议使用2021 LTS版本,这个版本稳定性好,社区支持也完善。安装完成后,记得在Hub里勾选"Wi…...

喜马拉雅音频下载终极指南:免费解锁付费内容的桌面神器

喜马拉雅音频下载终极指南:免费解锁付费内容的桌面神器 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 你是否曾因网络…...

ARM P-Channel接口设计与低功耗SoC电源管理实践

1. ARM P-Channel接口深度解析在低功耗SoC设计中,电源管理接口的可靠性和时序一致性直接决定了系统的能效表现。ARM P-Channel作为专为电源管理设计的标准化接口协议,通过独特的四阶段握手机制,为设备与电源控制器之间建立了高效的状态协商通…...

基于Orange Pi 5 Plus与DEEPX栈的边缘AI部署实战指南

1. 项目概述:当一块开发板遇见AI大潮最近在深圳参加了一场关于人工智能硬件与边缘计算的行业峰会,感触颇深。会上,一款基于Orange Pi 5 Plus开发板打造的DEEPX人工智能产品,实实在在地吸引了我的目光。这不仅仅是又一款“开发板AI…...

L298N驱动模块进阶玩法:用Arduino实现直流电机的软启动、缓停与速度曲线控制

L298N驱动模块进阶玩法:用Arduino实现直流电机的软启动、缓停与速度曲线控制 在创客和嵌入式开发领域,直流电机的控制是基础但至关重要的技能。大多数初学者会从简单的正反转和调速开始,但当项目需要更精细的运动控制时,粗暴的启…...

从狼群狩猎到参数调优:GWO算法在机器学习超参数搜索中的保姆级指南

从狼群狩猎到参数调优:GWO算法在机器学习超参数搜索中的保姆级指南 在机器学习项目的最后阶段,我们常常会陷入超参数优化的泥潭。网格搜索耗时费力,随机搜索像买彩票,而贝叶斯优化又过于复杂。这时候,一群来自大自然的…...

水文水资源、水生态与水环境领域必修技能暨 ArcGIS Pro全流程实践技术学习及AI融合应用

ArcGIS Pro 是一款集数据采集、处理、分析和可视化于一体的强大 GIS 工具,广泛应用于水文、水资源、水生态和水环境等领域。其全面的功能使得研究人员能够高效地处理各种水文和环境数据,从而为科学研究和决策支持提供强有力的技术保障。在水文分析方面&a…...

Exception in thread “main“ java.lang.Error: Unresolved compilation problem:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 八股文面试,平时啊,开发遇到什么问题 没编译过去的提示信息...

前端转行网络安全 漏洞挖掘赚钱前景分析

前言 最近,一个做运维的朋友跟我说他在学渗透测试。他说,公司请别人做渗透测试的费用是 2千/人天,一共2周。2周 2w 的收入,好香~ 于是,我也对渗透测试产生了兴趣。开始了探索之路~ 什么是渗透测试 渗透测试这名字听…...

Node.js框架深度解析:从Express到Nest.js,如何选择最适合你的Web开发框架?

1. 项目概述:为什么Node.js框架值得你花时间研究?如果你是一名Web开发者,或者正在向这个方向转型,那么“Node.js框架”这个词组对你来说一定不陌生。但面对市面上林林总总的框架,从Express、Koa到Nest.js、Fastify&…...

周末短途游成新风尚,家门口也能遇见诗与远方

如今生活节奏不断加快,长时间的长途旅行对很多人来说成了一种奢望,周末短途游便顺势走进大众生活,成为越来越多人放松身心的选择。不必提前很久规划行程,不用纠结复杂的交通攻略,甚至不用打包厚重的行李,只…...

紧急更新!Perplexity v3.2作家索引逻辑变更后,3小时内必须掌握的4项适配策略

更多请点击: https://kaifayun.com 第一章:Perplexity作家信息搜索 Perplexity 是一款以实时网络检索与引用溯源为特色的 AI 搜索工具,其“作家信息搜索”能力并非依赖静态数据库,而是通过动态解析权威出版平台(如 Su…...

iOS激活锁终极绕过指南:5分钟免费解锁iPhone完整方案

iOS激活锁终极绕过指南:5分钟免费解锁iPhone完整方案 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 对于拥有二手iPhone却卡在激活锁界面的用户来说,applera1n提供了一个专业、…...

Vue3 + Element Plus 项目里,用ECharts 5.4.3做个动态数据大屏(附完整代码)

Vue3 Element Plus 与 ECharts 5.4.3 构建企业级动态数据大屏实战 数据可视化大屏已成为现代企业监控业务指标、分析趋势的核心工具。本文将深入探讨如何基于最新的 Vue3 和 Element Plus 技术栈,结合 ECharts 5.4.3 的强大可视化能力,构建一个高性能、…...

Google I/O 2026 推出 Antigravity SDK:本地构建 AI Agent,灵活定制功能

Antigravity SDK 登场当开发者需要将 AI 能力嵌入自有应用时,常见做法是通过 API 调用远程 Agent 服务,但这种方式存在延迟高、定制性差、依赖网络等问题。据悉,Google 在 I/O 2026 大会上给出了另一种解法 ---- Antigravity SDK,…...

OAuth 接入DeepSeek总失败?这3类JWT签名验证错误正在 silently 拒绝你的请求,速查!

更多请点击: https://kaifayun.com 第一章:OAuth 接入DeepSeek总失败?这3类JWT签名验证错误正在 silently 拒绝你的请求,速查! 当你调用 DeepSeek 的 OAuth 2.0 接口(如 /v1/auth/token)时&am…...

Linux ISP驱动全流程解析:从V4L2框架到图像处理管线

1. 项目概述:从用户按下快门到ISP驱动当我们用手机或相机拍照时,屏幕上那个“咔嚓”的动画和瞬间生成的图片,背后是一场从物理世界到数字世界的精密“接力赛”。这场接力赛的第一棒是镜头和传感器,它们负责捕捉光线。但传感器输出…...

STM32MP25x嵌入式Linux平台:集成XFCE、VNC、TSN的工业边缘计算解决方案

1. 项目概述:一个面向工业边缘的“瑞士军刀”级嵌入式平台最近,我们团队基于STM32MP25x系列核心板,成功构建并发布了一套完整的Debian系统镜像。这个项目的目标非常明确:打造一个开箱即用、功能全面、且能无缝覆盖从传统工业控制到…...

为什么顶级策展人不用Google搜文化新闻?Perplexity文化垂直搜索的5层语义增强架构(含可复用prompt工程模板)

更多请点击: https://kaifayun.com 第一章:为什么顶级策展人不用Google搜文化新闻? 顶级策展人并非排斥搜索引擎,而是早已构建起一套高度结构化、语义化、可验证的信息摄取系统——它绕过关键词匹配的偶然性,直击文化…...

YOLOv5实战解析——激活函数的选择与调优

1. 激活函数在YOLOv5中的核心作用 第一次接触YOLOv5时,我被它的检测精度惊艳到了。但真正让我困惑的是:为什么同样的网络结构,换个激活函数效果就天差地别?后来在调试一个工业质检项目时,我才彻底明白激活函数的重要性…...

终极免费窗口强制调整工具:如何突破Windows尺寸限制

终极免费窗口强制调整工具:如何突破Windows尺寸限制 【免费下载链接】WindowResizer 一个可以强制调整应用程序窗口大小的工具 项目地址: https://gitcode.com/gh_mirrors/wi/WindowResizer 还在为那些无法拖拽的"顽固窗口"而烦恼吗?Wi…...

2026研发效能工具全景评测:Gitee Insight在DevSecOps赛道的差异化分析

核心结论:本研究基于功能覆盖、安全集成、数据分析、私有化部署等维度,对Gitee Insight、腾讯Cloud Studio DevOps及阿里Codeup三款主流研发效能工具进行了系统评测。研究结果表明,三款产品在定位与能力上呈现显著分化:Gitee Insi…...

OriginPro 2023 相关性热图插件 CorrelationPlot 保姆级安装与配置指南(附资源下载)

OriginPro 2023 CorrelationPlot插件全流程配置指南:从零基础到高效科研可视化 科研数据处理中,相关性热图(Correlation Plot)是揭示变量间关联强度的利器。对于非编程背景的研究者而言,OriginPro的CorrelationPlot插件…...

CTF实战:从ZIP伪加密到二进制文件结构解析

1. ZIP伪加密:CTF中的经典陷阱 第一次参加CTF比赛时,我遇到一个看似简单的MISC题目——解压一个加密的ZIP文件。当时我花了整整两小时尝试各种密码爆破工具,直到队友提醒我:"这可能是伪加密"。这个经历让我深刻认识到&…...

如何在3分钟内搭建Excel MCP Server:无需安装Microsoft Excel的终极指南

如何在3分钟内搭建Excel MCP Server:无需安装Microsoft Excel的终极指南 【免费下载链接】excel-mcp-server A Model Context Protocol server for Excel file manipulation 项目地址: https://gitcode.com/gh_mirrors/ex/excel-mcp-server 还在为没有Micros…...

你的动漫图片为什么总是不够清晰?3个步骤让AI帮你还原4K级画质

你的动漫图片为什么总是不够清晰?3个步骤让AI帮你还原4K级画质 【免费下载链接】Real-ESRGAN Real-ESRGAN aims at developing Practical Algorithms for General Image/Video Restoration. 项目地址: https://gitcode.com/gh_mirrors/re/Real-ESRGAN 想象一…...

别再死记硬背了!用NestJS + TypeORM实战‘用户-标签’系统,搞懂OneToMany和ManyToOne

NestJS TypeORM实战:构建高可维护的用户标签系统 在开发内容管理平台时,用户与标签的关联关系是典型的多对一建模场景。本文将带你从零实现一个基于NestJS和TypeORM的生产级用户标签系统,重点解析OneToMany和ManyToOne在实际项目中的最佳实践…...

告别Blob分析:Halcon差异化模型在复杂印刷品检测中的降本增效实践

工业视觉新范式:Halcon差异化模型在精密印刷检测中的实战突破 印刷品质量检测一直是工业视觉领域的硬骨头——那些微米级的墨点缺失、毫厘间的字符偏移,以及生产线上的光影变幻,都在挑战传统算法的极限。当Blob分析遇上多印漏印、位置飘移、…...

用NE555和LM324做个红外倒车雷达:从仿真到焊接,一个模电新手的踩坑实录

从零打造红外倒车雷达:NE555与LM324实战手记 第一次拿起电烙铁时,我的手抖得像风中的芦苇。作为电子工程专业的大二学生,模电课的理论公式在面包板上变成了一团乱麻。直到导师建议我尝试做个红外倒车雷达——这个结合了振荡电路、信号放大和电…...

华硕笔记本性能管家G-Helper:告别臃肿控制中心,重获系统掌控权

华硕笔记本性能管家G-Helper:告别臃肿控制中心,重获系统掌控权 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vi…...