自定义 Unity Scene 的界面工具

news2024/11/23 22:05:24

介绍

文档中会进行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_NEWER
        SceneView.duringSceneGui -= OnSceneViewGui;
        SceneView.duringSceneGui += OnSceneViewGui;
#else
        SceneView.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_NEWER
        SceneView.duringSceneGui -= OnSceneViewGui;
#else
        SceneView.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_NEWER
        SceneView.duringSceneGui -= OnSceneViewGui;
        SceneView.duringSceneGui += OnSceneViewGui;
#else
        SceneView.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_NEWER
        SceneView.duringSceneGui -= OnSceneViewGui;
#else
        SceneView.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.coloradmin.cn/o/1562124.html

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

相关文章

圈子小程序源码-圈子系统成品搭建-APP小程序H5三端源码交付,支持二开!PHP书写,uniAPP后端开发!

【首页】 圈子列表页可分为个人圈子、企业圈子、加入圈子、智诚工业圈子 (平台圈) 四种。 其中重要圈子可选择置顶&#xff0c;方便快速进入:个人圈子和企业圈子数量有限始终位于前位。也可通过搜索快速搜索圈子。 为了实现流量分散入口的集中&#xff0c;将创建企业圈子、发…

服务器设置了端口映射之后外网还是访问不了服务器

目录 排查思路参考&#xff1a; 1、确认服务是否在运行 2、确认端口映射设置是否正确 3、使用防火墙测试到服务器的连通性 4、检查服务内部的配置 5、解决办法 6、学习小分享 我们在一个完整的网络数据存储服务系统设备中都会存有业务服务器、防火墙、交换机、路由器&a…

缓存(反向代理)服务器-varnish

varnish简介&#xff1a; varnish是一款高性能且开源的反向代理服务器和HTTP加速器&#xff0c;&#xff08;其实就是带缓存的反向代理服务器&#xff09;它可以把整个HTTP响应内容缓存到内存或文件中&#xff0c;从而提高web服务器器的响应速度。 与传统的squid相比&#xff0…

electron 打不同环境的包

