Unity 通过配置文件生成代码

news2024/9/22 4:04:38

文章目录

      • 示例1:基于ScriptableObject的配置生成类
      • 示例2:预制体路径列表生成加载代码
      • 示例3:动画剪辑生成动画控制器片段
      • 示例4:Excel配置表生成序列化类
      • 示例5:UI元素及其事件绑定生成代码

在Unity编辑器模式下,根据配置文件动态生成代码可以通过编写自定义编辑器脚本实现。以下是一些场景下的5个简化示例,分别说明如何基于不同的配置数据来生成对应的C#代码:

示例1:基于ScriptableObject的配置生成类

using UnityEngine;
using UnityEditor;
using System.IO;

[CreateAssetMenu(fileName = "NewConfig.asset", menuName = "Configuration/New Config")]
public class ConfigurationSO : ScriptableObject
{
    public string[] GameObjectNames;

    [MenuItem("Assets/Generate Code From Config")]
    static void GenerateCode()
    {
        var config = Selection.activeObject as ConfigurationSO;
        if (config != null)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var name in config.GameObjectNames)
            {
                sb.AppendLine($"public GameObject {name};");
            }

            string className = "GeneratedConfig";
            string filePath = Path.Combine(Application.dataPath, $"Scripts/{className}.cs");
            File.WriteAllText(filePath, $@"
using UnityEngine;

public class {className}
{{
    {sb.ToString()}
}}
");

            AssetDatabase.Refresh();
        }
        else
        {
            Debug.LogError("Please select a ConfigurationSO asset.");
        }
    }
}

这个例子中,我们创建了一个ScriptableObject类型ConfigurationSO,其中包含一个字符串数组用于存储游戏对象名称。当用户通过菜单命令“Assets/Generate Code From Config”执行时,会根据这些名称动态生成一个新的C#类,该类包含了与配置中每个名称相对应的游戏对象字段。

示例2:预制体路径列表生成加载代码

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

public class PrefabLoaderGenerator : Editor
{
    [MenuItem("Assets/Generate Prefab Loader")]
    static void GeneratePrefabLoader()
    {
        var prefabPaths = new List<string>();
        foreach (var guid in Selection.assetGUIDs)
        {
            var path = AssetDatabase.GUIDToAssetPath(guid);
            if (PrefabUtility.GetPrefabAssetType(AssetDatabase.LoadMainAssetAtPath(path)) == PrefabAssetType.Regular)
            {
                prefabPaths.Add(path);
            }
        }

        if (prefabPaths.Count > 0)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < prefabPaths.Count; i++)
            {
                var name = Path.GetFileNameWithoutExtension(prefabPaths[i]);
                sb.AppendLine($"public GameObject {name}Prefab {{ get {{ return Resources.Load(\"{prefabPaths[i]}\") as GameObject; }} }}");
            }

            string className = "PrefabLoader";
            string filePath = Path.Combine(Application.dataPath, $"Scripts/{className}.cs");
            File.WriteAllText(filePath, $@"
using UnityEngine;

public static class {className}
{{
    {sb.ToString()}
}}
");

            AssetDatabase.Refresh();
        }
        else
        {
            Debug.LogError("Please select one or more prefabs.");
        }
    }
}

此例中,选择多个预制体后,编辑器将生成一个静态类,其成员为对应预制体路径的属性,并且返回从Resources目录加载的预制体引用。

示例3:动画剪辑生成动画控制器片段

using UnityEngine;
using UnityEditor;
using UnityEngine.Animations.Rigging;
using System.Linq;

