开发者中心 开发者中心
  • 简体中文
  • English
视频教程
敢为云网站
  • 6.0版本
  • 6.1 版本
视频教程
敢为云网站
  • 平台概述
  • 平台功能
  • 平台安装
  • 开发者指南
    • 协议插件开发
    • 扩展插件开发
    • 报警插件开发
    • 应用插件开发
    • Web可视化开发
    • 3D可视化开发
      • 低代码开发
      • 二次开发
        • 概述
        • 编辑器插件
        • 开发实战
          • 场景开发
          • 三维设备开发
          • UI控件开发
          • 进阶
        • 附录
    • 桌面可视化开发
    • 小程序开发
  • 项目实战
  • 附录

开发实战

# 开发实战

通过场景开发、三维设备开发、UI控件开发三个案例,从拿到二次开发包开始,一直到在3D可视化平台看到实际效果,完整的演示整个流程。

二次开发包可以从3D开发开源仓库 (opens new window)中获取,三个案例均使用此开发包,以下不再赘述。

# 场景开发

开发步骤
  1. 创建项目。首先打开Unity Hub ,点击打开按钮旁边的倒三角,选择从磁盘添加项目。

    点击到开发包路径,选择iotcenter-3d-development文件夹,点击添加项目.

    此时项目列表会出现添加后的文件夹名称,双击打开即可。打开后界面如下,编辑器工具也会自动打开

    提示

    若编辑器工具没有自动打开,参考编辑器工具部分内容打开编辑器工具。如果布局和案例不一样,是因为Unity布局可以自定义,可随意修改。

  2. 创建新场景。打开项目后,打开编辑器工具,然后在侧边栏点击新建场景按钮。

    提示

    本教程使用编辑器工具创建场景,工具会将一些必要的、重复的操作自动完成,比如创建设备预制体等等。

    根据弹窗提示选择文件夹并填写文件名称然后保存即可创建新场景。

    注意

    场景文件名称必须全部小写

    创建完成后场景的默认结构如下:

    提示

    Main Camera物体用于在Game视图调试效果,在Bulid更新包时需要隐藏掉。

  3. 增加模型。在场景中添加一个Cube模型

    提示

    Bulid更新包时,请注意场景是否保存,如果没有保存场景,Bulid后不会显示没保存的数据。

  4. 构建AB包。

    首先需要设置IoT 3D平台的路径,在编辑器工具窗口选择AssetBundles点击Browse选择路径。

    点击Open Folder可以打开当前配置的路径。

    点击Bulid按钮等待构建完成。

    构建进度条消失后点击Run IoTCenter3D按钮打开3D平台。

  5. 平台预览。输入服务器地址、用户名、密码,登录平台。

    登录成功后进入编辑模式。

    创建场景。

    提示

    1. 首先打开场景编辑面板
    2. 选中根节点Scene
    3. 点击添加场景

    为场景设置名称.

    点击三维场景可以看到刚才创建的场景,鼠标选中点击选择即可加载场景。

    创建的cube正常显示在场景中.

# 三维设备开发

开发步骤
  1. 创建项目。参考场景开发部分的内容创建项目即可。

  2. 创建Cube设备。

    提示

    本教程使用编辑器工具创建场景,工具会将一些必要的、重复的操作自动完成,比如创建设备预制体等等。

    打开编辑器工具后,创建设备页面默认显示,填写基本脚本名称、设备名称等参数后点击创建即可(设备模型和设备图表可以为空,也可以为其选择物体和图标)。

    等待一会,场景中已经添加了刚才创建的设备预制体,点击Open进入编辑。

    添加Cube模型,保存预制体。

  3. 构建AB包。参考场景开发部分的内容构建AB包即可。

  4. 平台预览。登录3D平台,并进入编辑模式后点击资源库,下拉滚动条即可看到创建的设备

# UI控件开发

制作网络图片UI控件为例介绍UI控件的开发步骤。

提示

本次案例代码可以在二次开发包中查看,路径如下:

  1. UI_NetworkImage.cs:\iotcenter-3d-development\Assets\SceneModule\TianjinPortScenes\UIControl\Scripts
  2. UI_NetworkImage:\iotcenter-3d-development\Assets\SceneModule\TianjinPortScenes\UIControl\Prefabs