我用的打包工具: electron-builder 1、在package.json 文件的同级下创建2个js文件 electron-builder-test.config.js electron-builder.config.js electron-builder-test.config.js const basejson require(./electron-builder.config.js); module.exports {extraMetada…

【opencv】教程代码 —features2D(6)透视矫正:读取两个棋盘格图片并进行图像对齐...

perspective_correction.cpp 透视校正 hconcat(img2, img1_warp, img_draw_warp); hconcat(img1, img2, img_draw_matches); #include <iostream> // 引入iostream库&#xff0c;用于进行标准输入和输出操作 #include <opencv2/core.hpp> // 引入opencv的core库&am…

session学习

3次请求均有sessionID session的作用 跟踪用户的行为&#xff0c;方便日后推荐客户端和服务器交互相对安全些session是代表会话&#xff0c;也可理解为客户端和服务端的交互sessionID是服务器生成的唯一字符串&#xff0c;用来跟踪用户行为cookie是浏览器自带的&#xff0c;专…

4.1作业

对菱形继承给出的代码中每一个类&#xff0c;写一个有参构造函数写出下列类的&#xff0c;构造函数(有参、无参)&#xff0c;析构函数&#xff0c;拷贝构造函数和拷贝赋值函数 class Father { int *p; const string name; } class Son:public Father { int *age; 3整理思维导图…

【JavaWeb】Day30.SpringBootWeb请求响应——响应

响应 HTTL协议的交互方式&#xff1a;请求响应模式&#xff08;有请求就有响应&#xff09;那么Controller程序&#xff0c;除了接收请求外&#xff0c;还可以进行响应。 1.ResponseBody 在我们前面所编写的controller方法中&#xff0c;都已经设置了响应数据。 controller方…

前端订阅推送WebSocket定时任务

0.需求 后端定时向前端看板推送数据&#xff0c;每10秒或者30秒推送一次。 1.前言知识 HTTP协议是一个应用层协议&#xff0c;它的特点是无状态、无连接和单向的。在HTTP协议中&#xff0c;客户端发起请求&#xff0c;服务器则对请求进行响应。这种请求-响应的模式意味着服务器…

路径规划——搜索算法详解(六):LPA*算法详解与Matlab代码

上文讲解了D*算法&#xff0c;D*算法为在动态环境下进行路径规划的场景提出了可行的解决方案&#xff0c;本文将继续介绍另外一种动态规划路径的方法——Lifelong Planning A*&#xff08;LPA*&#xff09;算法。 该算法可以看作是A*的增量版本&#xff0c;是一种在固定起始点…

语音克隆技术浪潮:探索OpenAI Voice Engine的奇妙之旅

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Bridge Champ与Ignis公链:探索Web3游戏的新未来

在数字化和去中心化的浪潮中&#xff0c;Web3游戏与公链的融合为游戏行业带来了新的变革。特别是&#xff0c;Bridge Champ和Ignis公链的结合&#xff0c;展示了一种全新的游戏生态模式&#xff0c;不仅为玩家提供了更加公平、透明的游戏体验&#xff0c;同时也为游戏开发和运营…

Higress 基于自定义插件访问 Redis

作者&#xff1a;钰诚 简介 基于 wasm 机制&#xff0c;Higress 提供了优秀的可扩展性&#xff0c;用户可以基于 Go/C/Rust 编写 wasm 插件&#xff0c;自定义请求处理逻辑&#xff0c;满足用户的个性化需求&#xff0c;目前插件已经支持 redis 调用&#xff0c;使得用户能够…

C++ 注册Nacos

下载源码&#xff1a; git clone GitHub - nacos-group/nacos-sdk-cpp: C client for Nacos 编译源码 cd nacos-sdk-cpp cmake . make 生成库文件 在nacos-sdk-cpp 下 注册nacos 将include 和libnacos-cli.so libnacos-cli-static.a 放入你的工程 如果Nacos服务地址:…

3.26号arm

1. SPI相关理论 1.1 概述 spi是一种同步全双工串行总线&#xff0c;全称串行外围设备接口 通常SPI通过4个引脚与外部器件相连&#xff1a; MISO&#xff1a;主设备输入/从设备输出引脚。该引脚在从模式下发送数据&#xff0c;在主模式下接收数据。 MOSI&#xff1a;主设备输…

LangChain入门:9.使用FewShotPromptTemplate实现智能提示工程

在构建智能提示工程时&#xff0c;LangChain 提供了强大的 FewShotPromptTemplate 模型&#xff0c;它可以帮助我们更好地利用示例来指导大模型生成更加优质的提示。 在这篇博文中&#xff0c;我们将使用 LangChain 的 FewShotPromptTemplate 模型来设计一个智能提示工程&#…

StarRocks使用Minio备份和还原

1.安装minio minio api端口&#xff1a;9090 下文用到这个端口 必须提前创建好桶: packfdv5 名称自定义和后面对上就可以 2.创建备份仓库 格式&#xff1a; CREATE REPOSITORY <repository_name> WITH BROKER ON LOCATION "s3a://<bucket_name>/backup…

47.goto语句

目录 一.goto语句 二.语法格式 三.举例 四.视频教程 一.goto语句 goto语句可以使程序在没有任何条件的情况下跳转到指定位置&#xff0c;所以goto语句也就跳转语句。 二.语法格式 格式1&#xff1a;goto label&#xff1a;//其他代码 lable&#xff1a;//其他代码格式2&a…

【Node.js从基础到高级运用】二十、Node.js 强大的REPL

引言 Node.js REPL&#xff08;Read-Eval-Print Loop&#xff09;是一种交互式的命令行工具&#xff0c;它允许开发者快速地执行JavaScript代码&#xff0c;并查看结果。这个功能在进行快速原型设计、调试、学习JavaScript或Node.js时非常有用。 启动REPL 首先&#xff0c;确保…

【总结】在嵌入式设备上可以离线运行的LLM--Llama

文章目录 Llama 简介运用另一种&#xff1a;MLC-LLM 一个令人沮丧的结论在资源受限的嵌入式设备上无法运行LLM&#xff08;大语言模型&#xff09;。 一丝曙光&#xff1a;tinyLlama-1.1b&#xff08;10亿参数&#xff0c;需要至少2.98GB的RAM&#xff09; Llama 简介 LLaMA…