Unity & 蓝湖 关于UI工作流优化的思考(二)

简介: Unity & 蓝湖 关于UI工作流优化的思考(二)

最新版本:

image.gif


image.gif

本文旨在让不会使用Unity的其他人员在简单了解该工具后,可以帮助研发人员搭建Unity中的UI预制体,研发人员稍作调整即可用,以减轻研发人员的工作压力。

一个UI视图的预制体的制作步骤如下:

1.在蓝湖中下载该视图的所有相关切图

image.gif

2.将下载的切图资源包解压缩后,拖入到Unity中Project窗口的Assets目录中的任一文件夹内

image.gif

3.选中所有切图,在Inspector窗口修改Texture Type为Sprite类型,并点击右下角的Apply

image.gif

4.在顶部菜单栏SKFramework中找到LanHu,打开窗口

image.gif

5.点击浏览按钮选择该视图的切图所在文件夹

image.gif

6.点击创建,创建一个Canvas画布,也可以选择场景中已有的Canvas

image.gif

7.添加

点击添加按钮,添加一项UI视图元素

image.gif

在蓝湖中点击切图的样式信息中的内容即可复制

image.gif

回到Unity,点击粘贴按钮,将从蓝湖中复制的内容粘贴到对应参数中

image.gif

8.删除

点击”-“号按钮,可以将该项进行移除

image.gif

点击清空按钮,可以清空当前所有的配置信息

image.gif

image.gif

9.收缩

配置信息过多时,点击收缩按钮,可以关闭所有折叠栏

image.gif

10.展开

点击展开按钮,可以打开所有折叠栏

image.gif

11.生成

点击生成后,工具会根据填写的配置信息,在切图所在文件夹中加载指定切图,并将其设置到指定位置、设置指定大小,最终将生成的UI视图创建为prefab预制体。

image.gif


image.gif

随着预制体的生成,工具还会将该视图的所有配置信息以资产的形式保存下来

image.gif

12.导入

当想要修改一个UI视图的某一元素时,点击导入按钮,将该视图的配置资产文件进行导入,修改配置内容后重新生成即可。

image.gif

13.预览生成的UI视图

打开Scene窗口中的2D选项

image.gif

在Hierarchy窗口找到Canvas中的UI视图,双击聚焦查看

image.gif

工具完整代码:

usingSystem;
namespaceSK.Framework{
/// <summary>/// 蓝湖界面UI元素/// </summary>    [Serializable]
publicclassLanHuViewElement    {
/// <summary>/// 图层名称/// </summary>publicstringname;
/// <summary>/// 位置x/// </summary>publicstringx;
/// <summary>/// 位置y/// </summary>publicstringy;
/// <summary>/// 宽度/// </summary>publicstringwidth;
/// <summary>/// 高度/// </summary>publicstringheight;
/// <summary>/// 不透明度/// </summary>publicstringopacity;
/// <summary>/// 像素倍数/// </summary>publicstringpixel="x1";
/// <summary>/// 构造函数/// </summary>publicLanHuViewElement(stringname, stringx, stringy, stringwidth, stringheight, stringopacity, stringpixel)
        {
this.name=name;  
this.x=x;
this.y=y;
this.width=width;
this.height=height;
this.opacity=opacity;
this.pixel=pixel;
        }
    }
}

image.gif

usingUnityEngine;
usingSystem.Collections.Generic;
namespaceSK.Framework{
publicclassLanHuView : ScriptableObject    {
/// <summary>/// 存放切图的文件夹路径/// </summary>publicstringpath;
publicList<LanHuViewElement>elements=newList<LanHuViewElement>(0);
    }
}

image.gif