开发步骤
  1. 创建项目。参考场景开发部分的内容创建项目即可。

  2. 创建控件

    提示

    本教程使用编辑器工具创建场景,工具会将一些必要的、重复的操作自动完成,比如创建设备预制体等等。

    由于本案例是显示一个网络图片所以需要创建UI控件。点击编辑器工具控件类型下拉框,选择UI控件。

    创建控件页面会自动弹出,设置好参数后,也可以查看代码的实时预览,确定无误后点击创建按钮,等待自动完成创建基本代码和预制体。

    自动创建完成后,场景中会多出Canvas 物体,展开后可以看到UI控件默认预制体

  3. 制作界面。

    在编辑器工具中,选择控件类型为UI控件,在控件列表中点击创建的UI在控件详情页面中点击预览控件,会打开预制体专属场景。

    打开场景后,点击2D按钮 只看平面视图,更好的制作UI界面。

    选中控件,首先设置UI控件在IOT 3D平台时显示的名称

    由于自动创建的UI 控件默认是一个Image,但是本案例选择不用Image,所以删除Image组件。

    本案例使用RawImage,在UI_NetworkImage物体下新建一个RawImage子物体。

    设置RawImage锚点,这样可以在IOT 3D平台调整图片大小。

  4. 编写脚本。

    选中预制体根物体,双击脚本组件下的引用可以在IDE打开

    代码模板:

    using UnityEngine.UI;
    public class UI_NetworkImage : UIControl
    {
        /// <summary>
        /// 用于公开给用户配置的属性
        /// </summary>
        #region 属性 
        [SerializeField]
        private string m_tips;
        public string Tips
        {
            get { return m_tips; }
            set { m_tips = value; }   
        }
        #endregion
    
        /// <summary>
        /// 定义平台显示UI控件时在哪个分类
        /// </summary>
        public override UIResEnum uIResEnum => UIResEnum.Other;
    
        /// <summary>
        /// 获取配置的属性后调用
        /// </summary>
        public override void OnSerialized()
        {
    
        }
    
        private void Awake()
        {
        }
    
        /// <summary>
        /// UI在平台隐藏时调用
        /// </summary>
        public override void OnClose()
        {
            base.OnClose();
        }
    
        /// <summary>
        /// UI在平台显示时调用
        /// </summary>
        public override void OnOpen()
        {
            base.OnOpen();
        }
    
        /// <summary>
        /// 用于获取子物体组件的方法
        /// </summary>
        /// <typeparam name="T">组件类型</typeparam>
        /// <param name="name">物体在预制体中的名称</param>
        /// <returns></returns>
        T GetGame<T>(string name)
        {
            return transform.Find(name).GetComponent<T>();
        }
    }
    
    • 为了获取RawImage,定义RawImage类型的字段,需要引用UnityEngine.UI。

      using UnityEngine.UI;
      

      字段定义如下:

      /// <summary>
      /// 定义一个 RawImage
      /// </summary>
      RawImage rawImage;
      
    • 在Awake方法中获取到RawImage。

      private void Awake()
      {
          //获取到 RawImage
          rawImage = GetGame<RawImage>("RawImage");
      }
      
    • 删除默认创建的属性,创建一个公开属性URL,用户可以在IOT 3D平台进行配置,让控件更加通用,同时也可以赋一个默认值,让控件默认就能加载出一张网络图片。

      /// <summary>
      /// 用于公开给用户配置的属性
      /// </summary>
      #region 属性 
      [SerializeField]
      private string m_url = "https://s3.bmp.ovh/imgs/2022/07/15/1abf154a41a46201.jpg";
      public string Url
      {
          get { return m_url; }
          set 
          { 
              m_url = value;
          
              Debug.Log(value);
          }
      }
      #endregion
      
    • 使用协程获取网络图片。

      添加如下引用:

      using System.Collections;
      using UnityEngine.Networking;
      

      获取网络图片方法如下所示:

       /// <summary>
      /// 获取图片
      /// </summary>
      /// <returns></returns>
      IEnumerator LoadImage()
      {
          //使用Unity提供的API获取网络图片
          UnityWebRequest www = UnityWebRequestTexture.GetTexture(Url);
          //等待图片返回
          yield return www.SendWebRequest();
          //判断是否获取图片失败
          if (www.result == UnityWebRequest.Result.ConnectionError)
              Debug.Log(www.error);
          else
          {
              //获取图片成功后,如果有,先删除之后的图片防止内存泄漏
              if (rawImage.texture)
                  DestroyImmediate(rawImage.texture);
              //设置图片到 RawImage组件
              rawImage.texture = DownloadHandlerTexture.GetContent(www);
          }
          //释放UnityWebRequest
          www.Dispose();
      }
      
    • 在每次显示组件时获取一次图片。

      /// <summary>
      /// UI在平台显示时调用
      /// </summary>
      public override void OnOpen()
      {
          base.OnOpen();
          //打开时获取一次图片
          StartCoroutine(LoadImage());
      }
      
    • 完整代码如下:

      using System.Collections;
      using UnityEngine;
      using UnityEngine.Networking;
      using UnityEngine.UI;
      
      public class UI_NetworkImage : UIControl
      {
          /// <summary>
          /// 用于公开给用户配置的属性
          /// </summary>
          #region 属性 
          [SerializeField]
          private string m_url = "https://s3.bmp.ovh/imgs/2022/07/15/1abf154a41a46201.jpg";
          public string Url
          {
              get { return m_url; }
              set 
              { 
                  m_url = value;
              
                  Debug.Log(value);
              }
          }
          #endregion
      
          /// <summary>
          /// 定义一个 RawImage
          /// </summary>
          RawImage rawImage;
      
          /// <summary>
          /// 定义平台显示UI控件时在哪个分类
          /// </summary>
          public override UIResEnum uIResEnum => UIResEnum.Other;
      
          /// <summary>
          /// 获取配置的属性后调用
          /// </summary>
          public override void OnSerialized()
          {
      
          }
      
          private void Awake()
          {
              //获取到 RawImage
              rawImage = GetGame<RawImage>("RawImage");
          }
      
          /// <summary>
          /// UI在平台隐藏时调用
          /// </summary>
          public override void OnClose()
          {
              base.OnClose();
          }
      
          /// <summary>
          /// UI在平台显示时调用
          /// </summary>
          public override void OnOpen()
          {
              base.OnOpen();
              //打开时获取一次图片
              StartCoroutine(LoadImage());
          }
      
          /// <summary>
          /// 获取图片
          /// </summary>
          /// <returns></returns>
          IEnumerator LoadImage()
          {
              //使用Unity提供的API获取网络图片
              UnityWebRequest www = UnityWebRequestTexture.GetTexture(Url);
              //等待图片返回
              yield return www.SendWebRequest();
              //判断是否获取图片失败
              if (www.result == UnityWebRequest.Result.ConnectionError)
                  Debug.Log(www.error);
              else
              {
                  //获取图片成功后,如果有,先删除之后的图片防止内存泄漏
                  if (rawImage.texture)
                      DestroyImmediate(rawImage.texture);
                  //设置图片到 RawImage组件
                  rawImage.texture = DownloadHandlerTexture.GetContent(www);
              }
              //释放UnityWebRequest
              www.Dispose();
          }
      
          /// <summary>
          /// 描述文件调用
          /// </summary>
          public void UpdateImg()
          {
              Debug.Log("UpdateImg");
              StartCoroutine(LoadImage());
          }
          /// <summary>
          /// 用于获取子物体组件的方法
          /// </summary>
          /// <typeparam name="T">组件类型</typeparam>
          /// <param name="name">物体在预制体中的名称</param>
          /// <returns></returns>
          T GetGame<T>(string name)
          {
              return transform.Find(name).GetComponent<T>();
          }
      }
      
      
      
  5. 构建AB包。参考场景开发部分的内容构建AB包即可。

  6. 平台预览。

    登录3D可视化平台并进入编辑模式后,选中UI资源库,选择其他分类,因为网络图片控件代码中将分类设置成了Other。

    控件名称也和设置的一样显示为网络图片。

    将其拖动到场景中,会加载出默认图片,并且公开属性URL也可以配置

