当前位置: 首页 > news >正文

Unity读书系列《Unity3D游戏开发》——拓展编辑器(一)

文章目录

  • 前言
  • 一、扩展Project视图
    • 1、右键扩展菜单(Asset)
    • 2、监听事件
    • 3、拓展布局
  • 二、扩展Hierarchy视图
    • 1、拓展菜单(GameObject)
    • 2、拓展布局
    • 3、重写菜单
  • 三、扩展Inspector视图
    • 1、扩展原生组件
    • 2、扩展继承组件
  • 四、扩展Scene视图
    • 1、绘制辅助元素
    • 2、辅助UI
    • 3、常驻辅助UI
  • 五、扩展Game视图
  • 总结


前言

本篇文章是对前文关于编辑器拓展的探讨的延伸。即使内置的Unity编辑器再强大,也无法满足所有不同产品和游戏的需求。为了解决这个问题,Unity提供了编辑器拓展的API接口。我们可以通过代码反射的方式修改内置的系统编辑器,同时,游戏开发者也可以利用EditorGUI接口编写适合自己的专属游戏编辑器。这涵盖了从简单的一键换字体、材质、一键打包、管理、优化,到复杂的技能编辑器、关卡编辑器等功能。

特别需要注意的是,由于内容涉及较多且较为复杂,会分2节进行详细讨论。在本文的第一部分中,我们将总结最基础和最实用的编辑器拓展知识。

本文所有代码均在Gitee参考工程,如有需要请自取。


一、扩展Project视图

Project视图是掌握Unity项目的生死大权的地方,包括创建、删除等重要操作。在这里,我们可以通过右键点击实现Asset菜单的拓展。在进行这项任务之前,首先需要将脚本文件保存到名为Editor的文件夹下,并引入UnityEditor命名空间。

1、右键扩展菜单(Asset)

右键创建物体

using UnityEngine;
using UnityEditor;public class AssetEditor
{[MenuItem("Assets/Tools/CreateSphere",false,1)]//数值越小越靠前static void Createxx() {GameObject.CreatePrimitive(PrimitiveType.Sphere);}
}

如图我点击CreateSphere按钮就创建了一个球体到场景当中。
在这里插入图片描述

2、监听事件

在大型或规范的项目中,通常会有严格的项目规范,包括对资源的归类等方面。例如,如果你将贴图移动到了脚本文件夹,项目可能会判断这样的操作是不合法的,并阻止你进行修改。
1、监听资源的删除、创建、移动、保存等操作,在进行操作后会输出绑定的委托。

    //监听事件[InitializeOnLoadMethod]static void InitializeOnLoadMethod() {EditorApplication.projectChanged += delegate (){Debug.Log("怎么回事,老弟。你是不是刚动了资源?");};}

嘿嘿,知识点还没完,[InitializeOnLoadMethod]写在方法 前则会使该方法在C#代码编译完成后首先调用。
2、当需要重新具体的删除、创建方法时必须继承UnityEditor.AssetModificationProcessor,具体方法如下:

public class AssetEventEditor : UnityEditor.AssetModificationProcessor
{//监听事件[InitializeOnLoadMethod]static void InitializeOnLoadMethod(){EditorApplication.projectChanged += delegate (){Debug.Log("怎么回事,老弟。你是不是刚动了资源?");};}//监听"双击左键打开资源"事件public static bool IsOpenForEdit(string assetPath, out string message){message = null;Debug.LogFormat("assetPath:{0}", assetPath);return true;//true表示该资源可以打开,false表示不允许打开}//监听"资源即将被创建"事件public static void OnWillCreateEdit(string path){Debug.LogFormat("创建资源的路径:{0}", path);}//监听"资源即将被保存"事件public static string[] OnWillSaveAssets(string[] paths) {if (paths != null){Debug.LogFormat("保存资源的路径:{0}",string.Join(",",paths));}return paths;}//监听"资源即将被移动"事件public static AssetMoveResult OnWillMoveAsset(string oldPath,string newPath) {Debug.LogFormat("资源从路径{0}移动到路径{1}", oldPath,newPath);return AssetMoveResult.DidNotMove;//DidNotMove表示可以移动,DidMove表示不可以移动}//监听"资源即将被删除"事件public static AssetDeleteResult OnWillDeleteAsset(string assetPath) {Debug.LogFormat("资源从路径{0}删除", assetPath);return AssetDeleteResult.DidNotDelete;//DidNotDelete表示可以移动,DidDelete表示不可以移动}}

3、拓展布局

选中资源后出现按钮,并监听按钮的点击事件