public class AnimationClipControllerGenerator : EditorWindow
{
    [MenuItem("Assets/Generate Animation Controller")]
    static void GenerateController()
    {
        var clips = Selection.objects.OfType<AnimationClip>().ToList();

        if (clips.Any())
        {
            AnimatorController ac = new AnimatorController();
            ac.name = "GeneratedAnimatorController";

            foreach (var clip in clips)
            {
                var stateMachine = ac.layers[0].stateMachine;
                var newState = stateMachine.AddStateMachineBehaviour(typeof(Playables.PlayableState));
                newState.motion = clip;
                newState.name = clip.name;
            }

            string controllerPath = AssetDatabase.GenerateUniqueAssetPath("Assets/_Generated/GeneratedAnimatorController.controller");
            AssetDatabase.CreateAsset(ac, controllerPath);

            // 这里是假设要生成控制代码,但实际AnimatorController不需要额外C#代码控制
            // 若需要,可以写入如切换动画状态的函数代码到指定文件
        }
        else
        {
            Debug.LogError("Please select one or more animation clips.");
        }
    }
}

虽然这个例子并不直接生成C#代码,而是动态地构建了AnimatorController层级结构(Unity内置功能),若需生成相关C#控制代码,则可进一步扩展以根据生成的状态机结构创建相应的C#方法调用逻辑。

示例4:Excel配置表生成序列化类

// 假设我们有一个工具能够读取Excel并转换成TSV格式文本
public class ExcelToCSClassGenerator : Editor
{
    [MenuItem("Assets/Generate C# Class from Excel")]
    static void GenerateClassFromExcel()
    {
        // 省略了读取和解析Excel的过程,假设已得到键值对集合
        Dictionary<string, string> tableData = ReadExcelDataAsDictionary("SettingSrc/Test.xls");

        StringBuilder sb = new StringBuilder();
        sb.AppendLine("using UnityEngine;");
        sb.AppendLine("[System.Serializable]");
        sb.AppendLine("public class ExcelConfig {");

        foreach (var pair in tableData)
        {
            sb.AppendLine($"    public string {pair.Key} {{ get; set; }} = \"{pair.Value}\";");
        }

        sb.Append("}");

        string className = "ExcelConfig";
        string filePath = Path.Combine(Application.dataPath, $"Scripts/{className}.cs");
        File.WriteAllText(filePath, sb.ToString());

        AssetDatabase.Refresh();
    }

    static Dictionary<string, string> ReadExcelDataAsDictionary(string excelPath) 
    {
        // 实现从Excel文件读取数据到字典的方法
        // 这里省略了具体实现细节
        return new Dictionary<string, string>(); // 返回样本空字典,实际应填充数据
    }
}

这里展示了如何根据Excel表格中的键值对生成一个带有属性的C#类,类中属性与Excel表头一一对应。

示例5:UI元素及其事件绑定生成代码

using UnityEngine.UIElements;
using UnityEditor.UIElements;
using UnityEditor;
using System.Linq;

