自定义 Unity Scene 的界面工具

介绍

文档中会进行SceneView的自定义扩展,实现显示常驻GUI和添加自定义叠加层(Custom Overlay)。

最近项目开发用回了原生的Unity UI相关内容。对于之前常用的FairyGUI来说,原生的UGUI对于UI同学来讲有些不太方便。再加上这次会进行一些固定的脚本绑定,想在UI制作时直接加进到组件上,所以有了这篇文章。

这篇文章是在制作完工具后进行的提炼,偏向代码方面。

在制作相关工具时,根据UI同学来讲,想做到在场景中能够直接点击创建对应的UI组件,切换、编辑和预览等操作时,工具不会消失。在此基础上又需要加上创建对应UI组件时直接添加好对应的脚本。

之前虽然也写过一些编辑器的扩展,但对于Scene界面涉及的不多。故我直接在网上找了一篇比较符合工具的文章,根据这篇文章做出了第一版的界面工具。引用:unity Scene View扩展之显示常驻GUI - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/124269658

准备

找一些功能图标,方便更直观的查看功能,推荐网站:iconfont-阿里巴巴矢量图标库

将准备好的图标,拷贝到当前工程的编辑器默认资源路径下。示例,我准备的按钮图标(Assets/Editor Default Resources/UITools/icon_button.png)

设置图标的属性为:Editor GUI and Legacy GUI

制作Scene常驻GUI

脚本中涉及到:

1.场景每次调用 OnGUI 方法时接收回调

SceneView.duringSceneGui

2.脚本重新编译后自动执行指定的操作

[DidReloadScripts]

3.编辑器模式下照常执行当前脚本

[ExecuteInEditMode]

4.编辑器执行指定菜单