    //选中资源后出现按钮,并监听按钮的点击事件[InitializeOnLoadMethod]static void InitializeOnLoadMethod(){EditorApplication.projectWindowItemOnGUI = delegate (string guid, Rect selectionRect){//在Project试图中选择一个资源if (Selection.activeObject && guid == AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(Selection.activeObject))){//设置拓展按钮区域float width = 80f;selectionRect.x += (selectionRect.width - width);selectionRect.y += 2;selectionRect.width = width;GUI.color = Color.red;//点击事件if (GUI.Button(selectionRect,"click")){Debug.LogFormat("点击:{0}", Selection.activeObject.name);}GUI.color = Color.white;}};}

在这里插入图片描述

二、扩展Hierarchy视图

在Hierarchy(层次)视图中,右键点击相当于打开菜单栏的GameObject栏目。

1、拓展菜单(GameObject)

细心的读者已经看出来了,下面代码对比上面写的仅仅将菜单栏目从"Assets"换成了"GameObject"。

    //右键创建物体[MenuItem("GameObject/Tools/CreateSphere", false, 1)]//数值越小越靠前static void Createxx(){GameObject.CreatePrimitive(PrimitiveType.Sphere);}

2、拓展布局

粗心的读者这下也已经看出来了,下面的代码复刻了之前的代码,将 EditorApplication 后的 GUI 委托修改为 Hierarchy 窗口专属的,并将参数从资源的 GUID 变为 instanceID 实例 ID。此外,按钮引入了本地图片。在各种插件中,编辑器引入图片的操作屡见不鲜,有时为了资源规范会整理插件的图标和图片位置,别忘了根据实际情况修改相关代码。
在这里插入图片描述

3、重写菜单

通过以上学习,我们了解了如何在原有基础上扩展编辑器。那么,能否完全重写呢?当然可以。

1、下面,我们将学习如何重新创建 Image 的逻辑。因为在创建 Image 时,Unity 默认会自动勾选 RaycastTarget,如果我们不需要它具有点击功能,就会有额外的性能开销。使用下面的代码,我们可以创建不勾选 RaycastTarget 的 Image。

  //创建Image默认不勾选RaycastTarget[MenuItem("GameObject/UI/Image0")]static void CreateImage() {if (Selection.activeTransform){if (Selection.activeTransform.GetComponentInParent<Canvas>()){Image image = new GameObject("image").AddComponent<Image>();image.raycastTarget = false;image.transform.SetParent(Selection.activeTransform, false);//设置选中状态Selection.activeTransform = image.transform;}}}

完整版会有检测视图是否有Canvas组件,没有则自动创建等功能。

2、重写菜单:

   //重写菜单[InitializeOnLoadMethod]static void StartInitializeOnLoadMethod(){EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;}static void OnHierarchyGUI(int instanceID, Rect selectionRect){//Event.current监听当前事件,如果监听到鼠标抬起则执行自定义事件(也就是我们的自定义菜单)if (Event.current != null && selectionRect.Contains(Event.current.mousePosition) && Event.current.button == 1 && Event.current.type <= EventType.MouseUp){GameObject selectedGameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;//判断是否满足条件if (selectedGameObject){Vector2 mousePosition = Event.current.mousePosition;EditorUtility.DisplayPopupMenu(new Rect(mousePosition.x, mousePosition.y, 0, 0), "Window/Test", null);Event.current.Use();}}}[MenuItem("Window/Test/Test1")]static void Test1(){}[MenuItem("Window/Test/Test2")]static void Test2(){}

重写完成后,右键视图中的实例将会弹出自定义菜单
在这里插入图片描述

三、扩展Inspector视图

Inspector(检视)视图是用来展示组件及资源的详细信息面板。unity自身提供的各类组件的面板能够满足我们正常的需求,但我们偶尔会希望在某些面板上添加快捷按钮或者某些逻辑。

1、扩展原生组件

摄像机是典型的原生组件,我们CustomEditor进行自定义组件,重写OnInspectorGUI在base.OnInspectorGUI()这个原有元素接口上下添加按钮。

using UnityEditor;
using UnityEngine;[CustomEditor(typeof(Camera))]
public class CameraEditor : Editor
{public override void OnInspectorGUI(){if (GUILayout.Button("拓展按钮-上")){}base.OnInspectorGUI(); if (GUILayout.Button("拓展按钮-下")){}}
}

如下便绘制了两个按钮,不过要注意该组件限制了按钮必须加在最上面或者最下面。
在这里插入图片描述

2、扩展继承组件

1、Unity将大量的Editor绘制方法封装进了DLL,通常来讲我们无法调用其中方法。想要解决可以使用反射获取内部对象,然后调用想要使用的未公开的方法。

using System.Reflection;
using UnityEditor;
using UnityEngine;[CustomEditor(typeof(Transform))]
public class TransformEditor : Editor
{private Editor m_Editor;private void OnEnable(){m_Editor = Editor.CreateEditor(target, Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.TransformInspector", true));}public override void OnInspectorGUI(){if (GUILayout.Button("拓展按钮")){}m_Editor.OnInspectorGUI();//原有信息面板// base.OnInspectorGUI();}
}

2、Context菜单
点击组件的设置按钮(或鼠标右键),会弹出Context菜单,里面有Copy、Reset等操作按钮。我们有时候想对特定组件进行自定义的操作,例如我想在Transform的Context菜单添加NewContext按钮,只需更改MenuItem里第一个参数为"CONTEXT/Transform/NewContext"接口。想给Camer加就将Transform替换成Camera,想给所有组件加就替换成"Compoment"。

    [MenuItem("CONTEXT/Transform/New Context")]static void NewContext(MenuCommand menuCommand){Debug.LogFormat("组件名称:{0}",menuCommand.context.name);}

下面演示如何重写特定脚本的系统方法。作者建议最好延迟一帧以防止在编辑模式下代码同步出现问题。在测试 Unity 2021 版本时,貌似没有出现问题。此外,需要注意的是,书中的部分接口可能已经过时,个人已经替换成最新的版本(以2021.3为准)。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ContextScript : MonoBehaviour
{[ContextMenu("Remove Component")]void RemoveComponent(){Debug.Log("RemoveComponent");//等一帧再删除自己,防止引擎底层错误UnityEditor.EditorApplication.delayCall = delegate () {DestroyImmediate(this);};}
}

脚本中使用宏定义(使用宏定义的原因是为了在发布后剔除无效代码),联动脚本中的变量在编辑模式下实现功能。下面代码就让NewContext按钮操作了脚本中的变量——将ContextScript脚本中的str变量从"原始"改成了"原神"。

using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;public class ContextScript : MonoBehaviour
{public string str = "原始";
#if UNITY_EDITOR//宏定义操作脚本变量[MenuItem("CONTEXT/ContextScript/New Context")]static void NewContext(MenuCommand menuCommand){ContextScript contextScript = menuCommand.context as ContextScript;contextScript.str = "原神";}
#endif
}

请添加图片描述

四、扩展Scene视图

Unity的Scene视图是一个用于编辑场景的窗口。在Scene视图中,你可以直观地查看、编辑和组织你的游戏场景。

1、绘制辅助元素

场景编辑中我们有时会需要线段、不同形状的元素来帮助我们快速编辑。下面我们将使用Gizmos.cs工具类绘制简单元素。

using UnityEngine;public class GizmoScirpt : MonoBehaviour
{ //在鼠标点击到脚本挂载的物体的身上的时候运行private void OnDrawGizmosSelected(){Gizmos.color = Color.red;//画线Gizmos.DrawLine(transform.position, Vector3.one);//立方体Gizmos.DrawCube(Vector3.one, Vector3.one);}
}

在这里插入图片描述
我们发现未点击挂载脚本的物体时,立方体和线条消失了。如果想让绘制的物体一直出现,可以使用 OnDrawGizmos 方法。具体用法有很多,比如技能范围展示、地形和陷阱的实际范围绘制等,都能使项目更高效进行。

   //不依赖对象,会一直执行private void OnDrawGizmos(){Gizmos.DrawSphere(transform.position, 2.0f);}

2、辅助UI

我们在Scene视图中可以在各种组件中添加EditorGUI以获得便利。下面演示如何在Scene中给Camer添加位置信息。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;[CustomEditor(typeof(Camera))]
public class GUIEditor : Editor
{private void OnSceneGUI(){Camera camera = target as Camera;if (camera != null){Handles.color = Color.red;Handles.Label(camera.transform.position, camera.transform.position.ToString());Handles.BeginGUI();GUI.backgroundColor = Color.red;if (GUILayout.Button("click",GUILayout.Width(200f))){Debug.LogFormat("click = {0}", camera.name);}GUILayout.Label("Label");Handles.EndGUI();}}
}

在这里插入图片描述

最后注意如果你的脚本不生效,可能是该脚本与CameraEditor脚本互斥冲突,因为都用了"[CustomEditor(typeof(Camera))]",默认先创建的脚本会生效。

3、常驻辅助UI

常驻辅助UI或者说固定辅助UI,顾名思义,无需游戏对象即可常驻Scene视图,有些类似OnDrawGizmosSelected和OnDrawGizmos。

using UnityEngine;
using UnityEditor;//常驻辅助UI
public class GUIEditor2 : MonoBehaviour
{[InitializeOnLoadMethod]static void InitializeOnLoadMethod() {SceneView.duringSceneGui += delegate (SceneView sceneView){Handles.BeginGUI();GUI.Label(new Rect(0, 0, 50f, 50f), "标题");GUI.Button(new Rect(0, 20f, 50f, 50f), AssetDatabase.LoadAssetAtPath<Texture>("Assets/unity.png"));Handles.EndGUI();};}
}

如下,Scene视图左上角多出了一个UI
在这里插入图片描述

五、扩展Game视图

通常来讲运行游戏才能执行脚本的生命周期。如果想在非运行模式下也可以执行脚本,在脚本上添加[ExecuteInEditMode],那么该脚本可以在编辑模式下生效,如果不想在发布后出现可以使用宏定义来剔除。

using UnityEngine;#if UNITY_EDITOR//编辑器模式下依然执行生命周期
[ExecuteInEditMode]
public class GameScript : MonoBehaviour
{private void OnGUI(){if (GUILayout.Button("Click")){Debug.Log("Click");}GUILayout.Label("Click!");}
}#endif

总结

累死了,本篇详细讲述了 Unity 编辑器的五大视图的拓展方法。原本想分为多篇,但为了整体性,将其整合在一起。下一篇文章字数减少但会更加深入地探讨,并详细解释面板和编辑器源码的相关内容。有不愿透露姓氏的杨姓砖家建议认真阅读完本篇并亲自进行代码试验,然后再查看下一篇。
创作不易,觉得有用的请大家多点赞、评论、收藏,毕竟不收钱,甚至说不定因为哪个知识点恰巧能在面试里帮助到你,提升你的薪资,哈哈。

相关文章:

Unity读书系列《Unity3D游戏开发》——拓展编辑器(一)

文章目录 前言一、扩展Project视图1、右键扩展菜单&#xff08;Asset&#xff09;2、监听事件3、拓展布局 二、扩展Hierarchy视图1、拓展菜单&#xff08;GameObject&#xff09;2、拓展布局3、重写菜单 三、扩展Inspector视图1、扩展原生组件2、扩展继承组件 四、扩展Scene视图…...

【Git】项目管理笔记

文章目录 本地电脑初始化docker报错.gitignoregit loggit resetgit statusgit ls-filesgit rm -r -f --cached拉取仓库文件更新本地的项目报错处理! [rejected] master -> master (fetch first)gitgitee.com: Permission denied (publickey).error: remote origin already e…...

中文词性标注工具pkuseg例子(运行结果,不太好)

pkuseg_demo.md pkuseg 预训练模型 预训练模型science 安装 pip3 install pkuseg cd /rot/pkuseg_home/model/wget https://github.com/lancopku/pkuseg-python/releases/download/v0.0.25/science.zip uzip science.zip -d ./science/ ls /rot/pkuseg_home/model/science/…...

获取URL参数:split方法、URLSearchParams方法示例

在JavaScript中&#xff0c;可以使用多种方法来获取URL参数&#xff0c;其中常用的方法有split()和URLSearchParams()。 使用split()方法获取URL参数&#xff1a; split()方法将字符串分割成数组。可以使用split()方法将URL分割成协议、主机、路径和查询字符串等部分。然后可…...

SparkSql---用户自定义函数UDFUDAF

文章目录 1.UDF2.UDAF2.1 UDF函数实现原理2.2需求:计算用户平均年龄2.2.1 使用RDD实现2.2.2 使用UDAF弱类型实现2.2.3 使用UDAF强类型实现 1.UDF 用户可以通过 spark.udf 功能添加自定义函数&#xff0c;实现自定义功能。 如&#xff1a;实现需求在用户name前加上"Name:…...

系统架构15 - 软件工程(3)

软件过程模型 瀑布模型特点缺点 原型化模型特点两个阶段不同类型注意 螺旋模型V 模型特点 增量模型特点 喷泉模型基于构件的开发模型(CBSD)形式化方法模型敏捷模型特点“适应性” (adaptive) 而非“预设性” (predictive)“面向人的” (People-oriented) 而非“面向过程的” (P…...

两个近期的计算机领域国际学术会议(软件工程、计算机安全):欢迎投稿

近期&#xff0c;受邀担任两个国际学术会议的Special session共同主席及程序委员会成员&#xff08;TPC member&#xff09;&#xff0c;欢迎广大学界同行踊跃投稿&#xff0c;分享最新研究成果。期待这个夏天能够在夏威夷檀香山或者加利福尼亚圣荷西与各位学者深入交流。 SERA…...

(二十一)Flask之上下文管理第二篇(细细扣一遍源码)

每篇前言&#xff1a; &#x1f3c6;&#x1f3c6;作者介绍&#xff1a;【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者 &#x1f525;&#x1f525;本文已收录于Flask框架从入门到实战专栏&#xff1a;《Flask框架从入…...

Java项目:基于SSM框架实现的企业员工岗前培训管理系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm821基于ssm框架实现的企业员工岗前培训管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格…...

深入了解Redis:选择适用于你的场景的持久化方案

自然语言处理的发展 文章目录 自然语言处理的发展强烈推荐前言&#xff1a;Redis提供了几种主要的持久化方案&#xff1a;RDB快照持久化&#xff1a;工作原理&#xff1a; AOF日志文件持久化&#xff1a;混合持久化&#xff1a; 总结强烈推荐专栏集锦写在最后 强烈推荐 前些天…...

【Git配置代理】Failed to connect to github.com port 443 问题解决方法

前言&#xff1a; 在学习代码审计时&#xff0c;有时会需要使用git去拉取代码&#xff0c;然后就出现了如下错误 看过网上很多解决方法&#xff0c;觉得问题的关键还是因为命令行在拉取/推送代码时并没有使用VPN进行代理。 解决办法 &#xff1a; 配置http代理&#xff1a;…...

python提取word文档内容的示例

一、微软Word历史、背景&#xff1a; Word 的特异功能就是把那些应该写成简单的 TXT 或 PDF 格式的文件&#xff0c;变成了既大又慢且难以打开的怪兽&#xff0c;它们经常在系统切换和版本切换中出现格式不兼容&#xff0c;而且因为某些原因在文件内容已经定稿后仍处于可编辑的…...

MarkDown快速入门-以Obsidian编辑器为例

直接上图&#xff0c;左右对应。 首先是基础语法。 # 标题&#xff0c;几个就代表几级标题&#xff1b;* 单个是序号&#xff0c;两个在一起就是斜体&#xff1b;- [ ] 代表任务&#xff0c;注意其中的空格&#xff1b; 然后是表格按钮代码 | 使用中竖线代表表格&#xff0c…...

【计算机网络】协议,电路交换,分组交换

定义了在两个或多个通信实体之间交换的报文格式和次序,以及报文发送和/或接收一个报文或其他事件所采取的动作.网络边缘: 端系统 (因为处在因特网的边缘) 主机 端系统 客户 client服务器 server今天大部分服务器都属于大型数据中心(data center)接入网(access network) 指将端…...

加速应用开发:低代码云SaaS和源码交付模式如何选

随着数字化转型的加速&#xff0c;企业对于快速开发和交付高质量应用的需求也越来越迫切。为了满足这一需求&#xff0c;开发者们开始探索采用低代码平台进行软件开发工作&#xff0c;以加速应用开发过程。 目前&#xff0c;市场上的低代码产品众多&#xff0c;但基本可分为简单…...

ATT汇编

指令后缀 AT&T格式的汇编指令有不同的后缀 其中 b表示byte&#xff0c;字节 w表示word&#xff0c;字/两字节 l表示long&#xff0c;32位系统下的long是4字节 q表示quad&#xff0c;意味四重&#xff0c;表示4个字/8字节 寄存器用途 参见 AT&T的汇编世界 - Gemfield…...

java split 拆分字符串

今天突然把java里split 跟&#xff0c;kotlin中的split 弄混了 kotlin中split 的用法跟python 中的split 用法是一样的&#xff0c;java中由于返回值是String[] 的数组&#xff0c;所以 在使用的时候需要注意下返回值如果要获取里面的内容&#xff0c;还是需要遍历下里面的内…...

【InternLM 大模型实战】作业与笔记汇总

笔记1&#xff1a;https://blog.csdn.net/weixin_42567071/article/details/135375937 笔记2&#xff1a;https://blog.csdn.net/weixin_42567071/article/details/135423120 作业2&#xff1a;https://github.com/xiaomile/InternLM-homework/tree/main/%E4%BD%9C%E4%B8%9A1 笔…...

解析PreMaint在石油化工设备预测性维护领域的卓越表现

石油化工行业一直在寻找能够确保设备高效运行的先进维护解决方案。在这个领域&#xff0c;PreMaint以其卓越的性能和创新的技术引起了广泛关注。 一、为何选择预测性维护&#xff1f; 传统的维护方法&#xff0c;基于固定的时间表&#xff0c;无法灵活应对设备的真实运行状况。…...

C++面试宝典第25题:阶乘末尾零的个数

题目 给定一个整数n,返回n!(n的阶乘)结果尾数中零的个数。 示例 1: 输入:3 输出:0 解释:3! = 6,尾数中没有零。 示例 2: 输入:5 输出:1 解释:5! = 120,尾数中有1个零。 解析 这道题主要考察应聘者对于数学问题的分析和理解能力,以及在多个解决方案中,寻求最优…...

PCIE 4.0 Equalizaiton(LTSSM 均衡流程)

1. 均衡 在Tx端有FFE&#xff08;Feed Forward Equalizer&#xff0c;前馈均衡器&#xff09;&#xff1b;在Rx端有&#xff1a;CTLE&#xff08;Continuous Time Linear Equalizer&#xff0c;连续时间线性均衡器&#xff09;和DFE&#xff08;Decision Feedback Equalizer&a…...

[libwebsockets]lighttpd+libwebsockets支持ws和wss配置方法说明

libwebsockets介绍 libwebsockets是一款轻量级用来开发服务器和客户端的C库。它不仅支持ws,wss还同时支持http与https,可以轻轻松松结合openssl等库来实现ssl加密。 官方参考链接: https://libwebsockets.org/ lighttpd版本 lighttpd/1.4.59 (ssl) - a light and fast w…...

常用软件安装

服务器版本为Centos7.8 x86_64 1.yum下载提速 1.wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 2. yum clean all 3.yum makecache2.jdk yum install java-1.8.0-openjdk* -y # yum update 时自动更新jdk版本 1.yum -y install …...

翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二 1. 将任何静态图表转换为动态数据可视化 ChatGPT Vision 不仅可以将涂鸦变成功能齐全的 Streamlit 应用程序&#xff0c;还…...

Qt QPlainTextEdit高亮显示当前行

Qt QPlainTextEdit高亮显示当前行 文章目录 Qt QPlainTextEdit高亮显示当前行摘要错误的代码正确的代码QTextEdit::ExtraSelection 关键字&#xff1a; Qt、 QPlainTextEdit、 QTextBlock、 ExtraSelection、 GPT 摘要 今天要在说一下GPT&#xff0c;当下如果你还不会用G…...

Linux编辑器vim(含vim的配置)

文章目录 前言vim的基本概念vim基本操作进入vim模式切换退出vim vim指令vim命令模式指令vim底行模式命令 简单vim配置 前言 本篇文章&#xff0c;小编将介绍Linux编辑器–>vim以及vim的配置。 vim的基本概念 正常/普通/命令模式(Normal mode) 控制屏幕光标的移动&#xf…...

Oracle DG环境下的秘钥管理

今天有朋友问到1&#xff09;DG环境下的秘钥管理需要注意什么&#xff0c;2&#xff09;秘钥管理对DG的日志同步有影响吗&#xff1f; 对于2&#xff09;的回答是明确的&#xff0c;没有影响。秘钥的管理和DG的redo log shipping完全是两套机制。在最新版的Oracle Key Vault常…...

【Sql Server】新手一分钟看懂在已有表基础上增加字段和说明

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…...

亚信安慧AntDB打造开放创新的数据库生态

在当今信息化快速发展的时代背景下&#xff0c;亚信安慧AntDB作为一种新兴的DBMS&#xff0c;以其核心优势引起了行业内的广泛关注。它基于具有广泛全球影响力和繁荣社区支持的PostgreSQL(PG)内核&#xff0c;继承了PG的开放性与生态活力&#xff0c;同时在性能和稳定性方面进行…...

在Mixamo网站上,下载的动画导入unity给自己的模型添加后出错怎么解决

在Mixamo网站上&#xff0c;下载的动画导入unity给自己的模型添加后出错 一、在Mixamo下载的模型可以正常使用二、在自己的模型和unity自带模型上就出错1.解决方法2.解决成功 注意 一、在Mixamo下载的模型可以正常使用 二、在自己的模型和unity自带模型上就出错 1.解决方法 选…...