【Unity】QFramework通用背包系统优化:使用Odin优化编辑器

前言

在学习凉鞋老师的课程《QFramework系统设计:通用背包系统》第四章时,笔者使用了Odin插件,对Item和ItemDatabase的SO文件进行了一些优化,使物品页面更加紧凑、更易拓展。

核心逻辑和功能没有改动,整体代码量减少了,并且增加了一个复制ItemConfig的小功能。

需要注意:

  • 在ItemConfigGroup的列表中中删除ItemConfig时,应该点红色的X按钮,不要点最右侧的叉号,不然关联的ItemConfig SO文件不会被同时删除;
  • QFramework带有的自定义属性功能可能会和Odin冲突,建议只使用其中一种;

为了和原教程区分,下文将使用ItemConfig和ItemConfigGroup类来代替Item和ItemDatabase类。

修改前后对比:
请添加图片描述

代码

IItem接口:

using UnityEngine;namespace QFramework
{public interface IItem{string GetKey { get; }string GetName { get; }string GetDescription { get; }Sprite GetIcon { get; }bool GetStackable { get; }bool GetHasMaxStackableCount { get; }int GetMaxStackableCount { get; }ItemLanguagePackage.LocalItem LocalItem { get; set; }bool GetBoolean(string propertyName);}
}

ItemConfig类:

using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;namespace QFramework
{[CreateAssetMenu(menuName = "@ItemKit/Create ItemConfig")]public class ItemConfig : ScriptableObject, IItem{public ItemConfigGroup ItemConfigGroup { get; set; }[HideLabel][PreviewField(48, ObjectFieldAlignment.Left)][HorizontalGroup("名称类型", 54), VerticalGroup("名称类型/left")]public Sprite Icon = null;private void OnValidate(){this.name = Key;}[VerticalGroup("名称类型/left")][Button("X"), GUIColor(1, 0, 0)]private void RemoveThisConfig(){if (EditorUtility.DisplayDialog("删除物品", "确定要删除吗?\n(此操作不可恢复)", "删除", "取消")){ItemConfigGroup.ItemConfigs.Remove(this);AssetDatabase.RemoveObjectFromAsset(this);AssetDatabase.SaveAssets();AssetDatabase.Refresh();}}[VerticalGroup("名称类型/left")][Button("Dup"), GUIColor("yellow")]private void DuplicateThisConfig() // 增加复制/插入功能{if (ItemConfigGroup == null){Debug.LogError("ItemConfigGroup is null!");return;}ItemConfigGroup.DuplicateItemConfig(ItemConfigGroup.ItemConfigs.IndexOf(this), this);}[VerticalGroup("名称类型/right"), LabelWidth(42)][LabelText("名称")]public string Name = string.Empty;[VerticalGroup("名称类型/right"), LabelWidth(42)][LabelText("描述")][TextArea(minLines: 1, maxLines: 4)]public string Description = string.Empty;[VerticalGroup("名称类型/right"), LabelWidth(42)][LabelText("关键字")]public string Key = string.Empty;[VerticalGroup("名称类型/right"), LabelWidth(42)][LabelText("是武器")]public bool IsWeapon = false;[HorizontalGroup("属性")][VerticalGroup("属性/stackable"), LabelWidth(66)][LabelText("可堆叠")]public bool IsStackable = true;[ShowIf("IsStackable")][VerticalGroup("属性/stackable"), LabelWidth(66)][Indent][LabelText("有最大值")]public bool HasMaxStackableCount = false;[ShowIf("IsStackable"), EnableIf("HasMaxStackableCount")][DisplayIf(new string[] { "IsStackable", "HasMaxStackableCount" }, new[] { false, false })][VerticalGroup("属性/stackable"), LabelWidth(66)][Indent(2)][LabelText("最大值")]public int MaxStackableCount = 99;public string GetName => ItemKit.CurrentLanguage == ItemKit.DefaultLanguage ? Name : LocalItem.Name;public string GetKey => Key;public string GetDescription => ItemKit.CurrentLanguage == ItemKit.DefaultLanguage ? Description : LocalItem.Description;public Sprite GetIcon => Icon;public bool GetStackable => IsStackable;public bool GetHasMaxStackableCount => HasMaxStackableCount;public int GetMaxStackableCount => MaxStackableCount;public ItemLanguagePackage.LocalItem LocalItem { get; set; }public bool GetBoolean(string propertyName){if (propertyName == "IsWeapon"){return IsWeapon;}return false;}}
}

ItemConfigGroup类:

using Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using UnityEditor;namespace QFramework
{[CreateAssetMenu(menuName = "@ItemKit/Create Item ConfigGroup")]public class ItemConfigGroup : ScriptableObject{public string NameSpace = "QFramework.Example";[Searchable][TableList(ShowIndexLabels = true)]public List<ItemConfig> ItemConfigs = new List<ItemConfig>();[Button("添加 ItemConfig", ButtonSizes.Large), GUIColor("yellow")]private void AddItemConfig(){// 创建一个新的 ItemConfig 实例ItemConfig itemConfig = CreateInstance<ItemConfig>();itemConfig.ItemConfigGroup = this;itemConfig.name = nameof(ItemConfig);itemConfig.Name = "新物品";itemConfig.Key = "item_new";// 将新创建的 itemConfig 添加到 ItemConfigGroup 的资源中AssetDatabase.AddObjectToAsset(itemConfig, this);// 在 ItemConfigs 列表中添加一个新的元素ItemConfigs.Add(itemConfig);// 保存所有更改到资源AssetDatabase.SaveAssets();// 刷新资源AssetDatabase.Refresh();}public void DuplicateItemConfig(int index, ItemConfig itemConfig){// 创建一个新的 ItemConfig 实例ItemConfig itemConfigSO = CreateInstance<ItemConfig>();itemConfigSO.ItemConfigGroup = this;itemConfigSO.name = itemConfig.Key;itemConfigSO.Name = string.Empty;itemConfigSO.Key = "item_new";itemConfigSO.IsWeapon = itemConfig.IsWeapon;itemConfigSO.IsStackable = itemConfig.IsStackable;itemConfigSO.HasMaxStackableCount = itemConfig.HasMaxStackableCount;itemConfigSO.MaxStackableCount = itemConfig.MaxStackableCount;// 将新创建的 itemConfig 添加到 ItemConfigGroup 的资源文件中AssetDatabase.AddObjectToAsset(itemConfigSO, this);// 在 ItemConfigs 列表中添加一个新的元素ItemConfigs.Insert(index + 1, itemConfigSO);// 保存所有更改到资源AssetDatabase.SaveAssets();// 刷新资源AssetDatabase.Refresh();}[Button("生成 Items 代码", ButtonSizes.Large), GUIColor("green")]private void GenerateCode(){var itemDatabase = this;// 获取当前 ItemDatabase 脚本的文件路径,并确定生成代码的保存位置string filePath = AssetDatabase.GetAssetPath(itemDatabase).GetFolderPath() + "/Items.cs";// 使用 QFramework 中的代码生成功能// 创建一个代码作用域树,用于生成代码结构ICodeScope rootCode = new RootCode()// 添加命名空间.Using("UnityEngine").Using("QFramework")// 空一行.EmptyLine()// 定义命名空间.Namespace(itemDatabase.NameSpace, ns =>{// 在命名空间中定义一个类ns.Class("Items", String.Empty, false, false, c =>{// 为每个 itemDB.ItemConfigs 生成一个静态字符串字段foreach (ItemConfig itemConfig in itemDatabase.ItemConfigs){c.Custom($"public static string {itemConfig.Key} = \"{itemConfig.Key}\";");Debug.Log(itemConfig.Key);}});});// 创建或覆盖文件,并准备写入生成的代码// 使用 using 语句自动管理 StreamWriter 的生命周期。// 当离开 using 代码块的作用域时,fileWriter 的 Dispose 方法会被自动调用,确保文件资源被正确关闭。using StreamWriter fileWriter = File.CreateText(filePath);// 创建一个代码写入器,将代码作用域树转换为字符串FileCodeWriter codeWriter = new FileCodeWriter(fileWriter);// 生成代码并写入文件rootCode.Gen(codeWriter);// 保存所有未保存的资源更改AssetDatabase.SaveAssets();// 刷新 Unity 编辑器的资源数据库AssetDatabase.Refresh();}private void OnValidate(){foreach (ItemConfig itemConfig in ItemConfigs){if (itemConfig != null){itemConfig.name = itemConfig.Key;}elseItemConfigs.Remove(itemConfig);}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/673736.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习(15)--PyTorch构建卷积神经网络

目录 一.PyTorch构建卷积神经网络(CNN)详细流程 二.graphviz torchviz使PyTorch网络可视化 2.1.可视化经典网络vgg16 2.2.可视化自己定义的网络 一.PyTorch构建卷积神经网络(CNN)详细流程 卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;是一种深度学…

PHP入门指南:进阶篇

PHP入门指南&#xff1a;进阶篇 PHP入门指南&#xff1a;进阶篇1. 面向对象编程&#xff08;OOP&#xff09;1.1 类和对象的基本概念1.2 构造函数和析构函数1.3 属性和方法的访问控制1.4 继承与多态 2. 错误和异常处理2.1 错误处理机制2.2 异常处理机制2.3 自定义异常类 3. PHP…

Hadoop搭建(完全分布式)

节点分布&#xff1a; bigdata-masterbigdata-slave1bigdata-salve2 NameNode NodeManager NodeManager SecondaryNameNodeDataNodeDataNodeResourceManagerNodeManagerDataNode 目录 一、jdk安装&#xff1a; 二、hadoop安装 一、jdk安装&#xff1a; jdk-8u212链接&am…

信息隐藏研究新动向

信息隐藏有三十年的研究历史&#xff0c;在隐写、数字水印、可逆数据隐藏等方面&#xff0c;国内外发展了一系列新技术与新方法。随着深度学习时代的来临&#xff0c;信息隐藏研究出现了新的变化。一方面&#xff0c;深度学习技术在信息隐藏的发展中发挥了重要作用&#xff1b;…

94.网游逆向分析与插件开发-游戏窗口化助手-地图数据获取的逆向分析与C++代码还原

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;升级经验数据获取的逆向分析 码云地址&#xff08;游戏窗口化助手 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;c4351a5b346d8953a1a8e3ec…

SpringCloud-Eureka原理分析

Eureka是Netflix开源的一款用于实现服务注册与发现的工具。在微服务架构中&#xff0c;服务的动态注册和发现是必不可少的组成部分&#xff0c;而Eureka正是为了解决这一问题而诞生的。 一、为何需要Eureka 在微服务架构中&#xff0c;服务之间的协同合作和高效通信是至关重要…

CentOS下安装vlc

一、引言 vlc是一跨多媒体播放器&#xff0c;可以播放本地媒体文件和网络串流&#xff0c;帮助我们排查音视频开发过程中遇到的问题。大部分情况下&#xff0c;我们只需要在Windows系统下安装vlc就可以了。但有一种情况是需要在Linux下安装vlc的&#xff1a;我们的音视频拉流软…

华为配置内部人员接入WLAN网络示例(802.1X认证)

配置内部人员接入WLAN网络示例&#xff08;802.1X认证&#xff09; 组网图形 图1 配置802.1X认证组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 用户接入WLAN网络&#xff0c;使用802.1X客户端进行认证&#xff0c;输入正确的用户名和密…

Day10案例演示

Day10案例演示 在 AppInfoScanner所在的文件中运行cmd&#xff0c;输入 python -m pip install -r requirements.txt安装环境 具体用法可移步&#xff1a;https://github.com/kelvinBen/AppInfoScanner 以下仅以android类型示范 python app.py android -i <Your apk fil…

【Git版本控制 02】分支管理

目录 一、创建分支 二、切换分支 三、合并分支 四、删除分支 五、合并冲突 六、分支策略 七、bug分支 一、创建分支 # 当前仓库只有 master 一个主分支 # 可通过 git branch 是进行分支管理的命令&#xff0c;可通过不同参数对分支进行查看、创建、删除(base) [rootloc…

第一个 Angular 项目 - 静态页面

第一个 Angular 项目 - 静态页面 之前的笔记&#xff1a; [Angular 基础] - Angular 渲染过程 & 组件的创建 [Angular 基础] - 数据绑定(databinding) [Angular 基础] - 指令(directives) 这是在学完了上面这三个内容后能够完成的项目&#xff0c;目前因为还没有学到数…

Asp .Net Core 系列:Asp .Net Core 集成 Panda.DynamicWebApi

文章目录 简介Asp .Net Core 集成 Panda.DynamicWebApi配置原理什么是POCO Controller&#xff1f;POCO控制器原理ControllerFeatureProvider实现自定义判断规则IApplicationModelConventionPanda.DynamicWebApi中的实现ConfigureApiExplorer()ConfigureSelector()ConfigurePar…

S7-1200PLC通讯问题总结

文章目录 一、硬件1.串口通信RS232RS485RS422 2.网口通信 二、协议1.串口通信协议2.网口通信协议 三、程序编写1.S7通信PUTGET 2.开放式以太网通信 一、硬件 可分为PLC与PLC通信&#xff0c;PLC与上位机通信&#xff0c;PLC与变频器通信&#xff0c;PLC与仪器仪表通信&#xf…

兼容ARM 32位架构的edgeConnector产品为用户提供新的部署选项

Softing工业将ARM 32位兼容性集成到了edgeConnector产品中&#xff0c;以满足用户对ARM处理器的边缘设备日益增长的使用需求。 &#xff08;兼容ARM 32位架构的edgeConnector产品扩展了其应用部署范围&#xff09; 用户对采用ARM处理器的紧凑型边缘设备的需求正在大幅增长&…

使用 Docker 镜像预热提升容器启动效率详解

概要 在容器化部署中,Docker 镜像的加载速度直接影响到服务的启动时间和扩展效率。本文将深入探讨 Docker 镜像预热的概念、必要性以及实现方法。通过详细的操作示例和实践建议,读者将了解如何有效地实现镜像预热,以加快容器启动速度,提高服务的响应能力。 Docker 镜像预热…

使用influxdb+Grafana+nmon2influxdb+nmon实时监控vps性能

Grafana可以用来实时查看linux系统的各种性能数据。 1、安装环境&#xff1a; centos 7influxdb1.7.6grafana-4.6.3-1nmon2influxdb-2.1.7nmon-16m 2、安装influxdb&#xff1a; 下载rpm包&#xff1a; influxdb官网&#xff1a;https://docs.influxdata.com/influxdb/v2.0…

【Git版本控制 01】基本操作

目录 一、初始配置 二、添加文件 三、查看日志 四、修改文件 五、版本回退 六、撤销修改 七、删除文件 一、初始配置 Git版本控制器&#xff1a;记录每次的修改以及版本迭代的一个管理系统。 # 初始化本地仓库&#xff1a;git init(base) [rootlocalhost gitcode]# gi…

NLP_语言模型的雏形 N-Gram 模型

文章目录 N-Gram 模型1.将给定的文本分割成连续的N个词的组合(N-Gram)2.统计每个N-Gram在文本中出现的次数&#xff0c;也就是词频3.为了得到一个词在给定上下文中出现的概率&#xff0c;我们可以利用条件概率公式计算。具体来讲&#xff0c;就是计算给定前N-1个词时&#xff0…

笔记---dp---数字三角形模型

所谓数字三角形模型&#xff0c;即是从数字三角形这一题衍生出来的 题目为经典题目&#xff0c;不再赘述&#xff0c;此笔记根据AcWing算法提高课来进行对数字三角形模型衍生例题的记录 题目关系如下&#xff08;见AcWing里的AcSaber&#xff09;&#xff1a; AcWing.1015.摘…

微信小程序(三十八)滚动容器

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.滚动触底事件 2.下拉刷新事件 源码&#xff1a; index.wxml <view class"Area"> <!-- scroll-y 垂直滚动refresher-enabled 允许刷新bindrefresherrefresh 绑定刷新作用函数bindscrollto…