# 进阶

在平台预览时发现修改公开属性URL的网址,只能保存后重启三维才能更新。进阶要实现重新填写网址后能实时更新获取图片。

开发步骤
  1. 创建描述文件。首先找到UI_NetworkImage脚本,在其目录下创建文件夹ComponentDescriptors。

  2. 在创建的文件夹下新建脚本NetworkImageComponentDescriptor.cs(类名可以修改)。

  3. 编写脚本。

    • 默认脚本。

      using System.Reflection;
      using UnityEngine;
      
      public class NetworkImageComponentDescriptor : MonoBehaviour
      {
          //Start is called before the first frame update 
          void Start()
          {
      
          }
      
          //Update is called once per frame
          void Update()
          {
      
          }
      }
      
    • 填加特性[BuiltInDescriptor],继承ComponentDescriptorBase类,并且重写GetProperties方法。

      using IoT3D.RunTimeEditor;
      
      /// <summary>
      /// UI_NetworkImage 描述文件
      /// </summary>
      [BuiltInDescriptor]
      public class NetworkImageComponentDescriptor : ComponentDescriptorBase<UI_NetworkImage>
      {
          public override PropertyDescriptor[] GetProperties(ComponentEditor editor, object converter)
          {
              throw new System.NotImplementedException();
          }
      }
      
      
    • 编写获取UI_NetworkImage的公开属性URL,并且设置回调方法等。同时UI_NetworkImage也可以增加一个公开方法用于刷新数据。

      提示

      这里编写了两种回调,采用的是endEditCallback回调,也就是输入框输入完成后才回调

      using IoT3D.RunTimeEditor;
      using IoT3D.Utils;
      using System.Collections.Generic;
      using System.Reflection;
      using UnityEngine;
      
      /// <summary>
      /// UI_NetworkImage 描述文件
      /// </summary>
      [BuiltInDescriptor]
      public class NetworkImageComponentDescriptor : ComponentDescriptorBase<UI_NetworkImage>
      {
          public override PropertyDescriptor[] GetProperties(ComponentEditor editor, object converter)
          {
              this.editor = editor;
              //设置值更改回调
              PropertyEditorCallback valueChanged;
              valueChanged = OnValueChanged;
      
              //设置值结束回调
              PropertyEditorCallback valueEnd;
              valueEnd = OnValueEnd;
      
              //获取选中的第一个控件
              dev_Image = editor.Components[0] as UI_NetworkImage;
              List<PropertyDescriptor> descriptors = new List<PropertyDescriptor>();
              //获取属性
              MemberInfo urlInfo = Strong.PropertyInfo((UI_NetworkImage x) => x.Url, "Url");
              //设置显示名称、回调
              descriptors.Add(new PropertyDescriptor("链接", editor.Components, urlInfo, urlInfo, valueChanged, valueEnd));
              return descriptors.ToArray();
          }
      
          /// <summary>
          /// 值更改
          /// </summary>
          public virtual void OnValueChanged()
          {
              Debug.LogError("OnValueChanged");
          }
      
          /// <summary>
          /// 值结束
          /// </summary>
          public virtual void OnValueEnd()
          {
              dev_Image.UpdateImg();
          }
      }
      
      
    
    -   `UI_NetworkImage.cs`类中增加`UpdateImg`方法用于描述文件接收到值更改后调用。
    
     ```csharp
     /// <summary>
     /// 描述文件调用
     /// </summary>
     public void UpdateImg()
     {
         Debug.Log("UpdateImg");
         StartCoroutine(LoadImage());
     }
     ```
    
  4. 平台预览

    由于只是修改了代码,可以直接点击OnlyCopyScrpts按钮将代码拷贝到平台,然后点击RunIoTCenter3D启动平台。

    此时修改网址后,图片实时修改成功。

上次更新: 5/22/2023, 7:05:49 PM

← 编辑器插件 附录→

目录
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式