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

第八天 AI开发:NavMesh导航系统 对话系统:使用ScriptableObject存储对话数据 存档系统:JSON序列化保存数据

一、智能导航系统:NavMesh实战指南

1.1 导航网格基础配置

  1. 在Unity编辑器中:

    • 选择场景中的静态物体
    • 勾选Navigation Static属性
    • 打开Window > AI > Navigation窗口
  2. 烘焙参数设置:

    NavMeshBuildSettings settings = NavMesh.GetSettingsByID(0);
    settings.agentRadius = 0.5f;    // 代理半径
    settings.agentHeight = 2.0f;    // 代理高度
    settings.agentSlope = 45;       // 最大坡度
    NavMeshBuilder.BuildNavMeshAsync(settings);
    

1.2 NavMeshAgent组件控制

public class NPCMovement : MonoBehaviour
{public Transform target;private NavMeshAgent agent;void Start(){agent = GetComponent<NavMeshAgent>();agent.speed = 3.5f;       // 移动速度agent.angularSpeed = 360;  // 旋转速度agent.stoppingDistance = 1f; // 停止距离}void Update(){if(target != null){agent.SetDestination(target.position);// 到达目标后执行动作if(!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance){OnReachDestination();}}}void OnReachDestination(){// 触发对话或执行其他逻辑}
}

1.3 动态障碍物处理

// 动态添加障碍物
NavMeshObstacle obstacle = gameObject.AddComponent<NavMeshObstacle>();
obstacle.shape = NavMeshObstacleShape.Capsule;
obstacle.carving = true;  // 实时更新导航网格
obstacle.size = new Vector3(1f, 2f, 1f);

二、对话系统:ScriptableObject高级应用

2.1 对话数据结构设计

[CreateAssetMenu(fileName = "New Dialogue", menuName = "Dialogue System/Dialogue")]
public class DialogueData : ScriptableObject
{[System.Serializable]public class DialogueNode{public string speakerName;[TextArea(3,5)] public string content;public DialogueOption[] options;}[System.Serializable]public class DialogueOption{public string optionText;public DialogueData nextDialogue;}public DialogueNode[] dialogueNodes;
}

2.2 对话管理器实现

public class DialogueManager : MonoBehaviour
{public static DialogueManager Instance;public Text speakerText;public Text contentText;public GameObject[] optionButtons;private DialogueData currentDialogue;private int currentNodeIndex;void Awake(){Instance = this;HideDialogue();}public void StartDialogue(DialogueData dialogue){currentDialogue = dialogue;currentNodeIndex = 0;ShowDialogue();DisplayNode(currentDialogue.dialogueNodes[currentNodeIndex]);}void DisplayNode(DialogueData.DialogueNode node){speakerText.text = node.speakerName;contentText.text = node.content;for(int i=0; i<optionButtons.Length; i++){if(i < node.options.Length){optionButtons[i].SetActive(true);optionButtons[i].GetComponentInChildren<Text>().text = node.options[i].optionText;}else{optionButtons[i].SetActive(false);}}}public void SelectOption(int optionIndex){DialogueData.DialogueOption selectedOption = currentDialogue.dialogueNodes[currentNodeIndex].options[optionIndex];if(selectedOption.nextDialogue != null){StartDialogue(selectedOption.nextDialogue);}else{HideDialogue();}}
}

三、游戏存档:JSON序列化实战

3.1 存档数据结构设计

[System.Serializable]
public class SaveData
{public Vector3 playerPosition;public Quaternion playerRotation;public string currentScene;public Dictionary<string, bool> completedQuests = new Dictionary<string, bool>();// JSON序列化辅助方法public string ToJson(){return JsonUtility.ToJson(this);}public void LoadFromJson(string json){JsonUtility.FromJsonOverwrite(json, this);}
}

3.2 存档管理器实现

public class SaveSystem : MonoBehaviour
{private static string SAVE_PATH => Path.Combine(Application.persistentDataPath, "save.sav");public static void SaveGame(){SaveData data = new SaveData();// 收集需要保存的数据GameObject player = GameObject.FindGameObjectWithTag("Player");data.playerPosition = player.transform.position;data.playerRotation = player.transform.rotation;data.currentScene = SceneManager.GetActiveScene().name;// 序列化并加密存储string json = data.ToJson();byte[] encryptedData = Encrypt(json);File.WriteAllBytes(SAVE_PATH, encryptedData);}public static bool LoadGame(){if(File.Exists(SAVE_PATH)){byte[] encryptedData = File.ReadAllBytes(SAVE_PATH);string json = Decrypt(encryptedData);SaveData data = new SaveData();data.LoadFromJson(json);// 应用加载的数据SceneManager.LoadScene(data.currentScene);GameObject player = GameObject.FindGameObjectWithTag("Player");player.transform.position = data.playerPosition;player.transform.rotation = data.playerRotation;return true;}return false;}private static byte[] Encrypt(string data){// 实现AES加密逻辑return Encoding.UTF8.GetBytes(data);}private static string Decrypt(byte[] data){// 实现AES解密逻辑return Encoding.UTF8.GetString(data);}
}

四、综合实践:完整游戏系统搭建

4.1 第三人称角色控制升级版

public class AdvancedThirdPersonController : MonoBehaviour
{[Header("Movement")]public float moveSpeed = 5f;public float sprintMultiplier = 1.5f;public float jumpForce = 5f;[Header("Camera")]public CinemachineVirtualCamera followCamera;private CharacterController controller;private Vector3 moveDirection;private float verticalVelocity;void Start(){controller = GetComponent<CharacterController>();Cursor.lockState = CursorLockMode.Locked;}void Update(){HandleMovement();HandleCamera();}void HandleMovement(){float horizontal = Input.GetAxis("Horizontal");float vertical = Input.GetAxis("Vertical");bool isSprinting = Input.GetKey(KeyCode.LeftShift);Vector3 forward = followCamera.transform.forward;Vector3 right = followCamera.transform.right;forward.y = 0f;right.y = 0f;Vector3 move = forward.normalized * vertical + right.normalized * horizontal;float speed = isSprinting ? moveSpeed * sprintMultiplier : moveSpeed;if(controller.isGrounded){verticalVelocity = -0.5f;if(Input.GetButtonDown("Jump")){verticalVelocity = jumpForce;}}else{verticalVelocity += Physics.gravity.y * Time.deltaTime;}move.y = verticalVelocity;controller.Move(move * speed * Time.deltaTime);}void HandleCamera(){float mouseX = Input.GetAxis("Mouse X");float mouseY = Input.GetAxis("Mouse Y");transform.Rotate(Vector3.up * mouseX * 2f);followCamera.transform.RotateAround(transform.position, transform.right, -mouseY * 2f);}
}

4.2 系统集成示例

public class GameManager : MonoBehaviour
{public DialogueData startDialogue;public Transform npcDestination;void Start(){// 加载存档if(SaveSystem.LoadGame()){Debug.Log("存档加载成功");}else{// 新游戏初始化StartCoroutine(StartNewGame());}}IEnumerator StartNewGame(){yield return new WaitForSeconds(1f);DialogueManager.Instance.StartDialogue(startDialogue);// NPC开始移动NPCMovement npc = FindObjectOfType<NPCMovement>();npc.target = npcDestination;}void OnApplicationQuit(){SaveSystem.SaveGame();}
}

五、调试与优化技巧

5.1 NavMesh调试工具

void OnDrawGizmos()
{if(Application.isPlaying){NavMeshAgent agent = GetComponent<NavMeshAgent>();Gizmos.color = Color.red;Gizmos.DrawLine(transform.position, agent.destination);// 显示路径NavMeshPath path = agent.path;for(int i=0; i<path.corners.Length-1; i++){Gizmos.DrawLine(path.corners[i], path.corners[i+1]);}}
}

5.2 存档系统安全增强

  1. 数据校验机制:
    public class SaveData
    {public string checksum;public void GenerateChecksum(){checksum = CalculateMD5(JsonUtility.ToJson(this));}public bool Validate(){string temp = checksum;checksum = "";string current = CalculateMD5(JsonUtility.ToJson(this));checksum = temp;return current == temp;}
    }
    

5.3 对话系统性能优化

  1. 对象池技术实现:
    public class DialoguePool : MonoBehaviour
    {public GameObject optionPrefab;private Queue<GameObject> pool = new Queue<GameObject>();public GameObject GetOption(){if(pool.Count > 0){return pool.Dequeue();}return Instantiate(optionPrefab);}public void ReturnOption(GameObject option){option.SetActive(false);pool.Enqueue(option);}
    }
    

结语

通过本教程的学习,我们实现了从角色控制到AI行为、从交互系统到数据管理的完整开发流程。建议进行以下扩展练习:

  1. 实现多语言对话系统
  2. 添加NPC巡逻路径功能
  3. 开发云存档系统
  4. 制作任务进度追踪界面

相关文章:

第八天 AI开发:NavMesh导航系统 对话系统:使用ScriptableObject存储对话数据 存档系统:JSON序列化保存数据

一、智能导航系统&#xff1a;NavMesh实战指南 1.1 导航网格基础配置 在Unity编辑器中&#xff1a; 选择场景中的静态物体勾选Navigation Static属性打开Window > AI > Navigation窗口 烘焙参数设置&#xff1a; NavMeshBuildSettings settings NavMesh.GetSettingsBy…...

Spring AI Alibaba-02-多轮对话记忆、持久化消息记录

Spring AI Alibaba-02-多轮对话记忆、持久化消息记录 Lison <dreamlison163.com>, v1.0.0, 2025.04.19 文章目录 Spring AI Alibaba-02-多轮对话记忆、持久化消息记录多轮对话对话持久-Redis 本次主要聚焦于多轮对话功能的实现&#xff0c;后续会逐步增加更多实用内容&…...

联邦元学习实现个性化物联网的框架

随着数据安全和隐私保护相关法律法规的出台&#xff0c;需要直接在中央服务器上收集和处理数据的集中式解决方案&#xff0c;对于个性化物联网而言&#xff0c;训练各种特定领域场景的人工智能模型已变得不切实际。基于此&#xff0c;中山大学&#xff0c;南洋理工大学&#xf…...

做虚拟化应该怎么选择美国服务器?

选择适合做虚拟化的美国服务器&#xff0c;需要综合考虑硬件性能、网络质量、稳定性、价格和服务支持等多个方面。以下是详细的选购指南&#xff0c;适合准备搭建VPS、虚拟主机、分销业务、开发测试环境、容器集群等用途的用户参考。 一、为什么美国服务器适合虚拟化? 美国机房…...

实验1 温度转换与输入输出强化

知识点&#xff1a;input()/print()、分支语句、字符串处理&#xff08;教材2.1-2.2&#xff09; 实验任务&#xff1a; 1. 实现摄氏温度与华氏温度互转&#xff08;保留两位小数&#xff09; 2. 扩展功能&#xff1a;输入错误处理&#xff08;如非数字输入提示重新输入&#x…...

MongoDB 集合名称映射问题

项目场景 在使用 Spring Data MongoDB 进行开发时&#xff0c;定义了一个名为 CompetitionSignUpLog 的实体类&#xff0c;并创建了对应的 Repository 接口。需要明确该实体类在 MongoDB 中实际对应的集合名称是 CompetitionSignUpLog 还是 competitionSignUpLog。 问题描述 …...

【AI】SpringAI 第五弹:接入千帆大模型

1. 添加依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-qianfan</artifactId> </dependency> 2. 编写 yml 配置文件 spring:ai:qianfan:api-key: 你的api-keysecret-key: 你的secr…...

【编码规范】原生开发 与 Vue+组件库开发

原生开发 vs Vue组件库开发对比 一、原生开发常用方法 DOM操作&#xff1a; document.getElementById()document.querySelector()element.addEventListener()classList API操作类名 事件处理&#xff1a; 直接事件绑定事件委托 document.body.addEventListener(click, functi…...

[Godot] C#2D平台游戏基础移动和进阶跳跃代码

本文章给大家分享一下如何实现基本的移动和进阶的跳跃&#xff08;跳跃缓冲、可变跳跃、土狼时间&#xff09;以及相对应的重力代码&#xff0c;大家可以根据自己的需要自行修改 实现效果 场景搭建 因为Godot不像Unity&#xff0c;一个节点只能绑定一个脚本&#xff0c;所以我…...

【Unity笔记】Unity + OpenXR项目无法启动SteamVR的排查与解决全指南

图片为AI生成 一、前言 随着Unity在XR领域全面转向OpenXR标准&#xff0c;越来越多的开发者选择使用OpenXR来构建跨平台的VR应用。但在项目实际部署中发现&#xff1a;打包成的EXE程序无法正常启动SteamVR&#xff0c;或者SteamVR未能识别到该应用。本文将以“Unity OpenXR …...

使用 rebase 轻松管理主干分支

前言 最近遇到一个技术团队的 dev 环境分支错乱&#xff0c;因为是多人合作大家各自提交信息&#xff0c;导致出现很多交叉合并记录&#xff0c;让对应 log 看起来非常混乱&#xff0c;难以阅读。 举例说明 假设我们有一个项目&#xff0c;最初develop分支有 3 个提交记录&a…...

【愚公系列】《Python网络爬虫从入门到精通》063-项目实战电商数据侦探(主窗体的数据展示)

&#x1f31f;【技术大咖愚公搬代码&#xff1a;全栈专家的成长之路&#xff0c;你关注的宝藏博主在这里&#xff01;】&#x1f31f; &#x1f4e3;开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主&#xff01; &#x1f…...

HttpSessionListener 的用法笔记250417

HttpSessionListener 的用法笔记250417 以下是关于 HttpSessionListener 的用法详解&#xff0c;涵盖核心方法、实现步骤、典型应用场景及注意事项&#xff0c;帮助您全面掌握会话&#xff08;Session&#xff09;生命周期的监听与管理&#xff1a; 1. 核心功能 HttpSessionLi…...

火山RTC 5 转推CDN 布局合成规则

实时音视频房间&#xff0c;转推CDN&#xff0c;文档&#xff1a; 转推直播--实时音视频-火山引擎 一、转推CDN 0、前提 * 在调用该接口前&#xff0c;你需要在[控制台](https://console.volcengine.com/rtc/workplaceRTC)开启转推直播功能。<br> * 调…...

Spark两种运行模式与部署

1. Spark 的运行模式 部署Spark集群就两种方式&#xff0c;单机模式与集群模式 单机模式就是为了方便开发者调试框架的运行环境。但是生产环境中&#xff0c;一般都是集群部署。 现在Spark目前支持的部署模式&#xff1a; &#xff08;1&#xff09;Local模式&#xff1a;在本地…...

react 父子组件通信 子 直接到父, 父 forwardref子

React核心概念&#xff1a;单向数据流&#xff08;Unidirectional Data Flow&#xff09; React 中数据的流动像瀑布一样&#xff0c;只能从上层组件&#xff08;父组件&#xff09;流向下层组件&#xff08;子组件&#xff09;。 子组件无法直接反向修改父组件的数据&#x…...

qt画一朵花

希望大家的生活都更加美好&#xff0c;画一朵花送给大家 效果图 void FloatingArrowPubshButton::paintEvent(QPaintEvent *event) {QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing);QPen pen;pen.setColor("green");pen.setWidth(5);QBrush…...

服务器上安装maven

1.安装 下载安装包 https://maven.apache.org/download.cgi 解压安装包 cd /opt/software tar -xzvf apache-maven-3.9.9-bin.tar.gz 安装目录(/opt/maven/) mv /opt/software/apache-maven-3.9.9 /opt/ 3.权限设置 把/opt/software/apache-maven-3.9.9 文件夹重命名为ma…...

UOS+N 卡 + CUDA 环境下 X86 架构 DeepSeek 基于 vLLM 部署与 Dify 平台搭建指南

一、文档说明 本文档是一份关于 DeepSeek 在X86架构下通vLLM工具部署的操作指南&#xff0c;主要面向需要在UOSN卡CUDA环境中部署DeepSeek的技术人员&#xff0c;旨在指导文档使用者完成从 Python 环境升级、vLLM 库安装、模型部署到 Dify 平台搭建的全流程操作。 二、安装Pyt…...

MySQL终章(8)JDBC

目录 1.前言 2.正文 2.1JDBC概念 2.2三种编码方式 2.2.1第一种 2.2.2第二种&#xff08;优化版&#xff09; 2.2.3第三种&#xff08;更优化版&#xff09; 3.小结 1.前言 哈喽大家好吖&#xff0c;今天来给大家带来Java中的JDBC的讲解&#xff0c;之前学习的都是操作…...

点云数据处理开源C++方案

一、主流开源库对比 库名称特点适用场景开源协议活跃度PCL功能最全&#xff0c;算法丰富科研、工业级应用BSD★★★★★Open3D现代API&#xff0c;支持Python绑定快速开发、深度学习MIT★★★★☆CGAL计算几何算法强大网格处理、高级几何运算GPL/LGPL★★★☆☆PDAL专注于点云…...

Python 爬虫如何伪装 Referer?从随机生成到动态匹配

一、Referer 的作用与重要性 Referer 是 HTTP 请求头中的一个字段&#xff0c;用于标识请求的来源页面。它在网站的正常运行中扮演着重要角色&#xff0c;例如用于统计流量来源、防止恶意链接等。然而&#xff0c;对于爬虫来说&#xff0c;Referer 也可能成为被识别为爬虫的关…...

【MySQL】表的约束(主键、唯一键、外键等约束类型详解)、表的设计

目录 1.数据库约束 1.1 约束类型 1.2 null约束 — not null 1.3 unique — 唯一约束 1.4 default — 设置默认值 1.5 primary key — 主键约束 自增主键 自增主键的局限性&#xff1a;经典面试问题&#xff08;进阶问题&#xff09; 1.6 foreign key — 外键约束 1.7…...

基于STC89C52RC和8X8点阵屏、独立按键的小游戏《打砖块》

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、8X8点阵屏2、独立按键3、定时器04、定时器1 四、主函数总结 系列文章目录 前言 用的是普中A2开发板&#xff0c;外设有&#xff1a;8X8LED点阵屏、独立按键。 【单片机】STC89C52RC 【频率】12T11.0592MHz 效…...

数字电子技术基础(五十)——硬件描述语言简介

目录 1 硬件描述语言简介 1.1 硬件描述语言简介 1.2 硬件编程语言的发展历史 1.3 两种硬件描述的比较 1.4 硬件描述语言的应用场景 1.5 基本程序结构 1.5.1 基本程序结构 1.5.2 基本语句和描述方法 1.5.3 仿真 1 硬件描述语言简介 1.1 硬件描述语言简介 硬件描述语…...

【深度学习】【目标检测】【Ultralytics-YOLO系列】YOLOV3核心文件common.py解读

【深度学习】【目标检测】【Ultralytics-YOLO系列】YOLOV3核心文件common.py解读 文章目录 【深度学习】【目标检测】【Ultralytics-YOLO系列】YOLOV3核心文件common.py解读前言autopad函数Conv类__init__成员函数forward成员函数forward_fuse成员函数 Bottleneck类__init__成员…...

16.Chromium指纹浏览器开发教程之WebGPU指纹定制

WebGPU指纹概述 WebGPU是下一代的Web图形和计算API&#xff0c;旨在提供高性能的图形渲染和计算能力。它是WebGL的后继者&#xff0c;旨在利用现代GPU的强大功能&#xff0c;使得Web应用能够实现接近原生应用的图形和计算性能。而且它是一个低级别的API&#xff0c;可以直接与…...

示例:spring 纯xml配置

以下是一个完整的 纯 XML 配置开发示例&#xff0c;涵盖 DAO、Service、Controller 层&#xff0c;通过 Spring XML 配置实现依赖注入和事务管理&#xff0c;无需任何注解。 1. 项目结构 src/main/java ├── com.example.dao │ └── UserDao.java # DAO 接口…...

SQL预编译——预编译真的能完美防御SQL注入吗

SQL注入原理 sql注入是指攻击者拼接恶意SQL语句到接受外部参数的动态SQL查询中&#xff0c;程序本身 未对插入的SQL语句进行过滤&#xff0c;导致SQL语句直接被服务端执行。 拼接的SQL查询例如&#xff0c;通过在id变量后插入or 11这样的条件&#xff0c;来绕过身份验证&#…...

系统架构师2025年论文《论基于UML的需求分析》

论基于构件的软件开发 摘要: 2011 年 3 月,我有幸参加了某市医院预约挂号系统项目的开发工作,并担任系统架构师一职,负责系统的架构设计及核心构件的开发工作。该项目是某市医院为提升患者就医体验、优化挂号流程而委托开发的,项目于 2011 年底验收,满足了医院及患者提…...