public class UIElementCodeGenerator : EditorWindow
{
    [MenuItem("UI/Generate UI Bindings")]
    static void GenerateUIBindings()
    {
        VisualElement root = GetActiveUIRootElement();
        if (root != null)
        {
            StringBuilder sb = new StringBuilder();
            foreach (VisualElement element in root.Query().OfType<Button>())
            {
                var name = element.name;
                var methodBinding = GetBoundMethodName(element); // 获取绑定的回调方法名
                sb.AppendLine($"public void OnButton_{name}Clicked() {{ /* Call {methodBinding} */ }}");
            }

            string className = "UIBindings";
            string filePath = Path.Combine(Application.dataPath, $"Scripts/UI/{className}.cs");
            File.WriteAllText(filePath, $@"
using UnityEngine;
using UnityEngine.Events;

public class {className} : MonoBehaviour
{{
    {sb.ToString()}
}}
");

            AssetDatabase.Refresh();
        }
    }

    static string GetBoundMethodName(VisualElement element)
    {
        // 省略获取按钮绑定的UnityEvent回调方法名的逻辑
        return "OnButtonClick"; // 返回样本方法名,实际应提取真实方法名
    }

    static VisualElement GetActiveUIRootElement()
    {
        // 获取当前选中的UI根元素,此处省略具体实现
        return null; // 返回样本null,实际应返回UI根元素
    }
}

在这个例子中,我们遍历UI界面元素树,找到所有的按钮并根据它们的名字生成响应的点击事件处理方法,这些方法可以在UI相关的MonoBehaviour脚本中被调用。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

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

相关文章

java并发执行批量插入

java并发执行批量插入 1、mybatis-plus批量插入 long start System.currentTimeMillis();int num 5000; //一次批量插入的数量int j 0;for (int i 0;i<20;i){List<User> userList new ArrayList<>();while (true){j;User user new User();user.setUserP…

美国纳斯达克大屏怎么投放:投放完成需要多长时间-大舍传媒Dashe Media

陕西大舍广告传媒有限公司&#xff08;Shaanxi Dashe Advertising Media Co., Ltd&#xff09;&#xff0c;简称大舍传媒&#xff08;Dashe Media&#xff09;&#xff0c;是纳斯达克在中国区的总代理&#xff08;China General Agent&#xff09;。与纳斯达克合作已经有八年的…

echartstool tips多曲线显示数据处理,保留小数位自定义tooltips样式

位置 options>tooltips>formatter tooltip: {trigger: "axis",axisPointer: {type: "cross",label: {backgroundColor: "#6a7985",},},formatter:(params)>{console.log(params)let str params.forEach((element,index) > {if(ind…

详解SkyWalking前端监控的性能指标

SkyWalking 从8.2.0版本开始支持对前端浏览器端的性能进行监控&#xff0c;不仅可以像以前一样监控浏览器发送给后端服务的与请求&#xff0c;还能看到前端的渲染速度、错误日志等信息——这些信息是获取最终用户体验的最有效指标。实现的方式是引入skywalking-client-js库&…

Jenkins(三):自动化部署SpringBoot项目

前言 在软件开发过程中&#xff0c;自动化部署已经成为不可或缺的一环。Jenkins是一个广泛使用的开源自动化部署工具&#xff0c;它提供了强大的功能和灵活的配置选项&#xff0c;可以帮助开发团队实现高效的持续集成和持续部署。本文将详细介绍如何使用Jenkins自动化部署Spri…

2024/2/3学习记录

微信小程序 小程序中组件的分类 视图容器 view 普通视图区域&#xff0c;类似于 div 常用来实现页面的布局效果。 scroll-view 可滚动的视图区域&#xff0c;常用来实现滚动列表效果 swiper 和 swiper-item 常用 swiper 组件的常用属性 轮播图容器组件和轮播图item组件 基…

京东微前端框架MicroApp简介

一、MicroApp 1.1 MicroApp简介 MicroApp是由京东前端团队推出的一款微前端框架,它从组件化的思维,基于类WebComponent进行微前端的渲染,旨在降低上手难度、提升工作效率。MicroApp无关技术栈,也不和业务绑定,可以用于任何前端框架。 官网链接:https://micro-zoe.gith…

DAY11之有效的括号、删除字符串中的所有相邻重复项和逆波兰表达式求值

有效的括号 20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 由于栈结构的特殊性&#xff0c;非常适合做对称匹配类的题目。 首先要弄清楚&#xff0c;字符串里的括号不匹配有几种情况。 一些同学&#xff0c;在面试中看到这种题目上来就开始写代码&#xff0c;然后…

WPF布局面板

StackPanel StackPanel 是一种常用的布局控件,可以支持水平或垂直排列,但不会换行。当子元素添加到 StackPanel 中时,它们将按照添加的顺序依次排列。默认情况下,StackPanel 的排列方向是垂直的,即子元素将从上到下依次排列。可以使用 Orientation 属性更改排列方向。可以…

幻兽帕鲁服务器自动重启备份-python

幻兽帕鲁服务器自动重启备份-python 1. 前置知识点2. 目录结构3. 代码内容4. 原理解释5. 额外备注 基于python编写的服务器全自动管理工具&#xff0c;能够实现自动定时备份存档&#xff0c;以及在检测到服务器崩溃之后自动重新启动&#xff0c;并且整合了对于frp端口转发工具的…

web 技术栈有哪些?

前端技术栈&#xff1a; HTML&#xff08;超文本标记语言&#xff09;&#xff1a; 用于创建网页结构的标记语言&#xff0c;定义页面的内容和结构。 CSS&#xff08;层叠样式表&#xff09;&#xff1a; 用于设计和排版网页的样式表语言&#xff0c;负责页面的外观和样式。 …

蓝桥杯嵌入式第七届真题(完成) STM32G431

蓝桥杯嵌入式第七届真题(完成) STM32G431 题目 相关文件 main.c /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief : Main program body**********************…

NuxtJs安装Sass后出现ERROR:Cannot find module ‘webpack/lib/RuleSet‘

最近了解NuxtJs时&#xff0c;发现问题比较多&#xff0c;对于初学者来说是件比较头痛的事。这次是安装sass预处理器&#xff0c;通过命令安装后&#xff0c;出现了ERROR&#xff1a;Cannot find module webpack/lib/RuleSet 错误&#xff0c;于是根据之前经验&#xff0c;对版…

软件测试Bug系列之4个基本步骤(一)

目录 1.发现bug 2.提交bug 3.跟踪bug 4.总结bug 只要你一个测试人员 &#xff0c;就肯定离不开提交bug&#xff0c;跟踪bug的工作 。对于大多数的功能测试人员来说 &#xff0c;占比最多的工作就是和bug打交道 。可以说它是我们最重要的一块业绩 。所以&#xff0c;有必要静…

Python 连接 mysql 详解(mysql-connector-python)

文章目录 1 概述1.1 第三方库&#xff1a;mysql-connector-python1.2 可视化工具&#xff1a;navicat1.3 创建测试数据库 2 连接 mysql 数据库2.1 创建一个连接2.2 捕获连接异常2.3 从配置文件中获取连接信息 3 执行 sql 语句3.1 插入、更新、删除3.2 查询 1 概述 1.1 第三方库…

MySQL 小技巧:使用 xtrabackup 2.4 实现 完全备份及还原

演示&#xff1a;使用 xtrabackup 2.4 实现 完全备份及还原 本案例基于 CentOS 7 的 Mariadb5.5 实现&#xff0c;也支持 MySQL5.5 和 MySQL5.7 1) 安装 xtrabackup 包 // 先安装 Mariadb5.5 和 xtrabackup 包 [rootcentos7 ~] yum install mariadb-server -y [rootcentos7 ~]…

备份RK35XX 设备的ubuntu根文件系统的方法

简介 我们使用 RK35XX 提供的SDK包制作了一个完整的 ubuntu 镜像,烧录到设备中,会在设备中安装很多我们需要的软件,运行的一些自己写的脚本和业务程序,当我们有很多台设备时,不可能每台都一个个去安装,此时我们就需要一个工具来备份当前设备的根文件系统,然后再放到 SD…

面试八股文(3)

文章目录 1.HashSet如何检查重复2.comparable和Comparator区别3.ConcurrentHashMap和Hashtable区别4.线程和进程5.并发与并行的区别6.为什么使用多线程7.使用多线程可能带来问题8.线程的生命周期和状态9.什么是上下文切换10.线程死锁11.产生死锁四个条件12.如何避免死锁 1.Hash…

【项目日记(八)】第三层: 页缓存的具体实现(下)

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:项目日记-高并发内存池⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你做项目   &#x1f51d;&#x1f51d; 开发环境: Visual Studio 2022 项目日…

在windows和Linux中的安装 boost 以及 安装 muduo 和 mysql

一、CMake安装 Ubuntu Linux 下安装和卸载cmake 3.28.2版本-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/135960115?spm1001.2014.3001.5501二、安装boost boost官网&#xff1a;boost官网 我下载的boost版本&#xff1a; windows:boost_1_84_0.zipli…