usingSystem.IO;
usingUnityEditor;
usingUnityEngine;
usingUnityEngine.UI;
usingSystem.Collections.Generic;
namespaceSK.Framework{
/// <summary>/// 蓝湖UI界面搭建工具/// </summary>publicclassLanHu : EditorWindow    {
        [MenuItem("SKFramework/LanHu")]
privatestaticvoidOpen()
        {
GetWindow<LanHu>("LanHu").Show();
        }
privatestringpath;
privateList<LanHuViewElement>elements;
privateVector2scroll;
privateconstfloatlabelWidth=70f;
privateDictionary<LanHuViewElement, bool>foldoutDic;
privateCanvasScalercanvasScaler;
privatevoidOnEnable()
        {
path="Assets";
elements=newList<LanHuViewElement>();
foldoutDic=newDictionary<LanHuViewElement, bool>();
        }
privatevoidOnGUI()
        {
OnTopGUI();
OnElementsGUI();
OnMenuGUI();
        }
privatevoidOnTopGUI()
        {
GUILayout.BeginHorizontal();
GUILayout.Label("切图文件夹路径:", GUILayout.Width(100f));
EditorGUILayout.TextField(path);
if (GUILayout.Button("浏览", GUILayout.Width(40f)))
            {
//Assets相对路径path=EditorUtility.OpenFolderPanel("选择切图文件夹", "", "").Replace(Application.dataPath, "Assets");
            }
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("Canvas Scaler", GUILayout.Width(100f));
canvasScaler= (CanvasScaler)EditorGUILayout.ObjectField(canvasScaler, typeof(CanvasScaler), true);
if (canvasScaler==null)
            {
if (GUILayout.Button("创建", GUILayout.Width(40f)))
                {
varcanvas=newGameObject("Canvas").AddComponent<Canvas>();
canvas.renderMode=RenderMode.ScreenSpaceCamera;
canvasScaler=canvas.gameObject.AddComponent<CanvasScaler>();
canvasScaler.uiScaleMode=CanvasScaler.ScaleMode.ScaleWithScreenSize;
canvasScaler.referenceResolution=newVector2(1920f, 1080f);
EditorGUIUtility.PingObject(canvas);
                }
            }
GUILayout.EndHorizontal();
        }
privatevoidOnElementsGUI()
        {
EditorGUILayout.Space();
GUI.enabled=canvasScaler!=null;
scroll=EditorGUILayout.BeginScrollView(scroll);
for (inti=0; i<elements.Count; i++)
            {
varelement=elements[i];
if (!foldoutDic.ContainsKey(element))
                {
foldoutDic.Add(element, true);
                }
foldoutDic[element] =EditorGUILayout.Foldout(foldoutDic[element], element.name, true);
if (!foldoutDic[element]) continue;
GUILayout.BeginVertical("Box");
GUILayout.BeginHorizontal();
GUILayout.Label("图层", GUILayout.Width(labelWidth));
element.name=EditorGUILayout.TextField(element.name);
if (GUILayout.Button("粘贴", GUILayout.Width(40f)))
                {
element.name=GUIUtility.systemCopyBuffer;
                }
if (GUILayout.Button("-", GUILayout.Width(20f)))
                {
foldoutDic.Remove(element);
elements.RemoveAt(i);
Repaint();
                }
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("位置", GUILayout.Width(labelWidth));
element.x=EditorGUILayout.TextField(element.x);
if (GUILayout.Button("粘贴", GUILayout.Width(40f)))
                {
element.x=GUIUtility.systemCopyBuffer;
                }
element.y=EditorGUILayout.TextField(element.y);
if (GUILayout.Button("粘贴", GUILayout.Width(40f)))
                {
element.y=GUIUtility.systemCopyBuffer;
                }
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("大小", GUILayout.Width(labelWidth));
element.width=EditorGUILayout.TextField(element.width);
if (GUILayout.Button("粘贴", GUILayout.Width(40f)))
                {
element.width=GUIUtility.systemCopyBuffer;
                }
element.height=EditorGUILayout.TextField(element.height);
if (GUILayout.Button("粘贴", GUILayout.Width(40f)))
                {
element.height=GUIUtility.systemCopyBuffer;
                }
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("不透明度", GUILayout.Width(labelWidth));
element.opacity=EditorGUILayout.TextField(element.opacity);
if (GUILayout.Button("粘贴", GUILayout.Width(40f)))
                {
element.opacity=GUIUtility.systemCopyBuffer;
                }
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("像素倍数", GUILayout.Width(labelWidth));
if (GUILayout.Button(element.pixel))
                {
GenericMenugm=newGenericMenu();
gm.AddItem(newGUIContent("x1"), element.pixel=="x1", () =>element.pixel="x1");
gm.AddItem(newGUIContent("x2"), element.pixel=="x2", () =>element.pixel="x2");
gm.ShowAsContext();
                }
GUILayout.EndHorizontal();
GUILayout.EndVertical();
            }
EditorGUILayout.EndScrollView();
        }
privatevoidOnMenuGUI()
        {
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal();
if (GUILayout.Button("导入", "ButtonLeft"))
            {
stringpresetPath=EditorUtility.OpenFilePanel("选择预设文件", Application.dataPath, "asset");
if (File.Exists(presetPath))
                {
varimport=AssetDatabase.LoadAssetAtPath<LanHuView>(presetPath.Replace(Application.dataPath, "Assets"));
if (import!=null)
                    {
elements.Clear();
foldoutDic.Clear();
path=import.path;
for (inti=0; i<import.elements.Count; i++)
                        {
elements.Add(import.elements[i]);
                        }
Repaint();
                    }
                }
            }
if (GUILayout.Button("添加", "ButtonMid"))
            {
elements.Add(newLanHuViewElement("", "0px", "0px", "1920px", "1080px", "100%", "x1"));
            }
if (GUILayout.Button("清空", "ButtonMid"))
            {
if (EditorUtility.DisplayDialog("提醒", "确定删除当前所有配置信息?", "确定", "取消"))
                {
elements.Clear();
foldoutDic.Clear();
                }
            }
if (GUILayout.Button("展开", "ButtonMid"))
            {
for (inti=0; i<elements.Count; i++)
                {
foldoutDic[elements[i]] =true;
                }
            }
if (GUILayout.Button("收缩", "ButtonMid"))
            {
for (inti=0; i<elements.Count; i++)
                {
foldoutDic[elements[i]] =false;
                }
            }
if (GUILayout.Button("生成", "ButtonRight"))
            {
vararray=path.Split('/');
varview=newGameObject(array[array.Length-1]).AddComponent<RectTransform>();
view.transform.SetParent(canvasScaler.transform, false);
SetRectTransform(view, 0, 0, canvasScaler.referenceResolution.x, canvasScaler.referenceResolution.y);
for (inti=0; i<elements.Count; i++)
                {
varelement=elements[i];
stringspritePath=string.Format("{0}/{1}{2}.png", path, element.name, element.pixel=="x1"?string.Empty : "@2x");
varobj=AssetDatabase.LoadAssetAtPath<Sprite>(spritePath);
if (obj!=null)
                    {
varimage=newGameObject(obj.name).AddComponent<Image>();
image.transform.SetParent(view.transform, false);
image.sprite=obj;
RectTransformrt=image.transformasRectTransform;
float.TryParse(element.x.Replace(element.x.Substring(element.x.Length-2, 2), string.Empty), outfloatxValue);
float.TryParse(element.y.Replace(element.y.Substring(element.y.Length-2, 2), string.Empty), outfloatyValue);
float.TryParse(element.width.Replace(element.width.Substring(element.width.Length-2, 2), string.Empty), outfloatwValue);
float.TryParse(element.height.Replace(element.height.Substring(element.height.Length-2, 2), string.Empty), outfloathValue);
/*float.TryParse(element.x, out float xValue);float.TryParse(element.y, out float yValue);float.TryParse(element.width, out float wValue);float.TryParse(element.height, out float hValue);*/SetRectTransform(rt, xValue, yValue, wValue, hValue);
                    }
else                    {
Debug.Log($"<color=yellow>加载切图失败 {spritePath}</color>");
                    }
                }
//创建预设文件varpreset=CreateInstance<LanHuView>();
for (inti=0; i<elements.Count; i++)
                {
preset.elements.Add(elements[i]);
                }
preset.path=path;
AssetDatabase.CreateAsset(preset, string.Format("Assets/{0}.asset", view.name));
AssetDatabase.Refresh();
Selection.activeObject=preset;
//创建Prefabvarprefab=PrefabUtility.SaveAsPrefabAsset(view.gameObject, $"Assets/{view.name}.prefab", outboolresult);
if (!result)
                {
Debug.Log($"<color=yellow>生成预制体失败 {view.name}</color>");
                }
else                {
EditorGUIUtility.PingObject(prefab);
                }
            }
GUILayout.EndHorizontal();
        }
privatevoidSetRectTransform(RectTransformrt, floatx, floaty, floatwidth, floatheight)
        {
//调整位置及大小rt.anchorMin=newVector2(0, 1);
rt.anchorMax=newVector2(0, 1);
rt.pivot=Vector2.one* .5f;
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
rt.anchoredPosition=newVector2(x+width/2f, -(y+height/2f));
//调整完成后自动设置锚点RectTransformprt=rt.parentasRectTransform;
Vector2anchorMin=newVector2(
rt.anchorMin.x+rt.offsetMin.x/prt.rect.width,
rt.anchorMin.y+rt.offsetMin.y/prt.rect.height);
Vector2anchorMax=newVector2(
rt.anchorMax.x+rt.offsetMax.x/prt.rect.width,
rt.anchorMax.y+rt.offsetMax.y/prt.rect.height);
rt.anchorMin=anchorMin;
rt.anchorMax=anchorMax;
rt.offsetMin=rt.offsetMax=Vector2.zero;
        }
    }
}

