ui展示3d unity3d_unity ui展示3d模型残影 - CSDN
  • Unity3D简单的UI系统

    千次阅读 2019-04-11 12:20:14
    Unity3d的ugui如果用得不好,非常的影响性能,可能很多人都不知道,其实ugui是基于网格模型渲染的,一个ugui组件就是一个Mesh,ui组件的Material为空,其实他是用了默认的Material,我们在运行游戏的时候Canvas回把...

    Unity3d的ugui如果用得不好,非常的影响性能,可能很多人都不知道,其实ugui是基于网格模型渲染的,一个ugui组件就是一个Mesh,ui组件的Material为空,其实他是用了默认的Material,我们在运行游戏的时候Canvas回把所有ui的Mesh合并成一个大的ShareMesh,用于渲染。所以一般情况下,ui的DrawCall会比较少,但是不一般的情况下,我们会用到动态的ui,导致cpu实时在合并网格顶点,gpu重新渲染整个ShareMesh,这就很卡了,所以我们要尽量不要用动态的ui,这怎么可能偷笑

    扯了一下不相干的事,接下来我们来讲讲怎么来写一个简单的ui系统。

    一个好的框架,底层少不了接口,所以我们创建一个UI的接口IView。

    // **********************************************************************
    // Copyright (C) XM
    // Author: 吴肖牧
    // Date: 2018-04-15
    // Desc: 
    // **********************************************************************
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public interface IView {
    
        /// <summary>
        /// 绑定组件
        /// </summary>
        void BindComponent();
    
        /// <summary>
        /// 注册事件
        /// </summary>
        void RegistrationEvent();
    
        /// <summary>
        /// 注销事件
        /// </summary>
        void UnregisterEvent();
    
        /// <summary>
        /// 初始化
        /// </summary>
        void Init();
    
        /// <summary>
        /// 关闭
        /// </summary>
        void Close();
    }
    

    2.接下来我们来创建一个ui的基类UIBase。

    // **********************************************************************
    // Copyright (C) XM
    // Author: 吴肖牧
    // Date: 2018-04-15
    // Desc: 
    // **********************************************************************
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class UIBase : Base, IView
    {
        public object[] param;
    
        public UIType uiType;
    
        public PanelType panelType;
    
        protected void Awake()
        {
            BindComponent();
            RegistrationEvent();
            XMAwake();
        }
        protected void Start()
        {
            Init();
        }
    
        public virtual void XMAwake()
        {
        }
    
        /// <summary>
        /// 绑定组件
        /// </summary>
        public virtual void BindComponent()
        {
        }
    
        /// <summary>
        /// 注册事件
        /// </summary>
        public virtual void RegistrationEvent()
        {
        }
    
        /// <summary>
        /// 注销事件
        /// </summary>
        public virtual void UnregisterEvent()
        {
        }
    
        /// <summary>
        /// 关闭
        /// </summary>
        public virtual void Close()
        {
        }
    
        /// <summary>
        /// 初始化
        /// </summary>
        public virtual void Init()
        {
    
        }
    
        private void OnDestroy()
        {
            UnregisterEvent();
            Close();
            param = null;
            XMUtil.ClearMemory();
            //Debug.Log("~" + name + " was destroy!");
        }
    }

    UIBase根据你们的需求可以相应的扩展,这里只写了ui类型和层级类型。

     

    3.然后我们随便创建一个界面UIMain

    // **********************************************************************
    // Copyright (C) XM
    // Author: 吴肖牧
    // Date: 2018-04-18
    // Desc: 
    // **********************************************************************
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class UIMain : UIBase {
    
        public Button btn_Attack;
    
        public override void BindComponent()
        {
            base.BindComponent();
        }
    
        public override void RegistrationEvent()
        {
            base.RegistrationEvent();
            btn_Attack.onClick.AddListener(Attack);
        }
    
        public override void UnregisterEvent()
        {
            base.UnregisterEvent();
            btn_Attack.onClick.RemoveListener(Attack);
        }
    
        public override void Close()
        {
            base.Close();
        }
    
        public override void Init()
        {
            base.Init();
        }
    
    
        private void Attack()
        {
            SendMessage(BattleEvent.Attack);
        }
    }
    

     

    每次创建新的界面我们都在UIType上添加新的类型,用于界面的创建和销毁。

     

    public enum UIType
    {
        UIMain,
    }

     

    4.最后我们写一个UIManager来管理所有的ui。

    using System.Collections;
    // **********************************************************************
    // Copyright (C) XM
    // Author: 吴肖牧
    // Date: 2018-04-13
    // Desc: 
    // **********************************************************************
    
    using System.Collections.Generic;
    using UnityEngine;
    
    /// <summary>
    /// 界面类型
    /// </summary>
    public enum PanelType
    {
        MainPanel,
        BottomPanel,
        TopPanel,
        TipPanel,
    }
    
    public class UIManager : Manager {
    
        Dictionary<UIType, GameObject> uiMap = new Dictionary<UIType, GameObject>();
    
        Transform MainPanel;
        Transform BottomPanel;
        Transform TopPanel;
        Transform TipPanel;
    
        void Awake()
        {
            Transform tr = AppFacade.Instance.GetManager<GameManager>(ManagerName.Game).uiRoot.transform;
            MainPanel = tr.Find("MainPanel");
            BottomPanel = tr.Find("BottomPanel");
            TopPanel = tr.Find("TopPanel");
            TipPanel = tr.Find("TipPanel");
        }
    
        /// <summary>
        /// 打开界面
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public GameObject Show(string path,object[] param = null)
        {
            GameObject ui = ResManager.CreateAsset(path);
            UIBase uibase = ui.GetComponent<UIBase>();
            uibase.param = param;
            SetPanelParent(uibase);
            ui.transform.localScale = Vector3.one;
            ui.transform.localPosition = Vector3.zero;
            ui.transform.rectTransform().sizeDelta = new Vector2(0, 0);
            ui.transform.rectTransform().anchoredPosition = new Vector2(0, 0);
            AddUI(uibase.uiType, ui);
            return ui;
        }
    
        /// <summary>
        /// 设置ui的父对象
        /// </summary>
        /// <param name="go"></param>
        void SetPanelParent(UIBase uibase)
        {
            if (uibase.panelType == PanelType.MainPanel)
            {
                uibase.transform.SetParent(MainPanel);
            }
            else if (uibase.panelType == PanelType.BottomPanel)
            {
                uibase.transform.SetParent(BottomPanel);
            }
            else if (uibase.panelType == PanelType.TopPanel)
            {
                uibase.transform.SetParent(TopPanel);
            }
            else if (uibase.panelType == PanelType.TipPanel)
            {
                uibase.transform.SetParent(TipPanel);
            }
        }
    
    
        void AddUI(UIType uiType, GameObject ui)
        {
            uiMap.Add(uiType, ui);
        }
    
        void RemoveUI(UIType uiType)
        {
            if (uiMap.ContainsKey(uiType))
            {
                Destroy(uiMap[uiType]);
                uiMap.Remove(uiType);
            }
            else
            {
                Debug.LogError("CloseUI Fail  >>>>  Not Find " + name);
            }
        }
    
        /// <summary>
        /// 关闭面板
        /// </summary>
        /// <param name="name"></param>
        public void Close(UIType uiType)
        {
            RemoveUI(uiType);
        }
    
        void OnDestroy()
        {
            //Debug.Log("~UIManager was destroy!");
        }
    }

    我写的这个ui系统是很简单的,主要就是面向对象的思路展示,并不是作为一个框架中完整的UI系统来写的,所以有需要的朋友可以自行拓展。

    如果有关注我的朋友,应该看过另一篇文章《Unity3D创建C#自定义模板快速实现基类接口》,我们可以创建一个UI的模版,每次创建新的界面都会自动帮我们实现基类的方法。

     

    展开全文
  • 助力快速利用 UGUI 完成 3D 物体在 UI 界面的显示,UnityUi显示3D物体/模型,控制物体旋转,转动全教程-超简单,游戏开发过程中,我们时长会需要把 3D 游戏对象/模型显示在 UI 界面上 例如王者荣耀上的人物选择,可以...
  • Unity UI显示3D模型

    千次阅读 2018-07-20 23:24:30
    2.新建一个空物体,作为UI的根节点 3.在UI Root 下新建一块画布,并设置Render Mode属性为"Screen Space - Camera " 4.在画布下新建一个相机,"Clear Flags"设置为"Depth only",...

    1.新建一个场景

    2.新建一个空物体,作为UI的根节点

    3.在UI Root 下新建一块画布,并设置Render Mode属性为"Screen Space - Camera "

    4.在画布下新建一个相机,"Clear Flags"设置为"Depth only",Projection 设置为"Orthographic",Clipping Planes下的"Far"缩短距离为"5"

    5.设置画布的"Render Camera" 为刚创建的相机"GUI Camera"

    6.在画布下新建一个"Image",并将Pox Z 设置为"20",此时已经显示正常的UI

    7.在画布下新建一个UI组建,去掉多余部分,只留"Rect Transform",并将Pox Z 设置为"20"

    8.在新建的UI组建下新建一个3D模型,调整Scale为"100,100,100",Position设置为50

    9.已经可以显示3D模型了,Scenc下,运行时,把GUICamera放到Canvas最下面

    10,该文章参考"Unity Store"的"UltimateSurvival"的UI布局,

    展开全文
  • Unity3d 5 官方教程:UI

    万次阅读 2017-03-29 23:30:12
    本篇是对UnityUI系统主要特性的介绍。 相关教程:用户界面CanvasCanvas是所有UI元素应当存放于内的区域。Canvas是一个有Canvas组件的游戏对象,并且所有UI对象必须是这样一个Canvas对象的子对象。

    UI


    UI系统允许用户迅速且直观地创建用户界面。本篇是对Unity的UI系统主要特性的介绍。
    相关教程:用户界面

    Canvas

    Canvas是所有UI元素应当存放于内的区域。Canvas是一个有Canvas组件的游戏对象,并且所有UI对象必须是这样一个Canvas对象的子对象。
    创建一个新的UI元素,例如使用 GameObjct>UI>Image,创建一个Image对象,会自动地创建一个Canvas,如果场景里没有已存在的Canvas。UI元素将作为这个Canvas的子对象创建。
    Canvas区域会在场景视图中显示为一个矩形。这使得它容易放置UI元素而不需要一直保持在游戏视图。
    Canvas使用EventSystem(事件系统)对象来帮助Messaging System(消息系统)、

    元素的绘制顺序

    在Canvas中的UI元素,以它们出现在层次中的顺序被绘制。第一个子对象被先渲染,然后第二个,以此类推。如果两个UI元素重叠,后一个将出现在前一个上上面。
    要改变某个元素出现在另外元素的上面,只要通过拖拽它们改变在层次中的顺序几个。通过使用在Transform组件中的这些方法,也可以从脚本中控制顺序:SetAsFirstSibling, SetAsLastSibling, 以及SetSiblingIndex 。

    渲染模式

    Canvas有渲染模式设置,可以用来让Canvas在屏幕空间或世界空间中渲染。

    屏幕空间 - 覆盖

    这个渲染模式将渲染的UI元素放置在场景的最上面(最靠近镜头)。如果屏幕被重新调整大小或调整分辨率,Canvas将自动改变尺寸以适应。
    屏幕空间覆盖Canvas

    屏幕空间 - 摄像机

    这个模式类似于“屏幕空间 - 覆盖”,但在这个渲染模式下,Canvas被放置在指定摄像机的一个给定距离前。UI元素用这个摄像机渲染,意味着摄像机设置将印象到UI的表现。如果摄像机被设置为透视的,UI元素将会以透视渲染,并且透视变形可以被摄像机视野区所控制。如果屏幕被重设大小或改变分辨率,或者摄像机frustrum 改变,Canvas同样将自动改变设置以匹配。
    UI in screen space camera canvas

    世界空间

    在这个渲染模式下,Canvas将如场景中其它的对象那样。Canvas的尺寸可以用它的矩形transform进行手动设置,UI元素会在场景中其它对象的前面或后面渲染,基于三维空间中的位置关系。这在UI元素被定义为世界一部分时有用。这也被称为“剧情界面”(diagetic interface)。
    UI in world space canvas

    基本布局

    这一部分我们将看看,元素关联到Canvas及相互间,应如何放置。如果用户希望在阅读时自己测试,可以创建一个Image(GameObject ->UI -> Image)。

    矩形工具

    为了布局考虑,每个UI元素用一个矩形所表示。这个矩形可以在场景视图中用工具栏中的矩形工具处理。矩形工具可以被Uinity的2D特性和UI所使用,实际上也可以用于3D对象。
    这里写图片描述

    矩形工具可以用来移动,重设大小,旋转UI元素。一旦选择了一个UI元素,可以通过点击矩形内的任何位置并拖拽它来移动。用户可以通过点击边缘或角落并拖拽来调整大小。元素可以被旋转通过将指针悬停在角落附近,直到鼠标指针看起来像个旋转记号。然后可以点击并向任意方向旋转。
    就像其它工具,矩形工具使用当前的当前的枢轴模式和空间,在工具栏中设置。当对UI进行工作,通常将这些设置为PivotLocal
    这里写图片描述

    矩形变换

    矩形变换是一个新的变换组件;对所有UI元素,取代了标准的变换组件。
    这里写图片描述

    重设相对缩放

    当矩形工具被用于改变对象的大小时,通常对于二维系统和三维对象,它将改变对象的局部缩放。然而,当被用于一个有矩形变换的对象时,改变的是宽度和高度,保持局部缩放不变。这样的重设大小将不影响字体尺寸、镶边等。

    轴Pivot

    旋转,尺寸,缩放的调整是围绕着轴的;所以轴的位置影响着旋转、尺寸或缩放的效果。当工具栏上Pivot按钮被设置为Pivot模式,矩形变换的轴会被移入场景视图。

    这里写图片描述

    定位Anchors

    矩形变换包括称为“定位”的一个布局概念。定位以四个在场景视图中的小直角柄所表示,定位信息在检视器中显示。
    如果矩形变换的父对象同样是个矩形变换,那么子举行变换可以若干种途径被定位到父对象。例如,子对象可以定位到父对象的中心,或者一个角落。
    UI element anchored to the center of the parent. The element maintains a fixed offset to the center.

    UI element anchored to the lower right corner of the parent. The element maintains a fixed offset to the lower right corner.
    定位也允许子对象随着父对象宽度、高度一同伸缩。每个矩形的角落相对它对应的定位有固定的偏移,即矩形的左上角有对左上定位有固定的偏移,等等。这种方式下,矩形不同角落而可以被定位到父对象矩形的不同点。
    UI element with left corners anchored to lower left corner of the parent and right corners anchored to lower right. The corners of the element maintains fixed offsets to their respective anchors.
    定位的位置用父对象矩形宽度及高度的分数(或百分比)来定义。0.0(0%)对应于左边或底边,0.5(50%)为中间,1.0(100%)为右边或顶部。但定位不限制于边沿或中间;可以定位到父对象矩形的任何位置。
    UI element with left corners anchored to a point a certain percentage from the left side of the parent and right corners anchored to a point a certain percentage from the right side of the parent rectangle.

    用户可以分别拖拽每个定位,或如果它们是一起的,用户可以通过点击它们中间并拖拽,让它们一起移动。如果在拖拽一个定位时按下Shift键,矩形对应的角将随着定位一起移动。
    定位柄一个有用的特性是,它们自动对齐到兄弟对象矩形,来允许精确的定位。

    定位预设

    在检视器中,定位预设按钮可以矩形变换组件的在左上角找到。点击此按钮让定位预设下拉。从这里用户可以快速选择一些最常用的定位选项。可以定位UI元素到父对象的边沿或中间,或者随着父对象的尺寸一起伸缩。水平和垂直定位是独立的。
    这里写图片描述
    定位预设按钮显示了当前如果存在的预设项。如果水平或垂直轴的定位被设置到预设不同与预设的任何位置,则显示用户定义的选择。

    检视器你中的定位和位置区

    可以点击定位扩大箭头来显示定位数字区,如果它们尚未可见。最小定位对应于在场景视图中的左下定位柄,最大定位对应于右上的定位柄。
    矩形的位置区根据定位是同步(这导致固定的宽度和高度)还是分开(这让矩形随着父对象矩形一同伸缩),有不同的展示。
    这里写图片描述
    当所有定位柄被同步,显示的区域是位置X、位置Y、宽度和高度。位置X和位置Y的值指明轴相对定位的位置。
    当定位是分开的,区域可以改为部分或完全到左边、右边、上部及底部。这些区域定义了在矩形内用定位定义的衬垫(?)。如果定位水平方向上分开,左边和右边的区域被使用;如果垂直方向分开,顶部和底部区域被使用。
    注意到,改变定位或轴区域中的值,通常将调整位置值,为了让矩形停留在原位置。如果不希望这样的情形,可以使用在检视器中一个小按钮来启用Raw模式。这让定位和轴的值可以被改变,而不是任何其他值改变所导致的结果。这将让矩形被可看到地移动或重设大小,因为它的位置和尺寸依赖于定位和轴的值。

    视觉组件

    在UI系统的介绍中,会帮助你创建有特定功能的GUI的新组件已经添加。这一部分是关于可以被创建的新组件的基本知识。

    文本

    这里写图片描述
    Text(文本)组件,也被作为“标签”,其文本区来输入被显示的文字。可以设置字体、风格、字号以及是否具有富文本功能。
    文本的对齐方式有多种选项,控制文本比矩形的宽度或高度更长时会发生什么的水平和垂直溢出设置,并且最佳匹配选项使得文本会重设大小来适应可用的空间。

    图片

    这里写图片描述
    一张图片有一个矩形变换组件及一个图片组件。一个精灵可以被应用到在目标图片区下方的图片组件,并且颜色可以在颜色区中设置。材质也可以被应用到图片组件。图片类型区定义了应用到图片的精灵如何出现,这些选项时:

    • Simple - 等量地缩放整个精灵。
    • Sliced - 利用3x3精灵分割法,这样尺寸调整不会扭曲角落,并且只有角落部分被拉伸。
    • Tiled - 类似于Sliced,但瓦片式摆放(平铺)中间部分并且不拉伸。对于完全没有边缘的精灵,整个精灵被平铺。
    • Filled - 像Simple模式那样显示精灵,但除了从原点以预定的方向、方法和数量填充精灵。
      设置本地尺寸的选项,在Simple或者Filled被选择时出现,重置图片的尺寸到原始的精灵尺寸。
      图片可以通过在纹理类型设置中选择精灵(2D/UI),被作为UI精灵导入。对比老的GUI精灵,精灵有额外的导入选项,最大的不同是精灵编辑器的增加。精灵编辑器提供了9-slicing图片的选项,将图片划分为9个区域,这样如果精灵被调整,四角不会被拉伸或扭曲。
      这里写图片描述

    原始图片

    图片组件有精灵,但原始图片是纹理(没有边缘等)。原始图片仅在必要时可以被使用,否则图片组件在大部分情况下都是适合的。

    遮罩

    遮罩(Mask)并不是可见的UI控制,然而是调整一个控制子元素外观的一种方式。遮罩根据父元素的形状限制(即所谓的“遮罩”)子元素。这样,如果子元素比父元素更大,那么,子元素只有在父元素中的那部分会可见。

    效果

    视觉组件也可以有各种简单的效果,例如简单的阴影或者轮廓线。可以查看Effect引用页来获得更多信息。

    交互组件

    这部分关于在UI系统中掌控交互的组件,例如鼠标或者触摸事件,以及使用键盘或控制器的交互。
    交互组件自身不可见,并且为了正确地工作,它必须被一个或多个可见元素所包含。

    共有功能

    大部分交互组件有相同的部分。它们是可选择的,意味着它们已经共享了:在状态(普通,高亮,按下,不可用)之间可见的切换,以及使用键盘或控制器到其它可选项的导航,这些内建功能。这些共有的功能在可选页面中描述。

    按钮

    按钮有一个点击Unity事件来定义当被点击时会做什么。
    这里写图片描述
    按钮控制 对来自用户的点击的反应,并且被用来初始化或确认一个动作。常见的例子有在网页表单中的提交和退出按钮。
    这里写图片描述

    属性

    属性 功能
    Interactable 这个组件是否接受输入?参见 Interactable。
    Transition 决定控制对用户动作反应如何可见的属性。参见Transition选项。
    Navigation 决定控制序列的属性。参见Navigation选项。

    事件

    属性 功能
    On Click 当一个用户点击并释放一个按钮时,调用一个Unity事件。

    细节

    按钮被涉及用来初始化一个动作,当用户点击并释放它。如果在松开前鼠标从按钮上移开,则不会发生动作。
    按钮有一个名为 On Click的单独事件,响应用户的一次完整点击。典型的使用情形包括:

    • 确认一个决定(例如,启动游戏或保存游戏)
    • 移动到GUI中的子菜单
    • 退出进行中的动作(例如,下载一个新场景)

    开关

    一个开关是一个决定了某一开关当前是开启或关闭的选择项。当用户点击开关时,值被改变;并且一个对勾会由此打开或关闭。同样有定义一个当值改变时就触发的OnValueChanged的Unity事件。
    这里写图片描述
    这里写图片描述

    属性

    属性 功能
    Interactable 选项是否接受输入?具体见Interactable。
    Transition 决定控制如何以可见的方式对用户动作反应的属性。参见Transition选项
    Navigation 决定控制顺序的属性。参见Navigation选项。
    Is On 选项开始时出于打开状态吗?
    Toggle Transition 当值被改变时开关图像方面的反应。选项是None(即对勾只是简单地出现或消失)和Fade(即对勾淡入或淡出)。
    Graphic 用于对勾的图像。
    Group 选项所属的选项组。

    事件

    属性 功能
    On Value Changed 当开关被点击时,调用的Unity事件。事件可以将当前的状态作为一个Bool类型的动态参数进行发送。

    细节

    开关控制允许用户对选项的开关状态进行切换。当同一时间里一系列开关中仅有一个开关能够开启时,你也可以在一个开关组中包含若干个开关。
    当用户改变当前值时,开关有一个名为 On Value Changed 的单一事件,会进行反应。新的值会作为一个布尔型参数传递给事件函数。开关典型的使用场景包括:

    • 让一个选项开启或关闭(例如,在游戏中播放音乐)。
    • 让用户确认他们已经阅读了法律免责声明。
    • 在一系列选项中选择一个(例如,一个星期中的某一日)。

    注意,开关是提供了子元素可点击区域的父元素。如果开关没有子元素(或者它们不可用),开关是不能点击的。

    开关组

    开关组可以用来将一系列互斥使用的选项形成一组。属于同一组的开关被认为,在同一时间仅有其中一个能被选中——选中它们中的一个,自动弃选其它所有的。
    这里写图片描述
    查看Toggle Group页面来获得关于开关组组件的细节。

    滑块

    滑块有个用户可以在最小值和最大值之间拖拽的十进制数值。滑块可以是水平或者垂直的。它同样也有一个定义了当值改变时如何反应的OnValueChanged的Unity事件。
    这里写图片描述

    滚动条

    滚动条有个在0到1之间的小数。当用户拖拽滚动条时,值对应地改变。
    滚动条通常与一个滚动矩形及遮罩一起使用,来创建一个滚动视图。滚动条有个在0到1之间的Size值,决定了当前部分与完整滚动条长度的比例有多大。这通常被另一个组件所控制,来指明在一个滚动视图中多少比例的内容可见。滚动矩形组件可以自动地做到这一点。
    滚动条可以是水平或者垂直的。它也有一个值被改变时定义如何执行的OnValueChanged的Unity事件。
    这里写图片描述

    下拉框

    下拉框有可以从中选择的选项列表。对于每个选项,可以指定一个文本串或一张图片来指代,并且可以在检视器里设置或者在代码中动态设置。它有一个在值被改变时,定义如何执行的OnValueChanged的Unity事件。
    这里写图片描述

    输入框

    输入框用于创建可被用户所编辑的文本元素的文本。它也有一个文本内容被改变时定义如何执行的OnValueChanged的Unity事件,以及另一个用来定义用户结束输入时如何执行的事件。
    这里写图片描述
    查看 Input Field 页面来获得关于使用输入框元素的细节。

    滚动框(滚动视图)

    一个滚动狂可在占用了大量空间的内容需要在一个小区域中显示的情况下被使用。滚动狂提供了滚动显示内容的功能。
    通常滚动框包含遮罩,以创建一个滚动视图,只有在滚动框中滚动区域的内容可见。它也可以额外地包含一个或两个滚动条,可以水平或垂直地滚动。
    这里写图片描述
    查看 Scroll Rect 页面获得更多关于滚动框组件的细节。

    展开全文
  • Unity3DUI设计

    千次阅读 2017-08-06 15:30:30
    UI, 差不多是玩家打开一个游戏最先看到的东西, 差不多也是玩家最不在意的... 好在 Unity 这样的引擎提供了已经很强大的 UI 解决方案, 以及许多其他开发者提供的插件. 但是这还不够. 这篇文章主要谈一谈 UI 的逻辑设
    
    

    UI程序设计

    首先先说一下UI程序设计, 差不多是玩家打开一个游戏最先看到的东西, 差不多也是玩家最不在意的东西. 对开发者来说, 几乎每个游戏模块都与 UI 有联系, 处理不当 UI 就是恶梦. 宽高比适应, 分辨率适应, 像素对齐…光是这些就足够没有经验的开发者浪费大量的时间了. 好在 Unity 这样的引擎提供了已经很强大的 UI 解决方案, 以及许多其他开发者提供的插件. 但是这还不够. 这篇文章主要谈一谈 UI 的逻辑设计而不是排版设计上的经验, 同时也在说明我的插件可以用来解决什么问题.


    一、使用事件
    屏幕角落里有一个 “血条”, 代表玩家的生命值. 决战的时候到了, 玩家抽出他的刚剑与怪物厮杀. 几乎没有人可以毫发无伤的打败怪物. 那么问题来了, 应该在什么时候修改 “血条” 的填充率?

    一个偷懒的做法是每帧去读取玩家的生命值, 然后应用到 “血条” 的填充率上. 好吧这的确可以, 暂时没什么问题 (其实还有一
    种人神共粪的办法是依据 “谁开发谁保护, 谁污染谁治理” 原则…). 然而策划说, 当玩家被攻击时,  “血条” 应当播放一个粒子动画效果, 因为帅. 如果你还是不打算改进方法, 那就缓存玩家的生命值然后每帧对比吧! 但是接下来策划又说, 因中毒损失生命值时播放的粒子效果是紫色的, 因被攻击损失生命值时播放的粒子效果是黄色的. 啊哦, 你放弃了, 你不想改了, 都写那么多了不是吗? 你严肃的对策划说, 这个做不了, 要大改, 游戏做不完的话, 这锅……

    观察者模式闪亮登场! 如果你与世无争对<四十二章经>这种神功秘笈没有兴趣的话, 那么应当很了解 C# 的 delegate 和 event 了 (不了解的点这里). 如果玩家每次生命值变化都大叫一声 “我因为什么原因而损伤/增加多少生命值”, AI 模块可以听见, UI 模块可以听见, Story 模块可以听见, 整个世界都可以听见……我的意思是, UI 在初始化时将 OnPlayerHpChange 方法注册到玩家的 onHpChange 事件里, 当事件触发时根据具体的参数来修改 “血条” 填充率和播放相应的粒子效果, 多么简洁优雅!
    可是不要忘了在恰当的时候取消注册事件. 这大概是最常发生的错误了. HUD 是作为一个非游戏核心模块存在的, 一般仅用来展示
    一些玩家需要关心的信息. 无论如何游戏不能因为 HUD 模块的错误而停止运行. 然而忘记取消注册事件可能导致这种情况发生. 比如某些 HUD 对象已经销毁后, 玩家生命值发生变化时触发这些 HUD 对象曾经注册的事件就会造成空引用异常. 另外一种不取消注册事件造成的错误是, 当游戏关卡重新开始时, HUD 因重新初始化而重复注册事件, 相同的方法在事件触发后执行多次.

     
    二、使用动画
    制作精美的游戏, 几乎都少不了带动画的 UI. 生硬的直接弹出窗口的方式已经是过去式了. 好吧, 那么加动画就是了, 有什么可以说的呢?比如说活动窗口切换问题. 因为动画的存在, 活动窗口的变化不再是 “瞬间完成” 的而是 “经历一段时间”. 时间就是问题. 现在我们在游戏主菜单界面, 点了一下 Options 按钮. 主菜单界面开始滑出屏幕左边界, Options 界面从屏幕右边界滑入. 在动画过程中, 如果玩家手速惊人, 又点了一下主菜单界面的开始游戏按钮会发生什么事呢? 或者只是快速的连续点击了 Options 按钮呢? 
    我们可以认为没有人想这么做, 除非他是误操作的. 好吧既然是误操作那么就忽略吧, 离开一个界面的动画开始时就立即关闭这个
    界面的 “可交互性”. 那么什么时候打开新界面的 “可交互性” 呢? 其实在动画开始到结束的任何时候都可以, 但是从避免误操作的角度出发还是应当在动画结束后才打开 “可交互性”.
    然后是动画控制问题. 现在我们有两个界面同时发生移动, 可能还有颜色, 不透明度, 缩放等一系列视觉属性的变化, 甚至还有 3D 相机的位置和朝向的变化. 我们希望所有的动画同时开始, 同时结束, 并且大多数动画具备相同的变化过程, 比如先加速后减速. 既然如此, 为何不设计一种动画控制器来负责这一切呢? 可以调整变化曲线, 可以设置持续时间, 可以关联多个动画元素, 可以触发结束事件……当动画开始的时候, 我们只需要打开这一个控制器, 这个控制器负责更新所有关联的动画, 最后在动画结束时打开新界面的 “可交互性”.

    最后是开发成本问题. 为了兼容各种不同的设备, 开发中 UI 本身就十分复杂易变, 再加上 UI 动画的存在让制作和修改成本再上
    一层楼. 在动画这一方面, 如果可以避免技术人员重复劳动, 修改代码, 甚至不需要技术人员的参与就可以实现, 无疑可以省去大
    量的成本. 在使用 Unity 这样的完善的开发工具时, 在编辑器中就可以方便的编辑和预览动画将可以大大减少技术人员的开发时间.

    三、使用栈状态机
    你可能知道栈, 也可能知道状态机, 但栈状态机是什么鬼?
    你的主菜单界面有 5 个按钮, 每个按钮点击后都打开一个新的界面, 同时让主菜单界面消失. Easy! 聪明的你写了 “隐藏主菜单
    ” 和 5 个 “显示xx界面” 方法在每个按钮事件里调用. 这没什么嘛. 然后打开的新界面都有返回主菜单的按钮, 你同样写了 5 个 “隐藏xx界面” 和 “显示主菜单” 的方法, 在返回按钮事件里调用它们. 你开始有点烦了. 更麻烦的是每个打开的界面还可以打开下一级界面, 每个按钮都要绑定一个 “隐藏当前界面” “显示下一个界面” 的方法, 最后你会想, 为什么我总是重复做一件相同的事情?
    因为你没有使用状态机. 主菜单界面的 5 个按钮, 虽然点击后目标界面不同, 但都需要先离开主菜单. 如果每个界面是一个 “状
    态”, 当进入状态时显示这个界面, 离开状态时隐藏这个界面, 那么只要状态发生变化, 离开和进入的状态都会做好自己的事情, 
    这样每个按钮的唯一任务就是切换状态了.
    我们再进一步思考这个问题. 既然同一时间只有一个活动界面, 并且只能从这个界面进入下一层界面或返回上一层界面, 这不正是 “栈” 的概念吗? 如果所有的状态都存储在栈里, 那么 “进入下一层界面” 就是栈的 Push 操作, “返回上一层界面” 就是栈的 Pop 操作. 哇哦, 听起来很不错的样子……但仔细想想, 与使用普通的状态机相比, 栈状态机 Push 操作与普通状态机 
    SetState 一样需要一个新状态参数, 只是 Pop 操作比普通状态机 SetState 省略了一个参数而已. 似乎并没有什么根本的区别嘛! 
    这里我们再扩展 “状态” 为 “栈状态”, 在 OnEnter 和 OnExit 基础上添加 OnPush 和 OnPop, 就可以做更多的事情了! 想一
    想, 一个新界面入栈的时候, 旧界面不必完全消失, 可以只是不可交互了而已. 这样就可以实现更丰富的 UI 效果了!

    现在你已经掌握了开发 UI 的秘诀了, 而且也不必重新造轮子,  White Cat’s Toolbox插件可以省去你半年的休息时间, 更重要的是可以立即为你创造更多价值. 而且这已经是第三个版本了. 当然不仅可以做 UI, 还有许多其他实用的工具, 比如路径. 几乎所有的东西都可以通过脚本访问和扩展. 包含完整源代码哦!

    UI优化

    UGUI的优点

    1、所见即所得的编辑方式,在Scene窗口中即可编辑。 
    2、智能的Sprite packer可以将图片按tag自动生成图集而无需人工维护,生成的图集合并方式比较合理,无冗余资源。 
    3、渲染顺序与GameObject的Hierarchy顺序相关,靠近根节点显示在底层,而靠近叶子节点显示在顶层;这样的渲染方式使得调整UI的层级比较方便和直观。 
    4、RectTranForm及锚点系统更适合于2D平面布局,并且非常方便多分辨率屏幕自适配。

    关于UGUI优化的,或许你会觉得UI的制作规范及指导方法与优化无关,其实很多性能问题往往是资源的不合理使用造成的,比如使用了尺寸过大的图片、引用了过多的图集以及加载了不必要的资源等。如果从设计和制作UI一开始就遵守特定的规范,则可以规避不必要的性能开销。笔者根据参与的多个项目总结了以下几点通用的规范和指导方法(这些规范适用于所有项目,不管你使用UGUI还是NGUI)。 

    优化其一: 合理的分配图集 
    合理的分配图集可以降低drawcall和资源加载速度;具体细节如下: 
    1、 同一个UI界面的图片尽可能放到一个图集中,这样可以尽可能的降低drawcall。 
      
    2、 共用的图片放到一个或几共享的图集中,例如通用的弹框和按钮等;相同功能的图片放到一个图集中, 例如装备图标和英雄头像等;这样可以降低切换界面的加载速度。 
      
    3、 不同格式的图片分别放到不同的图集中,例如透明(带Alpha)和不透明(不带Alpha)的图片,这样可以减少图片的存储空间和占用内存。(UGUI的sprite packer会自动处理这种情况) 
      
    优化其二、 resources目录中应该只保存prefab文件,其它非prefab文件(例如动画,贴图,材质等)应放到resource目录之外 
    因为随着项目的迭代,可能会导致部分资源(动画,贴图)等失效,如果这些文件放在resource目录下,在打包时,unity会将resource目录下文本全部打成一个大的AssetBundle包(非resouce目录下的文件只有在引用到时才会被打到包里),从而出现冗余,增加不必要的存储空间和内存占用。
      
    优化其三、 关卡内的UI资源不要与外围系统UI资源混用 
    在关卡内,需要加载大量的角色及场景资源,内存比较吃紧,一般在进入关卡时,都会手动释放外围系统的资源,以便使关卡内有更多的内存可以使用。如果战斗内的UI与外围系统的UI使用相同图集里的图片,则有可能会使得外围系统的图片资源释放不成功。对于关卡内与外围共用的UI资源需要特殊处理,一般来说复制一份出来专门给关卡内使用是比较好的选择。 
      
    优化其四、适当的降低图片的尺寸 
    有时UI系统的背景可能会使用全屏大小的图片,比如在Iphone上使用1136*640大小的图片;使用这样尺寸的图片代价是很昂贵的,可以和美术同学商量适当的降低图片的精度,使用更低尺寸的图片。 
      
    优化其五、 在android设备上使用etc格式的图片 
    目前,几乎所有android设备都支持etc1格式的图片,etc1的好处是第个像素点只战用0.5个字节而普通rgba32的图片每个像素点占4个字节,也就说一张1024*1024图片如果使用rgba32的格式所占用的内存为4M而etc1格式所占用的内存仅为0.5M。但是使用etc1格式的图片有两个限制——长和宽必须是POT的(2的N次方)并且不支持alpha通道,因此使用etc1时需要额外的一张图来存储alpha通道,并且使用特殊的shader来对alpha采样。
      
    优化其六、 删除不必要的UI节点、动画组件及资源 
    随着项目的迭代,可能有部分ui节点及动画已经失效,对于失效的节点及动画一定要删除,在很多项目中,有部分同学为了方便省事,只是将失效的节点及动画disable了。这样做虽然在运行时不会对cpu造成太多负担,但是在加载时会增加不必要的加载时间以及内存占用。对于废弃的UI图片资源,虽然未放到Resource目录最终不会打到包里,但是在Editor模式下仍然会打到图集中从而影响优化决策。 
      

    展开全文
  • 答案是中间那一个,这种UI显示3D物体适用很多场景,比如说商店展示模型展示、例子特效、2.5d游戏,实现起来很简单,接下来我们实现一下 实现步骤 1、新建一个相机 对准角色 2、UI新建一个RawImage(别忘了吧尺寸调...
  • Unity3D开发之设置模型显示在UI前面

    万次阅读 2020-01-14 09:50:11
    对于广大Unity开发者都知道,unity引擎默认UI渲染在最上层。所以,想要实现这个功能需要我们自己去处理下。 我这里提供了两个实现的方法。各有优缺点。根据自己的需求来选择。首先我们需要额外一个摄像机Model...
  • Unity3DUI菜单列表,滑动展示UI

    千次阅读 2020-05-20 16:05:06
    物体或者UI的在平面上的旋转展示的代码实现,这个功能也是用的比较多的模块,可以将这个代码做成模板,在以后的项目中都会用到。 二、原文 原文地址:http://www.manew.com/thread-110573-1-1.html 原文作者...
  • Unity3D 虚拟现实开发(三)-UI

    千次阅读 2018-11-13 21:38:36
    一款软件肯定要有好的界面了,Unity3D 5.X版本后开始了UGUI功能。 下面我们来讲解一下,Unity3D UGUI 界面的简单制作。看下面这张图,咱们将UI实现呢   下面我们就开始制作UI,哎,原来的图片没有了,还得自己...
  • Unity之在UI界面上显示3D模型

    万次阅读 2017-02-04 18:30:01
    1、创建一个3D摄像机,渲染3D模型。(我为了方便就把模型放到了Camera的下面,你可以不这样) 2、在2D里面指定一个TopLeft和BottomRight,用来表示模型渲染到UI上面的区域。 3、在之前的3D摄像机...
  • UI展示3d模型

    2019-06-04 12:35:15
    解决这种问题最简单粗暴的就是直接设置两个摄像机,每一个UICamera,一个3d模型Camera,然后摄像机成像进行叠加,但是这样的话可能有一些UI层级的问题,今天文章记录的是另一种方式来展示3d模型。 创建一个Rend...
  • Unity3D快速实现UI架构设计一

    千次阅读 2017-05-14 20:15:57
    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀...CSDN视频网址:http://edu.csdn.net/lecturer/144 在利用Unity3D引擎开发程序时,UI资源的加载,卸载,隐藏以及UI渐变动画等功能是UI架构设计
  • 对于广大Unity开发者都知道,unity引擎默认UI渲染在最上层。所以,想要实现这个功能需要我们自己去处理下。 我这里提供了两个实现的方法。各有优缺点。根据自己的需求来选择。首先我们需要额外一个摄像机ModelCamera...
  • 该脚本用于跟随物体显示UI标签(如角色名、血条等)。 跟随角色,显示角色名或者血条/蓝条等,且不受摄像机距离远近影响。 可扩展:使该UI未处于视野范围内时隐藏,处于视野范围内时显示。 效果图如下所示: ...
  • Unity_UGUI_如何在UI界面上显示3D物体

    千次阅读 2019-09-24 15:36:28
    UI --> Image 创建一个图片 用来做界面的背景图片 3.把图片 拖到 图片Image组件上的Source Image属性上 4.设置Main Camera Main Camera的Clear Flags 设置为Depth only Main Camera的Culling Mask 的 ...
  • 解决同时响应UI3D物体事件 传统使用OnMouseDown回调会同时响应UI3D物体事件,可使3D物体继承IPointerClickHandler实现OnPointerClick方法避免穿透(使用此方法需要在摄像机上挂Physics Raycaster脚本) public ...
  • UI --> Image 新建一个图片 作为背景图片 2.给Image 指定背景图片 3.在Canvas 下新建一个 Raw Image 4.再 新建一个摄像机 5.再新建一个 游戏物体 Cube 6.在 Project 新建一个 Render Texture ...
  • UnityUI界面上显示3D模型/物体,控制模型旋转

    千次阅读 多人点赞 2018-07-19 23:10:54
    UnityUi显示3D物体/模型,控制物体旋转,转动全教程-超简单 3D物体在UI界面的显示 Chinar 本文提供全流程,中文翻译,助力快速利用 UGUI 完成 3D 物体在 UI 界面的显示 游戏开发过程中,我们时长会需要把 3D 游戏...
  • 详细描述查看https://blog.csdn.net/weixin_41843959/article/details/80944478
  • unity3d 实现UI界面上渲染多个3D模型

    千次阅读 2018-07-09 09:15:36
    在查找如何ui显示3d模型发现Camera的TargetTexture挺简便的,可惜一直没找导如何去渲染多个3D模型,用多个camera去做效果不是理想,于是自己写了个,但是有上限限制。对于还不会使用camera去实现的可以用以下链接...
1 2 3 4 5 ... 20
收藏数 2,432
精华内容 972
关键字:

ui展示3d unity3d