EditorApplication.ExecuteMenuItem("已经存在的菜单项路径")
// 例子:创建UI按钮
// EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Button");
 1、添加GUI窗口
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
public class SceneTools1 : MonoBehaviour
{private Rect _initPosition = new Rect(50, 50, 0, 0);private readonly GUILayoutOption _winWidth = GUILayout.Width(120);private void Awake(){
#if UNITY_2019_1_OR_NEWERSceneView.duringSceneGui -= OnSceneViewGui;SceneView.duringSceneGui += OnSceneViewGui;
#elseSceneView.onSceneGUIDelegate -= OnSceneViewGui;SceneView.onSceneGUIDelegate += OnSceneViewGui;
#endif}private void OnSceneViewGui(SceneView obj){Handles.BeginGUI();_initPosition = GUILayout.Window(1, _initPosition, WindowContentFunc, "UI Tools", _winWidth);Handles.EndGUI();}private void WindowContentFunc(int id){GUILayout.Label("当前选中项:");EditorGUI.BeginDisabledGroup(true);EditorGUILayout.ObjectField(Selection.activeTransform, typeof(Transform), true);EditorGUI.EndDisabledGroup();GUI.DragWindow();}private void OnDestroy(){
#if UNITY_2019_1_OR_NEWERSceneView.duringSceneGui -= OnSceneViewGui;
#elseSceneView.onSceneGUIDelegate -= OnSceneViewGui;
#endif}[DidReloadScripts]private static void Reload(){var canvas = FindObjectOfType<SceneTools1>();if (canvas != null){canvas.Awake();}}
}

2、添加GUI按钮
// 添加按钮创建功能
var uiContent = EditorGUIUtility.TrTextContent("按钮", "点击后会创建一个按钮对象", $"Assets/Editor Default Resources/UITools/icon_button.png");
if (GUILayout.Button(uiContent))
{Debug.LogError("创建按钮被点击");// 执行菜单 按钮创建EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Button");
}

注1:可以通过修改GUI按钮风格来达到自己的想要的表现效果,详细的UI菜单执行方法可以在UI包的MenuOptions.cs中查看。

完整代码:

using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
public class SceneTools1 : MonoBehaviour
{private Rect _initPosition = new Rect(50, 50, 0, 0);private readonly GUILayoutOption _winWidth = GUILayout.Width(120);private void Awake(){
#if UNITY_2019_1_OR_NEWERSceneView.duringSceneGui -= OnSceneViewGui;SceneView.duringSceneGui += OnSceneViewGui;
#elseSceneView.onSceneGUIDelegate -= OnSceneViewGui;SceneView.onSceneGUIDelegate += OnSceneViewGui;
#endif}private void OnSceneViewGui(SceneView obj){Handles.BeginGUI();_initPosition = GUILayout.Window(1, _initPosition, WindowContentFunc, "UI Tools", _winWidth);Handles.EndGUI();}private void WindowContentFunc(int id){GUILayout.Label("当前选中项:");EditorGUI.BeginDisabledGroup(true);EditorGUILayout.ObjectField(Selection.activeTransform, typeof(Transform), true);EditorGUI.EndDisabledGroup();var uiContent = EditorGUIUtility.TrTextContent("按钮", "点击后会创建一个按钮对象", $"Assets/Editor Default Resources/UITools/icon_button.png");if (GUILayout.Button(uiContent)){Debug.LogError("创建按钮被点击");// 执行菜单 按钮创建EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Button");}GUI.DragWindow();}private void OnDestroy(){
#if UNITY_2019_1_OR_NEWERSceneView.duringSceneGui -= OnSceneViewGui;
#elseSceneView.onSceneGUIDelegate -= OnSceneViewGui;
#endif}[DidReloadScripts]private static void Reload(){var canvas = FindObjectOfType<SceneTools1>();if (canvas != null){canvas.Awake();}}
}

结果

当具体的功能实现以及同步到UI同学后,在使用的过程中发现了一些小问题。常见的有以下这些

1、工具跟着场景走,如果想要预览和编辑都有工具,需要在预览场景中和UI制作场景中都挂载当前脚本。

2、工具位置不会跟着窗口大小调整,如果调整了Scene窗口的大小可能会导致工具找不到。

3、如果在UI编辑场景中双击预览会导致工具异常。

制作Scene叠加层

为了解决上面的问题,我更换了扩展方案,要创建类似Scene中工具条的那种扩展。经过一番查找终于在官方手册中找到想要的扩展功能:Create your own overlay - Unity 手册 (unity3d.com)icon-default.png?t=N7T8https://docs.unity3d.com/cn/current/Manual/overlays-custom.html

跟着手册的操作执行下来,我如愿的创建了自己的工具条和面板。如图

如果界面中没有出现上面的示意图,在确保代码没有出错以及代码位置正确的情况下,通过点击右上角的三个点或者右键点击Scene标签,弹出工具条相关的菜单,选中自己自定义的菜单名即可。如图:

1、创建自定义工具条

在Editor目录下新建脚本并修改继承类,手册中的示例已经很详细了,这里将手册中的代码给贴了过来方便查看。

using UnityEditor;
using UnityEditor.Overlays;
using UnityEditor.Toolbars;
using UnityEngine;
using UnityEngine.UIElements;
namespace Game.Editor
{[Overlay(typeof(SceneView), "工具条例子")]public class EditorToolbarExample : ToolbarOverlay{[EditorToolbarElement(id, typeof(SceneView))]class DropdownExample : EditorToolbarDropdown{public const string id = "ExampleToolbar/Dropdown";static string dropChoice = null;public DropdownExample(){text = "Axis";clicked += ShowDropdown;}void ShowDropdown(){var menu = new GenericMenu();menu.AddItem(new GUIContent("X"), dropChoice == "X", () =>{text = "X";dropChoice = "X";});menu.AddItem(new GUIContent("Y"), dropChoice == "Y", () =>{text = "Y";dropChoice = "Y";});menu.AddItem(new GUIContent("Z"), dropChoice == "Z", () =>{text = "Z";dropChoice = "Z";});menu.ShowAsContext();}}[EditorToolbarElement(id, typeof(SceneView))]class ToggleExample : EditorToolbarToggle{public const string id = "ExampleToolbar/Toggle";public ToggleExample(){text = "Toggle OFF";this.RegisterValueChangedCallback(Test);}void Test(ChangeEvent<bool> evt){if (evt.newValue){Debug.Log("ON");text = "Toggle ON";}else{Debug.Log("OFF");text = "Toggle OFF";}}}[EditorToolbarElement(id, typeof(SceneView))]class DropdownToggleExample : EditorToolbarDropdownToggle, IAccessContainerWindow{public const string id = "ExampleToolbar/DropdownToggle";public EditorWindow containerWindow { get; set; }static int colorIndex = 0;static readonly Color[] colors = new Color[] { Color.red, Color.green, Color.cyan };public DropdownToggleExample(){text = "Color Bar";tooltip ="Display a color rectangle in the top left of the Scene view. Toggle on or off, and open the dropdown" +"to change the color.";dropdownClicked += ShowColorMenu;SceneView.duringSceneGui += DrawColorSwatch;}void DrawColorSwatch(SceneView view){if (view != containerWindow || !value){return;}Handles.BeginGUI();GUI.color = colors[colorIndex];GUI.DrawTexture(new Rect(8, 8, 120, 24), Texture2D.whiteTexture);GUI.color = Color.white;Handles.EndGUI();}void ShowColorMenu(){var menu = new GenericMenu();menu.AddItem(new GUIContent("Red"), colorIndex == 0, () => colorIndex = 0);menu.AddItem(new GUIContent("Green"), colorIndex == 1, () => colorIndex = 1);menu.AddItem(new GUIContent("Blue"), colorIndex == 2, () => colorIndex = 2);menu.ShowAsContext();}}[EditorToolbarElement(id, typeof(SceneView))]class CreateCube : EditorToolbarButton //, IAccessContainerWindow{public const string id = "ExampleToolbar/Button";public CreateCube(){text = "Create Cube";icon = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/CreateCubeIcon.png");tooltip = "Instantiate a cube in the scene.";clicked += OnClick;}void OnClick(){var newObj = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;Undo.RegisterCreatedObjectUndo(newObj.gameObject, "Create Cube");}}EditorToolbarExample() : base(CreateCube.id,ToggleExample.id,DropdownExample.id,DropdownToggleExample.id){}}
}
2、创建自定义面板

创建自定义面板给的例子比较简单,只是显示个标签。接下来我会贴出之前在使用过程中的一些修改,比如 单行显示,空间组合等等。

先贴上手册中的代码:

using UnityEditor;
using UnityEditor.Overlays;
using UnityEngine.UIElements;
[Overlay(typeof(SceneView), "面板自绘例子", true)]
public class MyToolButtonOverlay : Overlay
{public override VisualElement CreatePanelContent(){var root = new VisualElement() { name = "UI工具面板" };root.Add(new Label() { text = "这是个自定义面板" });return root;}
}

接下来将之前的按钮创建在这个面板中:

using UnityEngine;
using UnityEditor.Toolbars;
using UnityEditor.Overlays;
using UnityEngine.UIElements;
using UnityEditor;
[Overlay(typeof(SceneView), "面板自绘例子", true)]
public class MyToolButtonOverlay : Overlay
{public override VisualElement CreatePanelContent(){var root = new VisualElement() { name = "UI工具面板" };var btn1 = new EditorToolbarButton(){text = "按钮",icon = (Texture2D)EditorGUIUtility.LoadRequired($"Assets/Editor Default Resources/UITools/icon_button.png"),tooltip = "点击后会创建一个按钮对象",clickable = new Clickable(() =>{Debug.LogError("创建按钮被点击");// 执行菜单 按钮创建EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Button");}),};root.Add(btn1);return root;}
}

效果图预览:

可以看到这个外观尺寸和布局都不太合适,尤其在有多个按钮时,可以想想会有多不方便。这时,可以通过修改当前按钮的风格来美化组件。总结了些常用的风格如下:

style =
{color = Color.white, // 修改颜色height = 32,        // 修改高度width = 120,        // 修改宽度marginLeft = 4,     // 修改左边距marginRight = 4,     // 修改右边距marginBottom = 2,    // 修改下边距marginTop = 2,       // 修改上边距borderBottomLeftRadius = 4, // 修改左下角圆角borderBottomRightRadius = 4, // 修改右下角圆角borderTopLeftRadius = 4, // 修改左上角圆角unityTextAlign = TextAnchor.MiddleLeft, // 修改文本对齐方式flexDirection = FlexDirection.Row,  // 修改图文混排的布局方式显示
}

添加风格后的按钮示意图如下:

如果要单独修改按钮上的某个元素的风格时,可以通过方法 ElementAt 传入下标获取到对应的元素组件。比如将图片对齐到按钮左边等等。

var imgBtn1 = btn1.ElementAt(0);
var imgStyle1 = imgBtn1.style;
imgStyle1.width = 32;
imgStyle1.height = 32;
imgStyle1.alignSelf = Align.Center;

改后的效果图:

当一个按钮风格配置好后,如果想要通用当前的按钮,需要扩展当前的按钮类。

private class MyToolbarButton : EditorToolbarButton
{public MyToolbarButton(string name,string iconPath,string tooltip,Action onClick){this.text = name;this.icon = (Texture2D)EditorGUIUtility.LoadRequired(iconPath);this.tooltip = tooltip;this.clicked += onClick;var btnStyle = this.style;btnStyle.color = Color.white;btnStyle.height = 32;btnStyle.width = 120;btnStyle.marginLeft = 4;btnStyle.marginRight = 4;btnStyle.marginBottom = 2;btnStyle.marginTop = 2;btnStyle.borderBottomLeftRadius = 4;btnStyle.borderBottomRightRadius = 4;btnStyle.borderTopLeftRadius = 4;btnStyle.borderTopRightRadius = 4;btnStyle.unityTextAlign = TextAnchor.MiddleLeft;btnStyle.flexDirection = FlexDirection.Row;var imgBtn1 = this.ElementAt(0);var imgStyle1 = imgBtn1.style;imgStyle1.width = 32;imgStyle1.height = 32;imgStyle1.alignSelf = Align.Center;}
}

修改之前的添加按钮代码,改成封装后的按钮,并再添加一个看看效果。

var btn1 = new MyToolbarButton("按钮", "Assets/Editor Default Resources/UITools/icon_button.png", "创建文本对象",() =>{EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Button");});
var btn2 = new MyToolbarButton("文本", "Assets/Editor Default Resources/UITools/icon_text.png", "创建文本对象",() =>{EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Text");});
root.Add(btn1);
root.Add(btn2);

效果图:

效果出来了但这时候会发现,不管添加多少按钮组件,都是垂直向下添加的。如果想让某些组件进行水平显示,又不影响现有布局的情况下,我们可以这样做:

1、创建一个新的VisualElement,加入到根节点,并修改风格中的布局方向:

flexDirection = FlexDirection.Row

2、将需要重新布局的组件添加到当前新的节点中:

var layer = new VisualElement()
{style ={flexDirection = FlexDirection.Row, // 水平marginLeft = 4,marginRight = 4,marginTop = 2,marginBottom = 2,}
};
var btn3 = new MyToolbarButton("图片", "Assets/Editor Default Resources/UITools/icon_image.png", "创建图片对象",() =>{EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Image");});
btn3.style.width = 75;
var btn4 = new MyToolbarButton("原图", "Assets/Editor Default Resources/UITools/icon_image.png", "创建Raw Image对象",() =>{EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Raw Image");});
btn4.style.width = 75;
layer.Add(btn3);
layer.Add(btn4);
root.Add(layer);

示意图查看:

注:如果需要更复杂的布局,可以进行布局嵌套实现。

完整代码:

using System;
using UnityEngine;
using UnityEditor.Toolbars;
using UnityEditor.Overlays;
using UnityEngine.UIElements;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
[Overlay(typeof(SceneView), "面板自绘例子", true)]
public class MyToolButtonOverlay : Overlay
{private class MyToolbarButton : EditorToolbarButton{public MyToolbarButton(string name,string iconPath,string tooltip,Action onClick){this.text = name;this.icon = (Texture2D)EditorGUIUtility.LoadRequired(iconPath);this.tooltip = tooltip;this.clicked += onClick;var btnStyle = this.style;btnStyle.color = Color.white;btnStyle.height = 32;btnStyle.width = 120;btnStyle.marginLeft = 4;btnStyle.marginRight = 4;btnStyle.marginBottom = 2;btnStyle.marginTop = 2;btnStyle.borderBottomLeftRadius = 4;btnStyle.borderBottomRightRadius = 4;btnStyle.borderTopLeftRadius = 4;btnStyle.borderTopRightRadius = 4;btnStyle.unityTextAlign = TextAnchor.MiddleLeft;btnStyle.flexDirection = FlexDirection.Row;var imgBtn1 = this.ElementAt(0);var imgStyle1 = imgBtn1.style;imgStyle1.width = 32;imgStyle1.height = 32;imgStyle1.alignSelf = Align.Center;}}public override VisualElement CreatePanelContent(){var root = new VisualElement() { name = "UI工具面板" };var btn1 = new MyToolbarButton("按钮", "Assets/Editor Default Resources/UITools/icon_button.png", "创建文本对象",() =>{EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Button");});var btn2 = new MyToolbarButton("文本", "Assets/Editor Default Resources/UITools/icon_text.png", "创建文本对象",() =>{EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Text");});root.Add(btn1);root.Add(btn2);var layer = new VisualElement(){style ={flexDirection = FlexDirection.Row, // 水平marginLeft = 4,marginRight = 4,marginTop = 2,marginBottom = 2,}};var btn3 = new MyToolbarButton("图片", "Assets/Editor Default Resources/UITools/icon_image.png", "创建图片对象",() =>{EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Image");});btn3.style.width = 75;var btn4 = new MyToolbarButton("原图", "Assets/Editor Default Resources/UITools/icon_image.png", "创建Raw Image对象",() =>{EditorApplication.ExecuteMenuItem("GameObject/UI/Legacy/Raw Image");});btn4.style.width = 75;layer.Add(btn3);layer.Add(btn4);root.Add(layer);return root;}
}

Overlay的相关知识就分享到这了,如果后续有新的使用经验,会同步到当前文档中。

引用参考

1、unity Scene View扩展之显示常驻GUI - 知乎 (zhihu.com)

2、Create your own overlay - Unity 手册 (unity3d.com)

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

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

相关文章

自定义口令加入群聊怎么弄?用词令关键词直达口令加入微信群延长群二维码7天有效方法

微信口令加入群聊有二种方式 一、微信面对面建群 微信面对面建群的方式适合现实中的朋友之间相互认识且想要建立群聊的场景。微信面对面建群口令加入群聊的有效距离是在几十米范围内&#xff0c;因此只能是附近几十米范围内的人&#xff0c;正确输入微信面对面建群口令后才可…

台球王子,Android小游戏开发

使用 Android Studio 开发了一款休闲游戏 —— 《台球王子》 关键词&#xff1a;台球 A. 项目描述 台球作为一项优雅、策略性强的运动&#xff0c;在众多游戏类型中却相对较少。因此&#xff0c;开发《台球王子》小游戏&#xff0c;可以让更多玩家能够轻松享受到台球的乐趣。…

Python问题列表

文章目录 1、使用pip安装的模块都存放到哪里了&#xff1f;2、安装fitz包报错&#xff0c;如何解决&#xff1f;3、python代码运行时&#xff0c;控制台输出乱码如何解决。4、vscode中第三方库不自动补齐 1、使用pip安装的模块都存放到哪里了&#xff1f; 答&#xff1a; pip是…

易图讯智慧感知应急指挥三维电子沙盘系统设计

易图讯&#xff08;www.3dgis.top&#xff09;智慧感知应急指挥三维电子沙盘系统充分融合了物联网与人工智能识别分析技术&#xff0c;实现了从输入到输出的高效智能响应。在物联网方面&#xff0c;系统通过各类传感器和设备&#xff0c;实时采集环境、设备状态等关键数据&…

Adobe ColdFusion 任意文件读取漏洞复现(CVE-2024-20767)

0x01 产品简介 Adobe ColdFusion是美国奥多比(Adobe)公司的一套快速应用程序开发平台。该平台包括集成开发环境和脚本语言,将可扩展、改变游戏规则且可靠的产品的愿景变为现实。 0x02 漏洞概述 由于 Adobe ColdFusion 的访问控制不当,未经身份认证的远程攻击者可以构造恶…

享道出行:容器弹性技术驱动下的智慧出行稳定性实践

作者&#xff1a;郑嘉扬、何杉 前言 享道出行是一家专注于出行服务的专业品牌&#xff0c;是上汽集团实现汽车产业“新四化”&#xff08;即“电动化、智能网联化、共享化、国际化”&#xff09;的重要组成部分。作为上汽集团移动出行战略品牌&#xff0c;享道出行充分利用全…

【C++】list介绍

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. list介绍2. list的构造3. ist iterator的使用4. capacity5. element access6. modifiers7. 迭代器失效8. Operations8.1 reverse8.2 sort8.3 unique8.4 splice 1. list介绍 list是可以在常数范围内在任意位置进行插…

JumpServer 堡垒主机

JumpServer 堡垒机帮助企业以更安全的方式管控和登陆各种类型的资产 SSH&#xff1a;Linux/Unix/网络设备等Windows&#xff1a;Web方式连接/原生RDP连接数据库&#xff1a;MySQL、Oracle、SQLServer、PostgreSQL等Kubernetes&#xff1a;连接到K8s集群中的PodsWeb站点&#x…

微信小程序wx.navigateTo无法跳转到Component组件问题解决。(共享元素动画必备)

关于Component构造器官方是有文档说明的&#xff0c;然后官方文档内部也给出了组件是可以通过像pages一样跳转的。但是官方文档缺少了必要的说明&#xff0c;会引起wx.navigateTo无法跳转到组件问题&#xff01; 以下是官方文档截图&#xff1a; 解决方式&#xff1a; 组件创建…

吴恩达2022机器学习专项课程(一) 4.2 梯度下降实践

问题预览/关键词 本节内容梯度下降更新w的公式梯度下降更新b的公式的含义α的含义为什么要控制梯度下降的幅度&#xff1f;导数项的含义为什么要控制梯度下降的方向&#xff1f;梯度下降何时结束&#xff1f;梯度下降算法收敛的含义正确更新梯度下降的顺序错误更新梯度下降的顺…

【软件安装】(十四)Ubuntu22.04安装Psensor硬件监视器

一个愿意伫立在巨人肩膀上的农民...... Ubuntu系统硬件运行查询输入指令太繁琐&#xff0c;终端展示不直观&#xff0c;因此这款具有可视化监控Ubuntu系统下当前电脑的硬件CPU&#xff08;中央处理器&#xff09;、GPU&#xff08;显卡&#xff09;和硬盘等温度等功能&#xff…

微信支付平台与微信服务号关联配置要点

目录 JSAPI支付 前期资料及相关准备 申请微信服务号 服务号配置要点 微信认证 基本配置 功能设置 申请微信支付号 支付号配置要点 设置操作密码 API安全 开发设置 与服务号关联 小结 JSAPI支付 我们的开发应用场景以JSAPI支付为举例&#xff0c;这也是常用的一…

Python读取PDF文字转txt,解决分栏识别问题,能读两栏

搜索了一下&#xff0c;大致有这些库能将PDF转txt 1. PyPDF/PyPDF2&#xff08;截止2024.03.28这两个已经合并成了一个&#xff09;pypdf PyPI 2. pdfplumber GitHub - jsvine/pdfplumber: Plumb a PDF for detailed information about each char, rectangle, line, et cete…

MATLAB多级分组绘图及图例等细节处理 ; MATLAB画图横轴时间纵轴数值按照不同sensorCode分组画不同sensorCode的曲线

平时研究需要大量的绘图Excel有时候又臃肿且麻烦 尤其是当处理大量数据时可能会拖死Windows 示例代码及数据量展示 因为数据量是万级别的折线图也变成"柱状图"了, 不过还能看出大致趋势! 横轴是时间纵轴是传感器数值图例是传感器所在深度 % data readtable(C:\U…

Network AIS Receiver R400N

目录 Introduction OVERVIEW BASIC FEATURES APPLICATIONS SPECIFICATIONS Introduction OVERVIEW The R400N provides a method of monitoring the position, speed and heading of AIS vessels within VHF range. It can decode of Class A, Class B, Aids to Navigat…

鸿蒙OS开发实例:【Web网页】

背景 HarmonyOS平台通过Web控件可支持网页加载展示&#xff0c;Web在中是作为专项参考的。 本篇文章将从Android和iOS平台研发角度出发来实践学习API功能 说明 整个示例是以HarmonyOS开发文档网址作为加载目标页面布局增加了三个按钮“后退”&#xff0c;“前进”&#xff…

TransmittableThreadLocal 问题杂记

0、前言 TransmittableThreadLocal&#xff0c;简称 TTL&#xff0c;是阿里巴巴开源的一个Java库&#xff0c;它能够实现ThreadLocal在多线程间的值传递&#xff0c;适用于使用线程池、异步调用等需要线程切换的场景&#xff0c;解决了ThreadLocal在使用父子线程、线程池时不能…

2022 Tesla AI Day -特斯拉自动驾驶FSD的进展和算法软件技术之数据以及虚拟

2022 Tesla AI Day -特斯拉自动驾驶FSD的进展和算法软件技术之数据以及虚拟 附赠自动驾驶学习资料和量产经验&#xff1a;链接 人工智能算法犹如电影的主演&#xff0c;我们很多时候看电影只看到主演们的精彩&#xff0c;但其实电影的创意和呈现都来自于背后的导演和制片等团队…

数论与线性代数——整除分块【数论分块】的【运用】【思考】【讲解】【证明(作者自己证的QWQ)】

文章目录 整除分块的思考与运用整除分块的时间复杂度证明 & 分块数量整除分块的公式 & 公式证明公式证明 代码code↓ 整除分块的思考与运用 整除分块是为了解决一个整数求和问题 题目的问题为&#xff1a; ∑ i 1 n ⌊ n i ⌋ \sum_{i1}^{n} \left \lfloor \frac{n}{…

让工作自动化起来!无所不能的Python

让工作自动化起来&#xff01;无所不能的Python 一、Python是办公自动化的重要工具二、Python是提升职场竞争力的利器三、Python是企业数字化的重要平台四、Python是AI发展的重要通道之一内容简介作者简介前言读者对象如何阅读本书购买链接参与方式 随着我国企业数字化和信息化…