Unity 自定义批量打包工具

打包配置项

using UnityEngine;
using System.Collections.Generic;namespace MYTOOL.Build
{/// <summary>/// 批量打包配置文件/// </summary>[CreateAssetMenu]public class BatchBuildProfile : ScriptableObject{public List<BuildTask> tasks = new List<BuildTask>(0);}
}

打包功能

using UnityEditor;
using UnityEngine;
using System;
using System.IO;
using System.Collections.Generic;namespace MYTOOL.Build
{public class LogMessage{public LogType type;public string message;public LogMessage(LogType type, string message){this.type = type;this.message = message;}}[CustomEditor(typeof(BatchBuildProfile))]public class BatchBuildProfileInspector : Editor{//配置文件private BatchBuildProfile profile;//折叠栏private Dictionary<BuildTask, bool> foldoutMap;//记录日志private List<LogMessage> logsList;private void OnEnable(){profile = target as BatchBuildProfile;foldoutMap = new Dictionary<BuildTask, bool>();logsList = new List<LogMessage>();}public override void OnInspectorGUI(){OnMenuGUI();OnListGUI();serializedObject.ApplyModifiedProperties();if (GUI.changed)EditorUtility.SetDirty(profile);}/// <summary>/// 菜单项/// </summary>private void OnMenuGUI(){EditorGUILayout.HelpBox($"已有打包工作项:{profile.tasks.Count}个", MessageType.Info);EditorGUILayout.HelpBox($"打包时会先进行排序, 优先打包当前平台【{EditorUserBuildSettings.activeBuildTarget}】", MessageType.Info);//限制20个if (profile.tasks.Count < 20){//新建工作项if (GUILayout.Button("新建工作项", GUILayout.Height(30))){Undo.RecordObject(profile, "Create");string buildPath = Path.Combine(Directory.GetParent(Application.dataPath).FullName, ".Build");if (Directory.Exists(buildPath) == false){Directory.CreateDirectory(buildPath);Debug.LogFormat("创建构建目录:{0}", buildPath);}var task = new BuildTask(PlayerSettings.productName, (MyBuildTarget)EditorUserBuildSettings.activeBuildTarget, buildPath);profile.tasks.Add(task);}}else{EditorGUILayout.HelpBox($"无法新建打包工作项", MessageType.Warning);}if (profile.tasks.Count > 0){//清空GUI.color = Color.yellow;if (GUILayout.Button("清空工作项", GUILayout.Height(30))){Undo.RecordObject(profile, "Clear");if (EditorUtility.DisplayDialog("提醒", "是否确认清理所有打包工作项?", "确定", "取消")){Debug.LogWarningFormat("清理{0}个打包工作项", profile.tasks.Count);profile.tasks.Clear();foldoutMap.Clear();}}//开始打包GUI.color = Color.cyan;if (GUILayout.Button("开始打包", GUILayout.Height(30))){if (EditorUtility.DisplayDialog("确认操作", "即将开始打包过程,这可能需要一些时间。您希望继续吗?", "继续", "取消")){logsList.Clear();OnBuild(false);}return;}//清理并打包GUI.color = Color.yellow;if (GUILayout.Button("清理并打包", GUILayout.Height(30))){if (EditorUtility.DisplayDialog("确认操作", "即将进行清理并开始打包过程,这可能需要一些时间。您希望继续吗?", "继续", "取消")){if (EditorUtility.DisplayDialog("重要提醒", "清理操作将移除当前构建平台的所有文件,请确保已备份重要数据。是否要继续?此操作不可逆。", "确定继续", "取消")){logsList.Clear();OnBuild(true);}}return;}}GUI.color = Color.white;//排序if (profile.tasks.Count > 1){if (GUILayout.Button("排序工作项", GUILayout.Height(30))){Debug.Log("排序打包工作项");profile.tasks.Sort(new BuildTaskComparer());return;}}}/// <summary>/// 任务项/// </summary>private void OnListGUI(){for (int i = 0; i < profile.tasks.Count; i++){var task = profile.tasks[i];if (foldoutMap.ContainsKey(task) == false){foldoutMap.Add(task, true);}GUILayout.Space(20);GUILayout.BeginHorizontal("Badge");GUILayout.Space(20);foldoutMap[task] = EditorGUILayout.Foldout(foldoutMap[task], task.ToString(), true);if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash"), "IconButton", GUILayout.Width(20))){Undo.RecordObject(profile, "Delete Task");foldoutMap.Remove(task);profile.tasks.Remove(task);break;}GUILayout.EndHorizontal();//折叠栏if (foldoutMap[task]){GUILayout.BeginVertical("Box");//是否激活GUILayout.BeginHorizontal();GUILayout.Label("是否激活:", GUILayout.Width(70));task.enableTask = GUILayout.Toggle(task.enableTask, "");GUILayout.EndHorizontal();//打包场景GUILayout.BeginHorizontal();GUILayout.Label("打包场景:", GUILayout.Width(70));if (GUILayout.Button("+", GUILayout.Width(20f))){task.sceneAssets.Add(null);}GUILayout.EndHorizontal();//场景列表if (task.sceneAssets.Count > 0){OnSceneAssetsList(task);}//产品名称GUILayout.BeginHorizontal();GUILayout.Label("产品名称:", GUILayout.Width(70));var newPN = GUILayout.TextField(task.productName);if (task.productName != newPN){Undo.RecordObject(profile, "Product Name");task.productName = newPN;}GUILayout.EndHorizontal();//打包平台GUILayout.BeginHorizontal();GUILayout.Label("打包平台:", GUILayout.Width(70));var newBT = (MyBuildTarget)EditorGUILayout.EnumPopup(task.buildTarget);if (task.buildTarget != newBT){Undo.RecordObject(profile, "Build Target");task.buildTarget = newBT;//这些平台只能使用IL2CPPif (task.buildTarget == MyBuildTarget.iOS || task.buildTarget == MyBuildTarget.WebGL || task.buildTarget == MyBuildTarget.WeixinMiniGame){task.scriptMode = ScriptingImplementation.IL2CPP;}//其它平台默认切换到Playerif (task.buildTarget != MyBuildTarget.StandaloneWindows64 && task.buildTarget != MyBuildTarget.StandaloneLinux64 && task.buildTarget != MyBuildTarget.NoTarget){task.buildSubtarget = StandaloneBuildSubtarget.Player;}}GUILayout.EndHorizontal();//Windows Linux添加打包子平台if (task.buildTarget == MyBuildTarget.StandaloneWindows64 || task.buildTarget == MyBuildTarget.StandaloneLinux64){GUILayout.BeginHorizontal();GUILayout.Label("打包子平台:", GUILayout.Width(70));var newBS = (StandaloneBuildSubtarget)EditorGUILayout.EnumPopup(task.buildSubtarget);if (task.buildSubtarget != newBS){Undo.RecordObject(profile, "Build Subtarget");task.buildSubtarget = newBS;}GUILayout.EndHorizontal();}//打包选项GUILayout.BeginHorizontal();GUILayout.Label("打包选项:", GUILayout.Width(70));var newBO = (BuildOptions)EditorGUILayout.EnumFlagsField(task.buildOptions);if (task.buildOptions != newBO){Undo.RecordObject(profile, "Build Options");task.buildOptions = newBO;}GUILayout.EndHorizontal();//脚本模式GUILayout.BeginHorizontal();GUILayout.Label("脚本模式:", GUILayout.Width(70));var newSM = (ScriptingImplementation)EditorGUILayout.EnumPopup(task.scriptMode);if (task.scriptMode != newSM){Undo.RecordObject(profile, "Script Mode");task.scriptMode = newSM;}GUILayout.EndHorizontal();//打包路径GUILayout.BeginHorizontal();GUILayout.Label("打包路径:", GUILayout.Width(70));GUILayout.TextField(task.buildPath);if (GUILayout.Button("浏览", GUILayout.Width(40f))){string path = EditorUtility.SaveFolderPanel("Build Path", task.buildPath, "");if (!string.IsNullOrWhiteSpace(path)){task.buildPath = path;}GUIUtility.ExitGUI();}GUILayout.EndHorizontal();//安卓平台添加其它选项if (task.buildTarget == MyBuildTarget.Android){GUILayout.BeginHorizontal();GUILayout.Label("keystore:", GUILayout.Width(70));PlayerSettings.Android.keystorePass = EditorGUILayout.PasswordField(PlayerSettings.Android.keystorePass);GUILayout.EndHorizontal();GUILayout.BeginHorizontal();GUILayout.Label("keyalias:", GUILayout.Width(70));PlayerSettings.Android.keyaliasPass = EditorGUILayout.PasswordField(PlayerSettings.Android.keyaliasPass);GUILayout.EndHorizontal();//导出工程GUILayout.BeginHorizontal();GUILayout.Label("导出工程:", GUILayout.Width(70));EditorUserBuildSettings.exportAsGoogleAndroidProject = GUILayout.Toggle(EditorUserBuildSettings.exportAsGoogleAndroidProject, "");GUILayout.EndHorizontal();}GUILayout.EndVertical();}}}private void OnSceneAssetsList(BuildTask task){GUILayout.BeginHorizontal();GUILayout.Space(75);GUILayout.BeginVertical("Badge");for (int j = 0; j < task.sceneAssets.Count; j++){var sceneAsset = task.sceneAssets[j];GUILayout.BeginHorizontal();GUILayout.Label($"{j + 1}.", GUILayout.Width(20));task.sceneAssets[j] = EditorGUILayout.ObjectField(sceneAsset, typeof(SceneAsset), false) as SceneAsset;if (GUILayout.Button("↑", "MiniButtonLeft", GUILayout.Width(20))){if (j > 0){Undo.RecordObject(profile, "Move Up Scene Assets");var temp = task.sceneAssets[j - 1];task.sceneAssets[j - 1] = sceneAsset;task.sceneAssets[j] = temp;}}if (GUILayout.Button("↓", "MiniButtonMid", GUILayout.Width(20))){if (j < task.sceneAssets.Count - 1){Undo.RecordObject(profile, "Move Down Scene Assets");var temp = task.sceneAssets[j + 1];task.sceneAssets[j + 1] = sceneAsset;task.sceneAssets[j] = temp;}}if (GUILayout.Button("+", "MiniButtonMid", GUILayout.Width(20))){Undo.RecordObject(profile, "Add Scene Assets");task.sceneAssets.Insert(j + 1, null);break;}if (GUILayout.Button("-", "MiniButtonMid", GUILayout.Width(20))){Undo.RecordObject(profile, "Delete Scene Assets");task.sceneAssets.RemoveAt(j);break;}GUILayout.EndHorizontal();}GUILayout.EndVertical();GUILayout.EndHorizontal();}/// <summary>/// 开始打包/// </summary>/// <param name="clearBuild">清理旧的构建</param>private void OnBuild(bool clearBuild){//排序,优先当前平台的任务profile.tasks.Sort(new BuildTaskComparer());//旧版本号string oldVersion = PlayerSettings.bundleVersion;//新版本号string newVersion = GetNewVersion();try{for (int i = 0; i < profile.tasks.Count; i++){var task = profile.tasks[i];if (task.enableTask == false || task.buildTarget == MyBuildTarget.NoTarget){logsList.Add(new LogMessage(LogType.Log, $"跳过: {task}"));continue;}BuildTarget buildTarget = (BuildTarget)task.buildTarget;BuildTargetGroup targetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget);BuildPlayerOptions buildPlayerOptions = SetBuildParams(targetGroup, task);EditorUtility.DisplayProgressBar("正在打包", profile.tasks[i].ToString(), (float)i + 1 / profile.tasks.Count);if (string.IsNullOrEmpty(buildPlayerOptions.locationPathName)){throw new Exception(($"无法打包 {task},产品名称可能为空"));}if (buildPlayerOptions.scenes.Length == 0){throw new Exception($"无法打包 {task},打包场景为空");}//切换平台if (buildTarget != EditorUserBuildSettings.activeBuildTarget){EditorUserBuildSettings.SwitchActiveBuildTarget(targetGroup, buildTarget);}//设置新版本号PlayerSettings.bundleVersion = newVersion;PlayerSettings.SetScriptingBackend(targetGroup, task.scriptMode);string path = Path.GetDirectoryName(buildPlayerOptions.locationPathName);if (clearBuild && Directory.Exists(path)){Directory.Delete(path, true);}if (Directory.Exists(path) == false){Directory.CreateDirectory(path);}//开始打包var report = BuildPipeline.BuildPlayer(buildPlayerOptions);switch (report.summary.result){case UnityEditor.Build.Reporting.BuildResult.Unknown:logsList.Add(new LogMessage(LogType.Error, $"{task} 出现未知错误"));break;case UnityEditor.Build.Reporting.BuildResult.Succeeded:logsList.Add(new LogMessage(LogType.Log, $"{task} 打包耗时: {(report.summary.buildEndedAt - report.summary.buildStartedAt).TotalSeconds}秒"));break;case UnityEditor.Build.Reporting.BuildResult.Failed:string errorMsg = "";foreach (var file in report.GetFiles()){errorMsg += file.path + "\n";}foreach (var step in report.steps){foreach (var stepmsg in step.messages){errorMsg += "\n" + stepmsg.content;}errorMsg += "\n";}logsList.Add(new LogMessage(LogType.Error, $"{task} 打包失败: {errorMsg}"));break;case UnityEditor.Build.Reporting.BuildResult.Cancelled:logsList.Add(new LogMessage(LogType.Log, $"{task} 取消打包"));break;}//打包成功,打开目录并记录版本号if (report.summary.result == UnityEditor.Build.Reporting.BuildResult.Succeeded){File.WriteAllText(string.Format("{0}/version.txt", path), newVersion);Application.OpenURL(path);}}}catch (Exception ex){//异常情况下还原版本号PlayerSettings.bundleVersion = oldVersion;Debug.LogFormat("还原打包版本号:{0}", oldVersion);Debug.LogException(ex);}finally{EditorUtility.ClearProgressBar();Debug.LogFormat("当前打包版本号:{0}", newVersion);foreach (var log in logsList){Debug.unityLogger.Log(log.type, log.message);}logsList.Clear();}}/// <summary>/// 获取新版本号/// </summary>/// <returns></returns>private string GetNewVersion(){try{Version version = new Version(PlayerSettings.bundleVersion);int major = version.Major;              //主版本int minor = version.Minor;              //次版本int build = version.Build;              //构建版本int revision = version.Revision + 1;    //修订版本if (revision >= 100){build += 1;revision = 0;}if (build >= 100){minor += 1;build = 0;}if (minor >= 100){major += 1;minor = 0;}return $"{major}.{minor}.{build}.{revision}";}catch (Exception){return "1.0.0.0";}}/// <summary>/// 设置构建参数/// </summary>/// <param name="targetGroup"></param>/// <param name="task"></param>/// <returns></returns>private BuildPlayerOptions SetBuildParams(BuildTargetGroup targetGroup, BuildTask task){BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();List<string> levels = new List<string>();string[] activeLevels = EditorBuildSettingsScene.GetActiveSceneList(EditorBuildSettings.scenes);if (activeLevels.Length > 0){levels.AddRange(activeLevels);}for (int i = 0; i < task.sceneAssets.Count; i++){var scenePath = AssetDatabase.GetAssetPath(task.sceneAssets[i]);if (!string.IsNullOrEmpty(scenePath) && !levels.Contains(scenePath)){levels.Add(scenePath);}}buildPlayerOptions.scenes = levels.ToArray();buildPlayerOptions.target = (BuildTarget)task.buildTarget;buildPlayerOptions.subtarget = (int)task.buildSubtarget;buildPlayerOptions.targetGroup = targetGroup;buildPlayerOptions.options = task.buildOptions;buildPlayerOptions.locationPathName = GetBuildTargetPath(task.buildTarget, task.buildSubtarget, task.buildOptions, task.buildPath, task.productName);return buildPlayerOptions;}/// <summary>/// 获取构建路径/// </summary>/// <param name="buildTarget"></param>/// <param name="buildOptions"></param>/// <param name="buildPath"></param>/// <param name="productName"></param>/// <returns></returns>private string GetBuildTargetPath(MyBuildTarget buildTarget, StandaloneBuildSubtarget buildSubtarget, BuildOptions buildOptions, string buildPath, string productName){if (string.IsNullOrEmpty(productName)){return string.Empty;}bool isDevelopment = buildOptions.HasFlag(BuildOptions.Development);string currentDate = DateTime.Now.ToString("yyMMdd");string locationPathName = Path.Combine(buildPath, buildTarget.ToString(), buildSubtarget.ToString(), currentDate, productName);switch (buildTarget){case MyBuildTarget.StandaloneOSX:{if (isDevelopment)locationPathName += "_dev.app";elselocationPathName += ".app";}break;case MyBuildTarget.StandaloneWindows64:{if (isDevelopment)locationPathName += "_dev.exe";elselocationPathName += ".exe";}break;case MyBuildTarget.StandaloneLinux64:{if (isDevelopment)locationPathName += "_dev.x86_64";elselocationPathName += ".x86_64";}break;case MyBuildTarget.Android:{if (isDevelopment)locationPathName += $"_{currentDate}_dev";elselocationPathName += $"_{currentDate}";if (EditorUserBuildSettings.exportAsGoogleAndroidProject == false)locationPathName += ".APK";}break;case MyBuildTarget.iOS:{if (isDevelopment)locationPathName += $"_{currentDate}_dev";elselocationPathName += $"_{currentDate}";}break;}return locationPathName;}}
}

任务配置项

using System;
using System.Collections.Generic;
using UnityEditor;namespace MYTOOL.Build
{/// <summary>/// 打包的目标平台/// </summary>public enum MyBuildTarget{NoTarget = -2,//// 摘要://     Build a macOS standalone (Intel 64-bit).StandaloneOSX = 2,//// 摘要://     Build a Windows 64-bit standalone.StandaloneWindows64 = 19,//// 摘要://     Build a Linux 64-bit standalone.StandaloneLinux64 = 24,//// 摘要://     Build an iOS player.iOS = 9,//// 摘要://     Build an Android .apk standalone app.Android = 13,//// 摘要://     Build to WebGL platform.WebGL = 20,//// 摘要://     Build to WeixinMiniGame platform.WeixinMiniGame = 47,//// 摘要://     Build an OpenHarmony .hap standalone app.OpenHarmony = 48,}/// <summary>/// 打包工作项/// </summary>[Serializable]public class BuildTask{/// <summary>/// 是否激活/// </summary>public bool enableTask;/// <summary>/// 打包的产品名称/// </summary>public string productName;/// <summary>/// 打包的目标平台/// </summary>public MyBuildTarget buildTarget;/// <summary>/// 打包的目标子平台/// </summary>public StandaloneBuildSubtarget buildSubtarget;/// <summary>/// 打包的选项/// </summary>public BuildOptions buildOptions;/// <summary>/// 脚本模式/// </summary>public ScriptingImplementation scriptMode;/// <summary>/// 打包的保存路径/// </summary>public string buildPath;/// <summary>/// 打包的场景列表/// </summary>public List<SceneAsset> sceneAssets;/// <summary>/// 构造函数/// </summary>/// <param name="productName">产品名称</param>/// <param name="buildTarget">目标平台</param>/// <param name="buildPath">保存路径</param>public BuildTask(string productName, MyBuildTarget buildTarget, string buildPath){this.productName = productName;this.buildTarget = buildTarget;this.buildPath = buildPath;enableTask = true;buildSubtarget = StandaloneBuildSubtarget.Player;buildOptions = BuildOptions.CleanBuildCache;scriptMode = ScriptingImplementation.IL2CPP;sceneAssets = new List<SceneAsset>();}public override string ToString(){return string.Format("{0}【{1}】", productName, buildTarget);}}class BuildTaskComparer : IComparer<BuildTask>{public int Compare(BuildTask x, BuildTask y){if ((BuildTarget)x.buildTarget == EditorUserBuildSettings.activeBuildTarget && (BuildTarget)y.buildTarget != EditorUserBuildSettings.activeBuildTarget){return -1; // x排在前}else if ((BuildTarget)x.buildTarget != EditorUserBuildSettings.activeBuildTarget && (BuildTarget)y.buildTarget == EditorUserBuildSettings.activeBuildTarget){return 1; // y排在前}else{return x.buildTarget.ToString().CompareTo(y.buildTarget.ToString());}}}
}

效果图,可以将它锁定在这里,方便后面使用
使用也很简单,选择打包的平台,并设置一些参数。点击开始打包或清理并打包。
注意:打包场景字段是额外添加, 每次打包都会先获取Build Settings里激活的场景,并添加上打包场景中的设置
在这里插入图片描述

其它解释:
有些字段是直接使用Unity的,所以数据是共享的,比如安卓特有的选项,一个地方修改,相对于的位置也发生改变。
构建目录格式:打包路径+打包平台+打包子平台+日期(yyMMdd)
为什么添加打包子平台字段,因为我的项目中需要打包服务端(Dedicated Server)

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

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

相关文章

【JVM-2.3】深入解析JVisualVM:Java性能监控与调优利器

在Java应用的开发和运维过程中&#xff0c;性能监控与调优是不可或缺的环节。无论是排查内存泄漏、分析CPU瓶颈&#xff0c;还是优化线程使用&#xff0c;开发者都需要借助一些强大的工具来辅助诊断。JVisualVM 正是这样一款由Oracle提供的免费工具&#xff0c;它集成了多种性能…

基于大语言模型的组合优化

摘要&#xff1a;组合优化&#xff08;Combinatorial Optimization, CO&#xff09;对于提高工程应用的效率和性能至关重要。随着问题规模的增大和依赖关系的复杂化&#xff0c;找到最优解变得极具挑战性。在处理现实世界的工程问题时&#xff0c;基于纯数学推理的算法存在局限…

计算机网络 (40)域名系统DNS

前言 计算机网络域名系统DNS&#xff08;Domain Name System&#xff09;是互联网的基础技术之一&#xff0c;它负责将人类可读的域名转换为计算机用来通信的数字IP地址。 一、基本概念 DNS的主要目的是将域名解析或翻译为IP地址&#xff0c;使得用户可以通过简单易记的域名来访…

说一说mongodb组合索引的匹配规则

一、背景 有一张1000多万条记录的大表&#xff0c;需要做归档至历史表&#xff0c;出现了大量慢查询。 查询条件是 "classroomId": {$in: ["xxx", "xxx", ..... "xxx","xxx", "xxx" ] }耗时近5秒&#xff0c;且…

C# OpenCV机器视觉:转速测量

在一个看似平常却又暗藏神秘能量的日子里&#xff0c;阿杰正在他那充满科技感的实验室里&#xff0c;对着一堆奇奇怪怪的仪器发呆。突然&#xff0c;手机铃声如一道凌厉的剑气划破寂静&#xff0c;原来是工厂的赵厂长打来的紧急电话&#xff1a;“阿杰啊&#xff0c;咱们工厂新…

【RedisStack】Linux安装指南

【RedisStack】Linux安装指南.md 前言下载解压创建启动文件设置密码把密码设置到环境变量启动/停止相关命令测试&验证官网资料参考资料 前言 Redis Stack是使用Redis的最佳起点。我们将我们必须提供的最好的技术捆绑在一起&#xff0c;形成一个易于使用的软件包。Redis St…

2025-微服务—SpringCloud-1~3

2025-微服务—SpringCloud 第一章、从Boot和Cloud版本选型开始说起1、Springboot版本2、Springcloud版本3、Springcloud Alibaba4、本次讲解定稿版 第二章 关于Cloud各种组件的停更/升级/替换1、微服务介绍2、SpringCloud是什么&#xff1f;能干吗&#xff1f;产生背景&#xf…

深度学习-卷积神经网络反向传播梯度公式推导

这篇文章非常棒&#xff0c;单样本单通道的反向传播梯度公式推导我都理解了。为了防止找不到原网页&#xff0c;所以特复制于此 参考&#xff1a; https://zhuanlan.zhihu.com/p/640697443

MongoDB实践

MongoDB 是什么&#xff1f;— MongoDB 手册 v8.0 现在有一个名为city的集合&#xff0c;里面的结构如下图 一、增删改查操作 1.查询find db.getCollection("city").find({})db.city.find({})db.city.find({city:"广州" });db.city.find({city_id:17,ci…

mycat介绍与操作步骤

文章目录 1.分库分表2.mycat 入门2.1 概述2.2 案例&#xff1a;水平分表1&#xff09;准备工作2&#xff09;配置3&#xff09;启动并测试 3.mycat 配置详解3.1 schema.xml3.2 rule.xml3.3 server.xml 4.mycat 分片&#xff1a;垂直拆分1&#xff09;准备工作2&#xff09;配置…

苹果手机(IOS系统)出现安全延迟进行中如何关闭?

苹果手机&#xff08;IOS系统&#xff09;出现安全延迟进行中如何关闭&#xff1f; 一、设置二、隐私与安全性三、失窃设备保护关闭 一、设置 二、隐私与安全性 三、失窃设备保护关闭

线形回归与小批量梯度下降实例

1、准备数据集 import numpy as np import matplotlib.pyplot as pltfrom torch.utils.data import DataLoader from torch.utils.data import TensorDataset######################################################################### #################准备若干个随机的x和…

【Unity3D日常开发】Unity3D中打开Window文件对话框打开文件(PC版)

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享QQ群&#xff1a;398291828小红书小破站 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 这篇文章继续讲如何使用Unity3D打开Window文…

iOS 逆向学习 - Inter-Process Communication:进程间通信

iOS 逆向学习 - Inter-Process Communication&#xff1a;进程间通信 一、进程间通信概要二、iOS 进程间通信机制详解1. URL Schemes2. Pasteboard3. App Groups 和 Shared Containers4. XPC Services 三、不同进程间通信机制的差异四、总结 一、进程间通信概要 进程间通信&am…

零基础 监控数据可视化 Spring Boot 2.x(Actuator + Prometheus + Grafana手把手) (上)

一、安装Prometheus Releases prometheus/prometheus GitHubhttps://github.com/prometheus/prometheus/releases 或 https://prometheus.io/download/https://prometheus.io/download/ 1. 下载适用于 Windows 的二进制文件&#xff1a; 找到最新版本的发布页面&#xf…

【API】免费调用Qwen-vl2对图像打标

首次调用通义千问API_大模型服务平台百炼(Model Studio)-阿里云帮助中心https://help.aliyun.com/zh/model-studio/getting-started/first-api-call-to-qwen?spma2c4g.11186623.help-menu-2400256.d_0_1_0.8c693048HxtUzZ&scm20140722.H_2840915._.OR_help-T_cn~zh-V_1 一…

CF 371A.K-Periodic Array(Java实现)

题目分析 这里的意思是一共n个值每k个一组循环&#xff0c;最少改变多少个值就能让循环相同 思路分析 我在这里首先想的是二维数组方便观察循环&#xff0c;依据题目即为每一竖列比较&#xff0c;哪一个值出现的最少那么那就是需要更改的次数&#xff0c;(此题在这儿不考虑需要…

信息科技伦理与道德3:智能决策

1 概述 1.1 发展历史 1950s-1980s&#xff1a;人工智能的诞生与早期发展热潮 1950年&#xff1a;图灵发表了一篇划时代的论文&#xff0c;并提出了著名的“图灵测试”&#xff1b;1956年&#xff1a;达特茅斯会议首次提出“人工智能”概念&#xff1b;1956年-20世纪70年代&a…

一路相伴,非凸科技助力第49届ICPC亚洲区决赛

2024年12月27日-29日&#xff0c;第49届国际大学生程序设计竞赛亚洲区决赛在西北工业大学圆满举行。非凸科技再次作为EC Final的主要赞助方&#xff0c;鼎力支持这群心怀梦想的青年才俊&#xff0c;激励他们勇攀科技高峰&#xff0c;实现创新突破。 EC Final参赛名额主要由当…

MPLS原理及配置

赶时间可以只看实验部分 由来&#xff1a;90年代中期&#xff0c;互联网流量的快速增长。传统IP报文依赖路由器查询路由表转发&#xff0c;但由于硬件技术存在限制导致转发性能低&#xff0c;查表转发成为了网络数据转发的瓶颈。 因此&#xff0c;旨在提高路由器转发速度的MPL…