Unity编辑器扩展开发:打造高效项目资源查找工具

Android 开发中使用 SQLite 数据库 SQLite 介绍 SQLite 一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。许多开源项目((Mozilla, PHP, Python)都使用了 SQLite. SQLite 由以下几个组件组成:SQL 编译器、内核、后端以及附件。SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展 S... 阅读详情

1. 项目概述:为什么我们需要一个自己的资源查找工具?

在Unity项目开发中,尤其是当项目规模膨胀到几百上千个资源文件时,一个高效的资源查找工具就不再是“锦上添花”,而是“雪中送炭”的必需品。Unity编辑器自带的Project窗口搜索功能,虽然基础,但在面对一些特定、复杂的查找需求时,就显得力不从心了。比如,你想找出项目中所有引用了某个特定材质球的Prefab,或者想批量找到所有未压缩的纹理、所有超过特定大小的音频文件,又或者想根据脚本中的某个公共变量名来定位使用它的场景和预制体。这些需求,靠手动筛选和记忆,效率极低且容易出错。

这就是为什么我们需要自己动手,开发一个定制化的Unity编辑器扩展——项目资源查找工具。它不是一个简单的文件名搜索,而是一个能深入资源内部、理解资源关联关系、并能根据多种复合条件进行筛选的“项目管家”。通过它,我们可以将原本需要花费数小时甚至更长时间的重复性查找工作,压缩到几次点击和几秒钟之内。这不仅仅是提升效率,更是解放开发者,让我们能将精力更集中在创造性的游戏逻辑和内容制作上。

2. 核心需求与功能设计拆解

在动手写代码之前,我们必须先想清楚这个工具到底要解决哪些痛点,以及它应该具备哪些核心功能。一个好的设计,能让后续的开发事半功倍。

2.1 从痛点出发定义核心需求

基于日常开发经验,一个强大的资源查找工具至少需要满足以下几类核心需求:

  1. 基于类型的精确查找 :这是最基本的功能。不仅要能按 GameObject 、 Texture2D 、 AudioClip 、 Material 、 ScriptableObject 等类型筛选,更要能处理一些特殊或自定义类型。
  2. 基于属性的深度过滤 :这是工具价值的核心。例如:
    • 纹理资源:按纹理尺寸(如大于2048x2048)、纹理格式(如是否为ASTC)、是否开启Mipmap、是否可读写(Read/Write Enabled)进行筛选。
    • 音频资源:按音频时长、采样率、加载类型(Streaming, Compressed in Memory, Decompress on Load)进行筛选。
    • 模型资源:按顶点数、面数、是否包含动画、是否开启Read/Write进行筛选。
    • 预制体和场景:查找引用了特定材质、纹理、脚本或其它资源的对象。
  3. 基于路径与命名的灵活匹配 :支持通配符(如 *Character* )、正则表达式等高级匹配模式,方便进行批量操作。
  4. 依赖与引用关系分析 :这是Unity资源管理的难点。工具需要能分析两种关系:
    • 直接引用 :一个Prefab直接挂载了某个脚本。
    • 间接引用/依赖 :一个Material引用了某张Texture,而一个Prefab又使用了这个Material。工具需要能递归地找到所有直接或间接依赖某个“根资源”的所有资源。
  5. 结果的可操作性与导出 :查找结果不能只是一个列表。我们需要能够:
    • 在列表中选中并Ping到Project窗口中的具体资源。
    • 一键选中所有查找到的资源,便于批量操作(如修改导入设置、删除)。
    • 将结果列表导出为文本文件(如CSV),方便存档或与团队其他成员共享。

2.2 工具界面与交互设计思路

一个直观、高效的UI是工具好用的关键。我们将采用Unity的 EditorWindow 来创建自定义工具窗口。

界面布局规划:

  1. 顶部工具栏 :放置最常用的操作按钮,如“开始搜索”、“停止搜索”、“导出结果”、“清除结果”。
  2. 左侧筛选面板 :这是一个可折叠/展开的区域,包含所有搜索条件。
    • 搜索路径 :一个可输入或通过 ObjectField 选择的文件夹路径,限定搜索范围。
    • 资源类型选择器 :一个下拉菜单或多选框,用于选择要查找的资源类型。
    • 属性过滤器 :一个动态区域,根据选择的资源类型,显示对应的属性过滤条件(如输入框、滑块、下拉菜单)。例如,选择 Texture2D 后,会出现“最大宽度”、“最大高度”、“格式”等输入项。
    • 名称/路径匹配 :输入框,支持简单通配符。
    • 引用查找 :一个 ObjectField ,用于指定要查找其引用的目标资源。
  3. 中部结果展示区 :一个可滚动的列表(如使用 EditorGUILayout.BeginScrollView ),清晰展示每个匹配资源的图标、名称、路径、大小(如果可计算)等关键信息。每一行都应支持点击选中和Ping操作。
  4. 底部状态栏 :显示当前搜索状态,如“正在搜索...”、“找到 125 个资源”、“搜索完成,耗时 2.3 秒”。

交互逻辑:

  • 当用户修改筛选条件时,结果列表应实时更新(对于轻量搜索)或等待用户点击“搜索”按钮(对于重型递归搜索)。
  • 在结果列表项上右键点击,应弹出上下文菜单,提供“在Explorer中显示”、“复制路径”、“查看依赖项”等快捷操作。

3. 核心技术实现详解

有了清晰的设计,我们就可以深入代码层面,看看如何利用Unity Editor API将这些功能一一实现。

3.1 资源遍历的基石: AssetDatabase API

Unity提供了 AssetDatabase 这个静态类,它是我们与项目资源库交互的核心入口。对于查找工具,以下几个方法是重中之重:

  • AssetDatabase.FindAssets(string filter, string[] searchInFolders) : 这是最常用的快速查找方法。 filter 参数支持类似 t:Texture2D (类型过滤)和 l:UI (标签过滤)的语法。但它的过滤能力相对有限,主要用于初步、快速的资产GUID获取。
  • AssetDatabase.GUIDToAssetPath(string guid) : 将上一步找到的GUID转换为项目中的相对路径(如 "Assets/Textures/Icon.png" )。
  • AssetDatabase.LoadAssetAtPath<T>(string path) : 根据路径加载资源对象。这是后续进行属性检查的前提。

一个基础的遍历框架如下:

// 获取指定文件夹下的所有资源GUID(如果searchInFolders为空,则搜索整个Assets目录)
string[] guids = AssetDatabase.FindAssets("", new[] { “Assets/MyFolder” });
List<string> resultPaths = new List<string>();

foreach (string guid in guids)
{
    string assetPath = AssetDatabase.GUIDToAssetPath(guid);
    // 初步过滤:排除.meta文件、排除文件夹本身
    if (string.IsNullOrEmpty(assetPath) || assetPath.EndsWith(".meta")) continue;

    // 加载资源对象进行进一步判断
    UnityEngine.Object obj = AssetDatabase.LoadMainAssetAtPath(assetPath);
    if (obj != null && IsAssetMatchCondition(obj))
    {
        resultPaths.Add(assetPath);
    }
}

注意 : AssetDatabase.FindAssets 在大型项目中的性能表现可能成为瓶颈,因为它会遍历所有元数据(.meta文件)。在实际工具中,我们需要考虑分帧异步处理或提供进度提示,防止编辑器卡死。

3.2 深度属性检查:使用 AssetImporter 与反射

要对资源的具体属性(如纹理尺寸、音频时长)进行过滤,仅仅加载出 Texture2D 或 AudioClip 对象是不够的。我们需要获取它们在导入(Import)时的设置,这些信息存储在对应的 AssetImporter 派生类中。

  • TextureImporter : 对应纹理资源,可以获取 maxTextureSize , textureFormat , isReadable , mipmapEnabled 等。
  • AudioImporter : 对应音频资源,可以获取 defaultSampleSettings (包含 loadType , compressionFormat 等)。
  • ModelImporter : 对应模型资源(FBX等),可以获取 meshCompression , isReadable , animationType 等。

示例:检查纹理尺寸和格式

TextureImporter texImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (texImporter != null)
{
    // 获取平台特定设置,例如Android平台
    TextureImporterPlatformSettings platformSettings = texImporter.GetPlatformTextureSettings(“Android”);
    int maxSize = platformSettings.overridden ? platformSettings.maxTextureSize : texImporter.maxTextureSize;
    TextureImporterFormat format = platformSettings.overridden ? platformSettings.format : TextureImporterFormat.Automatic;

    if (maxSize > 2048 && format == TextureImporterFormat.ASTC_6x6)
    {
        // 符合“尺寸大于2048且格式为ASTC 6x6”的条件
        return true;
    }
}

对于脚本、Shader等文本类资源,我们可能需要读取文件内容进行关键字匹配。这时可以使用 System.IO.File 来读取文件。

3.3 引用关系挖掘: AssetDatabase.GetDependencies 与序列化探查

查找资源引用是工具中最复杂也最实用的功能之一。Unity提供了 AssetDatabase.GetDependencies 方法,它可以获取一个资源所依赖的所有其他资源的路径列表。

  • AssetDatabase.GetDependencies(string pathName, bool recursive) : recursive 参数为 true 时,会递归查找所有层级的依赖。
    • 正向查找(依赖什么) : GetDependencies(selectedPrefabPath, true) 可以得到这个Prefab用到的所有材质、纹理、脚本等。
    • 反向查找(被谁引用) :Unity没有直接的反向查询API。我们需要自己实现,思路是遍历项目中可能包含引用的资源(如所有Prefab、Scene、ScriptableObject、Material),检查其序列化数据中是否包含目标资源的GUID或引用。

实现反向查找的核心在于解析资源的序列化信息。 我们可以使用 SerializedObject 来遍历一个UnityEngine.Object的所有序列化属性。

// 简化版的反向查找思路
public static List<string> FindAssetsThatReference(string targetAssetPath)
{
    string targetGUID = AssetDatabase.AssetPathToGUID(targetAssetPath);
    List<string> results = new List<string>();
    // 遍历所有预制体和场景(主要引用源)
    string[] allPrefabs = AssetDatabase.FindAssets(“t:Prefab”);
    // ... 同样获取所有场景 t:Scene

    foreach (var prefabGuid in allPrefabs)
    {
        string prefabPath = AssetDatabase.GUIDToAssetPath(prefabGuid);
        SerializedObject serializedObject = new SerializedObject(AssetDatabase.LoadMainAssetAtPath(prefabPath));
        SerializedProperty iterator = serializedObject.GetIterator();
        bool found = false;
        while (iterator.NextVisible(true) && !found)
        {
            if (iterator.propertyType == SerializedPropertyType.ObjectReference)
            {
                var referencedObject = iterator.objectReferenceValue;
                if (referencedObject != null)
                {
                    string refPath = AssetDatabase.GetAssetPath(referencedObject);
                    if (AssetDatabase.AssetPathToGUID(refPath) == targetGUID)
                    {
                        results.Add(prefabPath);
                        found = true;
                        break;
                    }
                }
            }
            // 还需要检查ExposedReference、ManagedReference等复杂类型
        }
    }
    return results;
}

实操心得 :完整的反向查找实现非常复杂,需要处理数组、列表、嵌套结构、ScriptableObject字段等多种情况。对于生产环境,建议参考或集成已有的成熟方案,如Unity官方的 AssetDatabase.FindAssets(“ref:”) 语法(部分版本支持),或使用像 AssetReferenceFinder 这样的第三方开源工具库作为基础。自己从头实现一个健壮的反向查找器,是一个不小的工程。

3.4 构建响应式UI: EditorWindow 、 EditorGUI 与 SerializedObject

工具窗口继承自 EditorWindow 。UI的构建在 OnGUI 方法中完成。为了管理复杂的筛选条件,一个好的实践是创建一个可序列化的配置类(如 SearchConfig ),然后使用 SerializedObject 和 SerializedProperty 来自动绘制UI并处理撤销/重做。

public class ResourceSearchWindow : EditorWindow
{
    private SearchConfig _config;
    private SerializedObject _serializedConfig;
    private Vector2 _scrollPos;
    private List<SearchResultItem> _results = new List<SearchResultItem>();

    [MenuItem(“Tools/Project/Advanced Resource Finder”)]
    static void Init() { /* 创建窗口 */ }

    void OnEnable()
    {
        _config = ScriptableObject.CreateInstance<SearchConfig>();
        _serializedConfig = new SerializedObject(_config);
    }

    void OnGUI()
    {
        _serializedConfig.Update();
        // 绘制筛选条件面板
        EditorGUILayout.BeginVertical(“Box”);
        DrawSearchFilters();
        EditorGUILayout.EndVertical();

        // 绘制按钮
        if (GUILayout.Button(“Search”, GUILayout.Height(30)))
        {
            ExecuteSearch();
        }

        // 绘制结果列表
        DrawResultsList();
        _serializedConfig.ApplyModifiedProperties();
    }

    void DrawSearchFilters()
    {
        // 使用SerializedProperty自动绘制字段
        SerializedProperty sp = _serializedConfig.FindProperty(“searchFolder”);
        EditorGUILayout.PropertyField(sp);
        // ... 绘制其他条件
    }
}

// 可序列化的配置类
public class SearchConfig : ScriptableObject
{
    public DefaultAsset searchFolder;
    public List<System.Type> assetTypes = new List<System.Type>();
    public string nameFilter;
    // ... 其他条件
}

使用 SerializedObject 的优点是,当字段很多时,我们可以利用 EditorGUILayout.PropertyField 自动生成合适的UI控件(根据字段类型显示为ObjectField、TextField、Toggle等),并且自动支持Unity的撤销操作。

4. 高级功能与性能优化实战

一个基础工具能跑起来,但一个优秀的工具必须考虑效率、稳定性和扩展性。

4.1 实现异步搜索与进度反馈

在大型项目中,遍历数万个资源是耗时操作。我们必须将搜索过程放在后台,避免阻塞主线程导致编辑器无响应。可以使用 EditorApplication.update 回调或者 async/await (需注意Unity主线程限制)来模拟异步。

一个简单的分帧处理模式:

private IEnumerator SearchCoroutine(List<string> allAssetPaths)
{
    int processedCount = 0;
    int totalCount = allAssetPaths.Count;
    _results.Clear();

    for (int i = 0; i < totalCount; i++)
    {
        // 每处理N个资产,或每帧处理一次
        if (processedCount >= assetsPerFrame || i == totalCount - 1)
        {
            processedCount = 0;
            // 更新进度条
            if (EditorUtility.DisplayCancelableProgressBar(“Searching...”, $”Processing {i+1}/{totalCount}”, (float)i / totalCount))
            {
                // 用户取消了
                break;
            }
            yield return null; // 等待下一帧
        }

        string path = allAssetPaths[i];
        // ... 执行资源匹配检查
        if (IsAssetMatchCondition(path))
        {
            _results.Add(new SearchResultItem(path));
        }
        processedCount++;
    }

    EditorUtility.ClearProgressBar();
    // 搜索完成,刷新UI
    Repaint();
}

在 ExecuteSearch 方法中,使用 EditorCoroutineUtility.StartCoroutineOwnerless(SearchCoroutine(...)) 来启动这个协程。同时,要提供“停止搜索”的按钮,其本质是设置一个取消标志位,在协程中检查并退出。

4.2 结果缓存与索引构建

对于相对静态的项目,每次搜索都全量遍历是不经济的。可以考虑引入缓存机制:

  • 元数据缓存 :第一次搜索时,将资源的关键属性(路径、类型、大小、部分导入设置)提取并存储到一个内存结构或轻量级数据库中。
  • 引用关系图 :在项目空闲时(如编译后),后台构建一个资源引用关系图。当进行反向查找时,直接查询这个图,速度极快。
  • 增量更新 :监听 AssetDatabase 的 onAssetsChanged 事件,当资源被导入、删除、移动时,只更新缓存中受影响的部分。

注意事项 :缓存机制会显著增加工具的复杂度,并消耗更多内存。它更适合大型、长期运营的项目团队。对于中小型项目或临时性的查找,实时搜索的简单性可能更有优势。引入缓存前,务必做好性能 profiling,确认其收益大于维护成本。

4.3 制作可配置的过滤器系统

硬编码的过滤条件不灵活。我们可以设计一个过滤器接口和一系列实现,让工具支持“插件式”的过滤条件。

public interface IAssetFilter
{
    string Name { get; }
    bool IsMatch(string assetPath, UnityEngine.Object asset, AssetImporter importer);
}

[System.Serializable]
public class TextureSizeFilter : IAssetFilter
{
    public int maxWidth = 2048;
    public int maxHeight = 2048;
    public string Name => $”Texture Size > {maxWidth}x{maxHeight}”;

    public bool IsMatch(string path, UnityEngine.Object obj, AssetImporter importer)
    {
        var texImporter = importer as TextureImporter;
        if (texImporter == null) return false;
        // ... 检查逻辑
    }
}

// 在配置类中
public List<IAssetFilter> activeFilters = new List<IAssetFilter>();

这样,在UI中我们可以动态地添加、移除、配置不同的过滤器,甚至将过滤器组合保存为“搜索预设”,方便下次一键调用。

4.4 集成到编辑器工作流

让工具无处不在,提升使用频率:

  • 右键菜单 :为Project窗口中的资源添加右键菜单项,如“Find References in Project”,点击后直接打开工具窗口并执行对该资源的反向查找。
  • 自定义Inspector按钮 :为特定类型的资源(如Material)的Inspector添加一个按钮,点击后查找所有使用该材质的Renderer。
  • 编辑器快捷键 :为工具窗口分配一个全局快捷键(如Ctrl+Shift+F),方便快速呼出。
// 添加Project窗口右键菜单
public class ProjectWindowExtensions
{
    [MenuItem(“Assets/Find All References”, false, 20)]
    private static void FindReferencesToAsset()
    {
        var selected = Selection.activeObject;
        if (selected != null)
        {
            var window = EditorWindow.GetWindow<ResourceSearchWindow>();
            window.SetSearchTarget(selected);
            window.Show();
        }
    }

    [MenuItem(“Assets/Find All References”, true)]
    private static bool ValidateFindReferencesToAsset()
    {
        return Selection.activeObject != null;
    }
}

5. 常见问题排查与实战技巧

在实际开发和使用过程中,你肯定会遇到各种“坑”。这里记录了一些典型问题和解决方案。

5.1 搜索速度慢,编辑器卡死

  • 问题 :搜索一个包含数万资源的大项目时,UI无响应。
  • 排查 :
    1. 是否在单帧内处理了所有资源?使用 System.Diagnostics.Stopwatch 计时,确认耗时环节。
    2. 是否频繁调用 AssetDatabase.LoadAssetAtPath 或 AssetImporter.GetAtPath ?这些调用有一定开销。
    3. 是否在检查资源属性时执行了昂贵的操作,如读取大文件内容?
  • 解决 :
    • 强制分帧 :如上文所述,使用协程和 EditorUtility.DisplayProgressBar 。
    • 减少加载 :优先使用 AssetDatabase.GetMainAssetTypeAtPath 进行类型初筛,避免加载不需要的资源对象。
    • 缓存Importer :对于同一次搜索,同一个路径的 AssetImporter 获取一次即可。
    • 提供范围选项 :让用户可以选择仅在特定文件夹内搜索,而不是全项目。

5.2 查找引用结果不完整或错误

  • 问题 :反向查找时,漏掉了一些引用,或者找到了不相关的资源。
  • 排查 :
    1. 序列化遍历是否完整? SerializedObject 的 NextVisible 遍历可能无法访问所有属性,对于数组和自定义序列化类需要特殊处理。
    2. 是否处理了 ScriptableObject 中嵌套的引用? ScriptableObject 的字段也需要被遍历。
    3. 是否考虑了通过资源ID(GUID)的间接引用?有些引用是以GUID字符串形式存储在文本文件(如.anim、.playable)中。
  • 解决 :
    • 使用 SerializedProperty 深度遍历 :递归遍历所有属性,包括子属性和数组元素。
    • 检查文本内容 :对于已知的文本资产类型(如 .shader , .cginc , .mat (部分)),可以尝试用正则表达式匹配目标资源的GUID。
    • 借助专业工具验证 :用Unity官方工具(如 Search 窗口的 ref: 语法,如果版本支持)或成熟的第三方资产查找插件(如 Asset Hunter 2 )来交叉验证你的查找结果,以校准你的算法。

5.3 自定义类型或第三方插件资源无法识别

  • 问题 :工具无法正确筛选来自第三方插件(如Odin Serializer, Behavior Designer)或用户自定义 ScriptableObject 的资源。
  • 排查 : AssetDatabase.FindAssets(“t:”) 使用的类型过滤是基于Unity原生类型系统。自定义类型可能没有注册。
  • 解决 :
    • 使用全称或程序集限定名 :有时需要传入类型的完整名称。
    • 备用方案 :如果不支持类型过滤,可以退而求其次,先通过文件扩展名(如 .asset )筛选出所有潜在文件,再通过 AssetDatabase.LoadMainAssetAtPath 加载并判断其实际类型( obj.GetType() )。
    • 提供自定义类型输入 :在UI中允许用户输入类型的字符串名称,然后通过 Type.GetType() 或遍历所有程序集来尝试解析该类型。

5.4 工具在团队中的使用与配置同步

  • 问题 :你开发了一个好用的工具,如何让团队其他成员也能方便地用上,并且大家的搜索预设能共享?
  • 解决 :
    • 将工具代码放入版本控制 :这是最基本的要求。将整个Editor脚本文件夹纳入Git等版本管理系统。
    • 使用 EditorUserSettings 或项目级配置文件 :不要将用户的个人搜索配置(如最近使用的路径、过滤器组合)保存在本地机器路径。可以使用 EditorUserSettings.GetConfigValue / SetConfigValue 来存储用户级配置。对于团队共享的预设,可以创建一个 ScriptableObject 资产(如 TeamSearchPresets.asset )放在项目的 Editor 文件夹下,并纳入版本控制。
    • 编写简单的使用文档 :在工具窗口内添加一个“Help”标签页,用简短的文字和截图说明核心功能如何使用。

开发一个成熟的Unity编辑器扩展工具,就像在打造一把趁手的“瑞士军刀”。它始于一个具体的需求痛点,成长于不断迭代和解决实际问题的过程中。从最简单的按名搜索,到复杂的属性过滤和引用分析,每一步功能的添加都让这把“刀”更加锋利。最重要的是,这个工具是你为自己和团队量身定制的,它完全贴合你们的工作流。当你能在几秒钟内解决一个曾经需要翻找半天的资源问题时,那种效率提升带来的成就感,就是驱动我们不断优化工具的最佳动力。

Unity编辑器扩展-基本界面编写 1.先进行第一步,给编辑器加个菜单: 通过[MenuItem("AXX/BXX")]就可以在编辑器的上边菜单栏增加一个下拉菜单AXX,并增加一个按钮BXX。只要把这句话写在我们定义的函数上方就可以,然后我们点击这个按钮,就会调用这个我们自定义的函数。不过有一点一定要记住,这个函数要是static的!(想一想就可以知道是为什么,编辑器没有必要搞粗一个对象之类的,因为我们要调用的只是这个方法)例如: 阅读详情

相关推荐

Unity编辑器极限改造:从零打造高效神器,解锁游戏开发超能力!

解锁Unity编辑器的隐藏潜能,成为游戏开发的魔法大师!这份指南将带你深入编辑器扩展的奇幻世界,从基础到高阶,一步步构建属于你的定制化开发利器。无论是自定义Inspector的魔法改造,还是编辑器菜单的独家定制,你都能信手拈来,让工作效率与创意自由齐飞!

码趣阿佑 2248

Android SQLite 的介绍和使用(一)

SQLite 是一款小巧的嵌入式数据库,在Android和IOS中使用的数据库就是SQLite,它用的内存很少。并且它支持支持 SQL92(SQL2)标准的大多数查询语言的功能。而且它不需要配置,很容易使用。SQLite命令DDL–数据定义语言 CREATE:创建一个新表,或者其他对象 ALERT: 修改数据库中的某个已有对象 DROP:删除整个表或其他对象 DML–数据操作语言 INSERT:插入

Ricky 的博客 673

Unity 编辑器扩展总结 八:EditorPrefs、ScriptableObject、Undo

编辑器扩展总结 工欲善其事必先利其器 引言: 在项目开发中,编辑器扩展为开发者提供了开发自定义工具的功能,让开发者更加便利地使用编辑器开发项目。如若博客中存在错误,还请大佬们不吝赐教。所有参考的博客或者视频来源将在文末展示。 开发版本: Unity 2019.4.9f1 EditorPrefs、ScriptableObject、Undo EditorPrefs的简单使用 Unity编辑器为开发者提供了类似PlayerPrefs的数据保存方式EditorPrefs。EditorPrefs是适用于编辑器模式

胖胖的橘猫君 4461

Android中SQLite的意义及用法

演示SQLite数据库创建、建表、增删改查等操作

艟粼的专栏 1110

Unity编辑器——Inspector 面板扩展

目录 将EditorGUI 扩展在 Inspector 面板上 EditorWindows 窗口 EditorWindows 下拉菜单 预览窗口 获取预览信息 将EditorGUI 扩展在 Inspector 面板上 ●EditorGUI 和 GUI 的用法几乎完全一致,目前来说前者多用于编辑器开发,后者多用于发布后调试编辑器。总之,它们都是起辅助作用的。 EditorGUI 提...

TAOTAO 1万+

Unity编辑器扩展 UI控件篇

Unity引擎内编辑器扩展

xinzhilinger的博客 4230

Android的嵌入式关系型SQLite数据库使用

除了可以使用文件或SharedPreferences存储数据,还可以选择使用SQLite数据库存储数据。 在Android平台上,集成了一个嵌入式关系型数据库—SQLite,SQLite3支持 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际上sqlite3也接受varchar(n)、char(n)、decimal(p,s) 等数据类型,只不过在运算或保存时会转成对应的五种数据类型。 SQLite最大的特点是你可以

1942

【Unity编辑器扩展实践】、通过代码查找所有预制

在Unity中对编辑器的扩展,通常都会操作文件的增删改查,这里介绍两种Unity中查找预制的方法,其他文件同理。 1、利用AssetDatabase查找预制: 通过AssetDatabase的FindAssets方法可以查找到所有文件的guid,参数filter是过滤字符。就是Unity中Project窗口下搜索栏右边两个按钮弹出来的东西,t标识是Type,l标识是lable。(如"Prefa...

不文不武的禾文 4298

SQLlite在安卓中的基本详解和简单使用,真的太香了

super(context, name, null, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE IF NOT EXISTS person (personid integer primary key autoincrement, name varchar(20), age INTEGER)"); } @Override public void onUpgrade(SQLite

m0_65511807的博客 3779

Unity 编辑器扩展总结 十:AssetPostprocessor资源导入管线

AssetPostprocessor资源导入管线 AssetPostprocessor基本使用 AssetPostprocessor用于在资源导入时自动做一些设置,比如当导入大量图片时,自动设置图片的类型,大小等。AssetPostprocessor作为资源导入的管理器,可以根据不同的资源类型,在导入前后导入后做一些处理。 一些常用的方法如下: OnPreprocessTexture:在导入纹理贴图之前调用 OnPreprocessModel:在导入模型之前调用 OnPreprocessAudio:在导入音

胖胖的橘猫君 5276

【Unity编辑器扩展】 | 编辑器扩展入门基础

当谈到游戏开发工具,Unity编辑器是一个备受赞誉的平台。它为开发者提供了一个强大且灵活的环境,使他们能够创建令人惊叹的游戏和交互式体验。 然而,Unity编辑器本身也是可以扩展和定制的,这为开发者提供了进一步提升工作流程和增强功能的机会。 在Unity 编辑器扩展专栏中,将探讨Unity编辑器扩展的概念、优势、如何创建自己的扩展以及众多关于编辑器扩展的知识学习。

努力前行,总会成为自己心中的那道光 7万+

Unity 编辑器扩展总结 一:编辑器开发入门

编辑器扩展总结 工欲善其事必先利其器 引言: 在项目开发中,编辑器扩展为开发者提供了开发自定义工具的功能,让开发者更加便利地使用编辑器开发项目。近期小生一直在学习编辑器扩展的知识,发现网络上关于编辑器知识点的博客较为零散且混乱。所以决定近期会整理一系列编辑器相关的博客,分享给每一位在学习道路上奋斗的童鞋,如若博客中存在错误,还请大佬们不吝赐教。所有参考的博客或者视频来源将在文末展示。 相关博客...

胖胖的橘猫君 4万+

Unity编辑器扩展之项目资源查找工具

Unity编辑器扩展之项目资源查找工具

虚粒世界 330

盘点Unity几款编辑器扩展工具

今天推荐的三款编辑器扩展工具用于在Unity编辑器中以不同的方式创建3D模型,大家可以根据具体的项目需求选取最为合适的工具,类似的建模工具也进一步加强了Unity引擎的迭代效率,能为各种规模的Unity开发团队节省大量时间成本。未来我们还会为大家介绍Asset Store资源商店中高效实用的扩展工具,请保持关注。·END·扫描二维码⬇️添加助教老师⬇️免费领取游戏策划4天训练营!⬇️。

Richard_shen的博客 2593

算法之动态规划(DP)求解完全背包问题

算法之动态规划(DP)求解01背包问题 上面这篇文章主要讲解了01背包问题和动态规划算法,如果你不了解动态规划算法,建议先浏览一下这篇文章熟悉一下,因为,本文的算法思想是基于这篇文章的。 1、什么是完全背包问题? **01背包问题:**有一个背包的容积为V,有N个物品,每个物品的体积为v[i],权重为w[i],每个物品只能取1次放入背包中,背包所有物品权重和最大是多少? 完全背包: 有一个背包的容积为V,有N个物品,每个物品的体积为v[i],权重为w[i],每个物品可以取无限次放入背包中,背包所有物品权重和

PRML_MAN的博客 2万+

QCustomPlot实战:从入门到精通的数据可视化

本文详细介绍了如何使用QCustomPlot进行数据可视化,从基础环境搭建到高级图表定制,涵盖实时监控、多坐标系联动等实战技巧。基于Qt的QCustomPlot库以其强大的绘图能力和灵活的API,帮助开发者快速实现专业级数据可视化效果。

weixin_29003437的博客 115

【Unity笔记】Unity 编辑器扩展:一键查找场景中组件引用关系(含完整源码)(组件引用查找工具实现笔记)

本文介绍了如何在 Unity 编辑器中开发一款实用的编辑器扩展工具 —— ComponentReferenceFinder,用于查找场景中对某个自定义组件的引用关系。该工具特别适用于大型项目、多人协作或引入外部插件后,快速定位组件间的耦合关系。 本文从需求出发,逐步拆解功能目标:如何获取选中 GameObject、自定义组件的过滤逻辑、如何遍历场景中的 MonoBehaviour、反射字段和集合引用、解析 UnityEvent 中的持久化调用,以及如何在 EditorWindow 中呈现可视化查找结果。

一个XR(AR|VR|MR)程序猿的博客(EQ-雪梨蛋花汤) 1821

智慧城市项目实战:如何将你的地理数据从城市坐标系(如上海2000)转换到国家CGCS2000?

本文详细介绍了智慧城市项目中地理数据坐标系转换的全流程解决方案,重点讲解如何将城市坐标系(如上海2000)转换到国家CGCS2000。通过七参数布尔莎模型、ArcGIS Pro、QGIS开源方案及Python编程实现,帮助实施团队解决坐标系不统一的技术难题,确保空间分析精度。

weixin_28725949的博客 307

Unity编辑器扩展:提高效率与创造力的关键

Unity是一款广泛使用的游戏开发引擎,拥有强大的功能和灵活性。除了核心引擎外,Unity编辑器也是其重要组成部分。通过扩展Unity编辑器,开发者可以大大提高开发效率,同时释放创造力,打造出更加出色的游戏作品。本文将探讨Unity编辑器的扩展及其对游戏开发的重要性。

努力前行,总会成为自己心中的那道光 1万+

第八篇 永磁同步电机控制-MTPA、MTPV

MTPA 的全称是 Maximum Torque Per Ampere,即 最大转矩电流比控制。核心思想:在输出特定转矩时,通过控制定子电流的幅值和相位(即d轴和q轴电流的分量),使得所需要的定子电流幅值最小。通俗理解:就是用“最省电”的方式产生所需要的力矩。就像开车时,找到一个最合适的油门和档位配合,使得在输出相同动力时,油耗最低。

深耕汽车电子:AUTOSAR、电机控制,助力数字汽车 1874

Ubuntu 20.04下大陆ARS408毫米波雷达点云数据采集与RVIZ实时可视化全流程解析

本文详细解析了在Ubuntu 20.04系统下,如何实现大陆ARS408毫米波雷达的点云数据采集与RVIZ实时可视化全流程。内容涵盖硬件连接、ROS Noetic环境搭建、CAN接口配置、数据验证及自动化脚本编写,为机器人感知、自动驾驶等领域的开发者提供了一套稳定、实用的实战方案。

bash7scripter的博客 699

【Unity笔记】Unity 编辑器扩展:打造一个可切换 Config.assets 的顶部菜单插件

本文介绍了如何在 Unity 中通过自定义 ScriptableObject 配合 EditorWindow,开发一个顶部菜单栏的配置管理器插件。用户可在面板中通过下拉框快速切换配置文件,或首次从文件管理器选择并保存默认配置。文中解析了需求背景、技术原理、实现流程,并附带完整代码和 PlantUML 图示,帮助开发者快速掌握配置管理插件的设计与实现。

一个XR(AR|VR|MR)程序猿的博客(EQ-雪梨蛋花汤) 3551

playwright-mcp 安装使用的详细教程

Playwright MCP 快速入门指南 Playwright MCP Server 是由微软开发的浏览器自动化服务,通过 MCP 协议为 AI/Agent/LLM 提供网页交互能力。它基于可访问性树而非屏幕截图,支持多种浏览器和运行模式。 安装要求: Node.js v18+ 命令行操作能力 支持 MCP 的客户端 安装方式: 通过 npx 快速启动:npx @playwright/mcp@latest 项目依赖安装:npm install @playwright/mcp 主要特性: 支持 Chrome

上善若水 7997

Unity 编辑器扩展总结 六:扩展Scene视图

编辑器扩展总结 工欲善其事必先利其器 引言: 在项目开发中,编辑器扩展为开发者提供了开发自定义工具的功能,让开发者更加便利地使用编辑器开发项目。如若博客中存在错误,还请大佬们不吝赐教。所有参考的博客或者视频来源将在文末展示。 开发版本: Unity 2019.4f1 扩展Scene视图 OnSceneGUI的使用 场景视图是编辑游戏对象的窗口,扩展场景视图可以实现网格编辑,地形绘制或高级Gizmos等操作。视图的扩展主要通过OnSceneGUI()方法实现,因为场景扩展是基于场景对象的,所以可以选择不同

胖胖的橘猫君 6724

基于Python的二手奢侈品电商平台商品保值率数据爬取与分析

本文旨在探讨如何利用Python网络爬虫技术获取二手奢侈品电商平台商品数据,并通过数据分析研究奢侈品的保值率特性。研究将使用最新的爬虫技术(包括Playwright、异步处理和数据清洗技术)来高效获取数据,并利用Pandas、Matplotlib等数据分析库进行深入的数据可视化分析。本文详细介绍了爬虫的设计思路、实现过程以及数据分析方法,为奢侈品投资和消费提供数据参考。关键词:Python爬虫、奢侈品保值率、数据分析、Playwright、异步处理。

2201_76125261的博客 512

YOLOv11改进 | 主干/Backbone篇 | 轻量化目标检测网络MobileViTv1改进yolov11有效涨点

本文给大家带来的改进机制是MobileViT系列的V1版本,其作为MobileNet网络的挑战者,其效果自然不用多说,MobileViT模型是为移动设备设计的轻量级、通用目的视觉变换器。它融合了卷积神经网络(CNN)和视觉变换器(ViT)的优势,旨在在保持高效性能的同时减少模型参数和降低延迟。通过其创新的MobileViT Block和多尺度训练方法,MobileViT在多个视觉任务上取得了优异的结果,欢迎大家订阅本专栏,本专栏每周更新3-5篇最新机制,更有包含我所有改进的文件和交流群提供给大家。

Snu77的博客 2336
上一篇: 虚幻引擎PicoVR开发:PICO XR Plugin与OpenXR Plugin深度对比与选型指南
下一篇: 工业信号干扰防护:光耦隔离与MCU滤波技术解析
com_xpp
博客等级 码龄16年 23粉丝 160原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值