image.gif

目录
相关文章
|
5月前
|
存储 设计模式 监控
运用Unity Profiler定位内存泄漏并实施对象池管理优化内存使用
【7月更文第10天】在Unity游戏开发中,内存管理是至关重要的一个环节。内存泄漏不仅会导致游戏运行缓慢、卡顿,严重时甚至会引发崩溃。Unity Profiler作为一个强大的性能分析工具,能够帮助开发者深入理解应用程序的内存使用情况,从而定位并解决内存泄漏问题。同时,通过实施对象池管理策略,可以显著优化内存使用,提高游戏性能。本文将结合代码示例,详细介绍如何利用Unity Profiler定位内存泄漏,并实施对象池来优化内存使用。
359 0
|
3月前
|
前端开发 图形学 开发者
【独家揭秘】那些让你的游戏瞬间鲜活起来的Unity UI动画技巧:从零开始打造动态按钮,提升玩家交互体验的绝招大公开!
【9月更文挑战第1天】在游戏开发领域,Unity 是最受欢迎的游戏引擎之一,其强大的跨平台发布能力和丰富的功能集让开发者能够迅速打造出高质量的游戏。优秀的 UI 设计对于游戏至关重要,尤其是在手游市场,出色的 UI 能给玩家留下深刻的第一印象。Unity 的 UGUI 系统提供了一整套解决方案,包括 Canvas、Image 和 Button 等组件,支持添加各种动画效果。
168 3
|
4月前
|
存储 分布式计算 供应链
Spark在供应链核算中应用问题之通过Spark UI进行任务优化如何解决
Spark在供应链核算中应用问题之通过Spark UI进行任务优化如何解决
|
4月前
|
前端开发 开发工具 图形学
PicoVR Unity SDK⭐️三、详解与UI的交互方式
PicoVR Unity SDK⭐️三、详解与UI的交互方式
|
4月前
|
前端开发 图形学
Unity精华☀️UI和物体可见性的判断方法
Unity精华☀️UI和物体可见性的判断方法
|
4月前
|
开发者 图形学 iOS开发
掌握Unity的跨平台部署与发布秘籍,让你的游戏作品在多个平台上大放异彩——从基础设置到高级优化,深入解析一站式游戏开发解决方案的每一个细节,带你领略高效发布流程的魅力所在
【8月更文挑战第31天】跨平台游戏开发是当今游戏产业的热点,尤其在移动设备普及的背景下更为重要。作为领先的游戏开发引擎,Unity以其卓越的跨平台支持能力脱颖而出,能够将游戏轻松部署至iOS、Android、PC、Mac、Web及游戏主机等多个平台。本文通过杂文形式探讨Unity在各平台的部署与发布策略,并提供具体实例,涵盖项目设置、性能优化、打包流程及发布前准备等关键环节,助力开发者充分利用Unity的强大功能,实现多平台游戏开发。
129 0
|
4月前
|
开发者 图形学 前端开发
绝招放送:彻底解锁Unity UI系统奥秘,五大步骤教你如何缔造令人惊叹的沉浸式游戏体验,从Canvas到动画,一步一个脚印走向大师级UI设计
【8月更文挑战第31天】随着游戏开发技术的进步,UI成为提升游戏体验的关键。本文探讨如何利用Unity的UI系统创建美观且功能丰富的界面,包括Canvas、UI元素及Event System的使用,并通过具体示例代码展示按钮点击事件及淡入淡出动画的实现过程,助力开发者打造沉浸式的游戏体验。
116 0
|
4月前
|
开发者 图形学 UED
深度解析Unity游戏开发中的性能瓶颈与优化方案:从资源管理到代码执行,全方位提升你的游戏流畅度,让玩家体验飞跃性的顺滑——不止是技巧,更是艺术的追求
【8月更文挑战第31天】《Unity性能优化实战:让你的游戏流畅如飞》详细介绍了Unity游戏性能优化的关键技巧,涵盖资源管理、代码优化、场景管理和内存管理等方面。通过具体示例,如纹理打包、异步加载、协程使用及LOD技术,帮助开发者打造高效流畅的游戏体验。文中提供了实用代码片段,助力减少内存消耗、提升渲染效率,确保游戏运行丝滑顺畅。性能优化是一个持续过程,需不断测试调整以达最佳效果。
106 0
|
4月前
|
小程序 UED 开发者
揭秘支付宝小程序成功之道:UI/UX设计原则与用户体验优化秘籍大公开!
【8月更文挑战第27天】支付宝小程序在移动互联网中扮演着重要角色,优秀的UI/UX设计能显著提升用户满意度。本文首先强调了设计的一致性、简洁性、易用性和响应性原则,确保用户获得顺畅体验。接着,介绍了最佳实践,包括利用支付宝设计组件库保持界面统一、优化加载速度、适应多设备显示、设置清晰导航以及重视用户反馈。最后,提供了一个简单示例展示如何应用支付宝设计组件。遵循这些指导原则,开发者能够构建既美观又实用的小程序。
98 0
|
4月前
|
图形学
小功能⭐️Unity获取点击到的UI
小功能⭐️Unity获取点击到的UI
下一篇
DataWorks