美文网首页
Unity中,制作编辑器内简单的工具窗口

Unity中,制作编辑器内简单的工具窗口

作者: 全新的饭 | 来源:发表于2023-10-17 18:00 被阅读0次

用途

如制作一些配置工具等。

工具窗口说明

窗口内展示若干字段、2个按钮:一个执行功能、一个关闭窗口。
可继承ScriptableWizard来实现。

示例:

public class SaveCurMomentTools : ScriptableWizard
{
    private const string Title = "存储当前时刻";

    [SerializeField]
    private TextAsset _textAsset;

    [MenuItem("Fan的工具/存储当前时刻")]
    private static void Init()
    {
        DisplayWizard<SaveCurMomentTools>(Title, "关闭", "执行");
    }
    private void OnWizardUpdate()
    {
        Debug.Log($"{Title} 窗口的内容发生了变化!");
    }
    private void OnWizardOtherButton()
    {
        SaveMoment();
    }
    private void OnWizardCreate()
    {
        Debug.Log("关闭窗口:" + Title);
    }
    private void SaveMoment()
    {
        Debug.Log("存储当前时刻");
    }

弹出提示窗口

用途

如点击按钮后,执行失败或成功了,需弹窗告知玩家。

实现
    private void ShowTipsWnd(string title, string tips)
    {
        UnityEditor.EditorUtility.DisplayDialog(title, tips, "好的");
    }

编辑器模式下的延迟调用

用途

如执行功能是修改某个ScriptableObject文件,若此时Inspector窗口中正展示该文件,在修改保存后立刻弹窗提示时,不能看到该文件内的数据发生了变化(点击按钮关闭弹窗后才能看到数据变化了)。
因此成功执行后,可以等待一会儿再在弹出成功执行的提示窗口。

实现
    private void ShowTipsWnd(string title, string tips, float delaySeconds = 0f)
    {
        if (delaySeconds > 0)
        {
            System.Func<Task> func = async () =>
            {
                await Task.Delay(System.TimeSpan.FromSeconds(delaySeconds));
                ShowTipsWnd(title, tips);
            };
            func();
        }
        else
        {
            ShowTipsWnd(title, tips);
        }
    }
async、await、Task

async:会返回一个Task表示异步操作的完成情况。
await运算符可暂停其所属的async方法的执行,直到它修饰的操作执行完成,才继续往下执行。
Task:对ThreadPool进行了封装改进,使我们能更有效地通过代码控制线程的执行顺序、延续、取消等。
ThreadPool:基于线程,目的是减少创建线程的数量和管理线程的成本。无法控制线程执行顺序,不能获取线程取消、异常、完成的通知。

异步方法:一个方法被调用时立即返回,获取一个线程来执行该方法内部的业务,调用者无需等该方法执行完毕才继续执行后续内容。
可以将一些不需要立即使用执行产生的结果,比较耗时的任务设为异步执行。

将csv文件作为TextAsset资源读取

读取所有内容到字符串中

var str = textAsset.text;

读取每行,换行符"\r\n",剔除空白行

var rowContent = str.Split("\r\n", System.StringSplitOptions.RemoveEmptyEntries);

读取每行内的每个元素,csv间隔符',',剔除空白内容(根据实际需求)

var elements = rowContent.Split(',', System.StringSplitOptions.RemoveEmptyEntries);

修改并存储TextAsset文件

    private void SetTextAsset(TextAsset textAsset, string str)
    {
        // 若path不存在则创建->写入->关闭;若存在则打开->覆盖->关闭。
        File.WriteAllText(AssetDatabase.GetAssetPath(textAsset), str);
        AssetDatabase.Refresh();
    }

编辑器模式下修改某文件后,将修改内容保存到磁盘中

例如修改了某个ScriptableObject文件,需保存它。

    private void Save(UnityEngine.Object obj)
    {
        EditorUtility.SetDirty(obj);
        UnityEditor.AssetDatabase.SaveAssets();
    }

例子:存储当前时刻

在一个TextAsset文件中,存储每次执行本功能时的时刻。

SaveCurMomentTools.cs

using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEditor;
using System.IO;

public class SaveCurMomentTools : ScriptableWizard
{
    private const string Title = "存储当前时刻";

    [SerializeField]
    private TextAsset _textAsset;

    [MenuItem("Fan的工具/存储当前时刻")]
    private static void Init()
    {
        DisplayWizard<SaveCurMomentTools>(Title, "关闭", "执行");
    }
    private void OnWizardUpdate()
    {
        Debug.Log($"{Title} 窗口的内容发生了变化!");
    }
    private void OnWizardOtherButton()
    {
        SaveMoment();
    }
    private void OnWizardCreate()
    {
        Debug.Log("关闭窗口:" + Title);
    }

    private void SaveMoment()
    {
        if (_textAsset == null)
        {
            ShowTipsWnd("失败", "请配置正确的TextAsset!");
        }
        else
        {
            // 显示当前已存储的内容
            var curCnt = ShowMomentStorageContent(_textAsset);
            // 读取已存储的内容
            var dataStr = _textAsset.text;

            // 存储当前时刻
            var curMoment = System.DateTime.Now.ToString();
            var newStr = (curCnt == 0 ? string.Empty : "\r\n") + curCnt.ToString() + "," + curMoment;
            dataStr += newStr;
            SetTextAsset(_textAsset, dataStr);
            // ShowTipsWnd("成功", "将当前时刻存储到了文件中,请查看确认。", 0.1f);
        }
    }

    private void ShowTipsWnd(string title, string tips, float delaySeconds = 0f)
    {
        if (delaySeconds > 0)
        {
            System.Func<Task> func = async () =>
            {
                await Task.Delay(System.TimeSpan.FromSeconds(delaySeconds));
                ShowTipsWnd(title, tips);
            };
            func();

        }
        else
        {
            ShowTipsWnd(title, tips);
        }
    }
    private void ShowTipsWnd(string title, string tips)
    {
        UnityEditor.EditorUtility.DisplayDialog(title, tips, "好的");
    }

    private int ShowMomentStorageContent(TextAsset textAsset)
    {
        int curCnt = 0;
        foreach (var content in textAsset.text.Split("\r\n", System.StringSplitOptions.RemoveEmptyEntries))
        {
            var c = content.Split(',', System.StringSplitOptions.RemoveEmptyEntries);
            if (int.TryParse(c[0], out int index))
            {
                string curMoment = c[1];
                Debug.Log(index + ":" + curMoment);
                curCnt++;
            }
        }
        return curCnt;
    }

    private void SetTextAsset(TextAsset textAsset, string str)
    {
        // 若path不存在则创建->写入->关闭;若存在则打开->覆盖->关闭。
        File.WriteAllText(AssetDatabase.GetAssetPath(textAsset), str);
        // Save(textAsset);
        AssetDatabase.Refresh();
    }

    private void Save(UnityEngine.Object obj)
    {
        EditorUtility.SetDirty(obj);
        UnityEditor.AssetDatabase.SaveAssets();
    }
}

相关文章

网友评论

      本文标题:Unity中,制作编辑器内简单的工具窗口

      本文链接:https://www.haomeiwen.com/subject/sakqidtx.html