• 8种家居环境很败“性” 2019-06-28
  • 2018年全军院校招生计划下达:计划招收学员3.05万名 2019-06-15
  • 晋城市举办干部素质提升工程第十八期专题讲座 2019-06-15
  • 抖音广告出现对英烈邱少云不敬内容 今日头条致歉 2019-06-13
  • 超半数巴西民众对世界杯不感兴趣--旅游频道 2019-06-12
  • 外交部举行中外媒体吹风会:王毅介绍上合组织青岛峰会情况 2019-06-12
  • 2018网络中国节·端午 2019-06-04
  • 韩媒:韩美商定暂停原定8月“乙支自由卫士”联演 2019-06-03
  • 重庆市公安局交通管理局互联网交通安全服务管理平台 2019-06-03
  • 俄侦察船穿越英吉利海峡 英国急派军舰战机监视 2019-05-28
  • 网购陷阱多 女子花3000元买5套化妆品只有2套是真的 2019-05-28
  • 环保约谈濂溪区主要负责同志 谢一平要求立行立改真抓真改 2019-05-25
  • 官宣!广东签约北京3冠功勋 大莫助拳阿联未来可期 2019-05-25
  • 党建第一责任与发展第一要务相融合br全面提升机关党建工作水平 2019-05-22
  • 卡纳瓦罗:对比赛结果不满意 晋级机会各占一半 2019-05-22
  • 江苏十一选五走势图表: zhang273162308 Unity实用小工具或脚本—利用反射制作动态编辑栏(四

    53
    回复
    2186
    查看
    打印 上一主题 下一主题
    [ 复制链接 ]
    排名
    141
    昨日变化

    福建36选7和值走势图 www.00-na.com 121

    主题

    572

    帖子

    6936

    积分

    Rank: 9Rank: 9Rank: 9

    UID
    3579
    好友
    110
    蛮牛币
    5222
    威望
    0
    注册时间
    2013-9-10
    在线时间
    1510 小时
    最后登录
    2019-7-16

    专栏作家活力之星游戏蛮牛QQ群会员蛮牛哥

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

    您需要 登录 才可以下载或查看,没有帐号?注册帐号

    x
    本帖最后由 zhang273162308 于 2019-5-13 17:41 编辑

    一、前言
        在上一篇中,已经可以处理基本的数据类型的动态编辑栏创建并且保存数据的功能。但是,对于自定义的类型,比如Unity自带的Vector类型,还不能处理。另外,编辑栏都是单一的输入框,针对不同的数据创建不同的编辑框,如Bool类型,应该是Toggle类型。本篇主要是对这两个功能的实现。效果图如图所示:点击创建会动态生成结构体里所有的编辑栏,相比之前的只有输入框的编辑栏,这里增加了对Bool、Vector3变量类型的处理,Bool类型的会生成Toggle的,Vector3会生成带X、Y和Z的三个短输入框组合。并且,再Vector3的三个输入框中输入字符会自动删除,只能输入数字。再点击保存的时候会将编辑栏中的数据保存到结构体中,右下角的GlobalCtr中的TestData结构体数据会响应编辑栏的变化。

    二、实现
    1、动态编辑栏的拓展,在原有的基础上,我们将对原有的动态编辑栏预设新增Toggle、DropdownList和Vector3组合框,如下图所示:每个编辑框都默认是失活的,针对不同的变量类型,显示不同的输入框。

    动态编辑栏的初始化函数修改如下:通过Switch里对不同变量的类型进行不同的处理,注意Vector3是Unity自带的类型,它的完整类型名称为:“UnityEngine.Vector3”。针对Vector3这样的自定义类型,需要额外的脚本对其进行处理,控制这个组合编辑框
    [AppleScript] 纯文本查看 复制代码
    public void Init(Type variableType, string name,string value,string[] enumValue=null,Type strcutType=null,bool isInteractable=true)
        {
            valueInputContent = GetComponentInChildren<InputField>(true);
            valueDropdown = GetComponentInChildren<Dropdown>(true);
            valueToggle = GetComponentInChildren<Toggle>(true);
            valueVectorInput = GetComponentInChildren<UI2D_SubObjEAVectorInput>(true);
    
            valueDropdown.interactable = isInteractable;
            valueToggle.interactable = isInteractable;
            valueInputContent.interactable = isInteractable;
    
            varibleName = name;
            textName.text = name;
          //  Debug.Log(variableType.FullName+"v:"+value+"stype:"+strcutType.ToString());
            switch (variableType.FullName)
            {
                case "System.String":
                    valueInputContent.text = value;
                    curValue = value;
                    lastValue = curValue;
                    valueInputContent.gameObject.SetActive(true);
                    break;
                case "System.Int32":
                    if (null == enumValue)
                    {
                        valueInputContent.text = value;
                        valueInputContent.gameObject.SetActive(true);
                        valueInputContent.contentType = InputField.ContentType.IntegerNumber;
                    }
                    else
                    {
                        valueDropdown.gameObject.SetActive(true);
                        List<string> tempStrList = new List<string>();
                        for (int i = 0; i < enumValue.Length; i++)
                        {
                            tempStrList.Add(enumValue);
                        }
                        valueDropdown.options.Clear();
                        valueDropdown.AddOptions(tempStrList);
                        valueDropdown.value = int.Parse(value);
                    }
                    break;
                case "System.Boolean":
                    valueToggle.gameObject.SetActive(true);
                    bool tempIsOn;
                    bool.TryParse(value, out tempIsOn);
                    valueToggle.isOn = tempIsOn;
                    break;
                case "System.Single":
                    valueInputContent.text = value;
                    valueInputContent.gameObject.SetActive(true);
                    valueInputContent.contentType = InputField.ContentType.DecimalNumber;
                    break;
    
                case "UnityEngine.Vector3":
                    valueVectorInput.Init(value);
                    valueVectorInput.gameObject.SetActive(true);
                    break;
            }
            isInitSucced = true;
    
        }

    Vector3的编辑框控制脚本为:在初始化获取值的时候需要进行额外的处理,Vector3实例转换成字符类型一般为“(xx,xx,xx)"。不同的字段类型会决定输入框的输入字符的类型,上述代码中比如”System.Int32“类型的变量,其输入框的设置为”valueInputContent.contentType = InputField.ContentType.IntegerNumber“,这个设置保证了输入框里只能输入整数数字,并且是可以为负数的,而编号之类的输入框一般都是不为负数的更符合要求,这是Unity自带的功能,不能改变,其实还是有不足之处。

    可以通过打印Vector.ToString()来看看。这里其实也可以将object类型作为参数,主要是我不想修改”UI2D_SubObjEditorAttr“脚本里的初始化参数了,比如你可以将Init函数定义成 ,将所有的参数的值都转换成基类object

    [AppleScript] 纯文本查看 复制代码
    public void Init(Type variableType, string name,object value,string[] enumValue=null,Type strcutType=null,bool isInteractable=true)
    
    {
    
    ...
    
    }

    2、动态生成
    还需要用到之前定义的方法“GetVaule_ReflectMethod”,该方法处理了结构体的泛型和非泛型的字段或属性,并且将得到的字段或属性的
    [AppleScript] 纯文本查看 复制代码
     /// <summary>
        /// 获取结构体非泛型的所有属性和字段,并返回由所有属性的名字和值组成的列表,Out 参数返回结构体或类中的泛型属性或字段
        /// (这里只处理类或结构体只有一个List这样的泛型字段或属性)的整个列表
        /// </summary>
        /// <typeparam name="S">结构体类型</typeparam>
        /// <typeparam name="L">结构体属性或字段列表中装载的数据类型</typeparam>
        /// <param name="obj">结构体实例</param>
        /// <param name="listGenericDatas">结构体属性或字段列表</param>
        /// <returns></returns>
        public static List<NP_SingleReflectInfo> GetVaule_ReflectMethod<S, L>(S obj, out List<L> listGenericDatas)
        {
            List<NP_SingleReflectInfo> tempList = new List<NP_SingleReflectInfo>();
            listGenericDatas = new List<L>();
            try
            {
                //遍历所有的属性
                PropertyInfo[] tempPI = obj.GetType().GetProperties();
                foreach (var info in tempPI)
                {
                    //装载泛型属性
                    if (info.PropertyType.IsGenericType)
                    {
                        object tempListObj = info.GetValue(obj, null);
                        listGenericDatas = (List<L>)tempListObj;
                    }
                    else
                    {
                        string tempVarName = info.Name;
                        string tempVarVaule = info.GetValue(obj, null).ToString();
                        //    Debug.Log(info.PropertyType);
                        NP_SingleReflectInfo tempData = new NP_SingleReflectInfo();
                        tempData.Init(info.PropertyType, tempVarName, tempVarVaule);
                        //装载信息到列表中
                        tempList.Add(tempData);
                    }
                }
                //遍历所有的字段
                FieldInfo[] tempFI = obj.GetType().GetFields();
                foreach (var itemInfo in tempFI)
                {
                    //装载泛型字段
                    if (itemInfo.FieldType.IsGenericType)
                    {
                        object tempListObj = itemInfo.GetValue(obj);
                        listGenericDatas = (List<L>)tempListObj;
                    }
                    else
                    {
                        string tempVarName = itemInfo.Name;
                        string tempVarVaule = itemInfo.GetValue(obj).ToString();
                        //  Debug.Log(itemInfo.FieldType);
                        NP_SingleReflectInfo tempData = new NP_SingleReflectInfo();
                        tempData.Init(itemInfo.FieldType, tempVarName, tempVarVaule);
                        //装载信息到列表中
                        tempList.Add(tempData);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.Log("获取类型数据错误" + e.Message);
                return null;
            }
    
            return tempList;
        }




    名字和值都以String类型返回。结构体“NP_SingleReflectInfo”是用来封装字段或属性的名字、值和类型的,其定义为:


    [AppleScript] 纯文本查看 复制代码
    /// <summary>
    /// 反射获得结构体、类中的单个变量或属性的名字和值
    /// </summary>
    [Serializable]
    public struct NP_SingleReflectInfo
    {
        /// <summary>
        /// 变量的类型
        /// </summary>
        public Type VariableType;
        /// <summary>
        /// 变量的名字
        /// </summary>
        public string VariableName;
        /// <summary>
        /// 变量的值
        /// </summary>
        public string VariableValue;
        public void Init(Type type, string name, string value)
        {
            VariableType = type;
            VariableName = name;
            VariableValue = value;
        }
    }



    定义的结构体“TestData"为:

    [AppleScript] 纯文本查看 复制代码
    [Serializable]
    public struct TestData
    {
        public float Number;
        public int Type;
        public string Name;
        public bool IsOPen;
        public Vector3 Pos;
        public void Init(float no,int type,string name,bool isOpen,Vector3 pos)
        {
            Number = no;
            Type = type;
            Name = name;
            IsOPen = isOpen;
            Pos = pos;
        }
    }


    创建按钮的点击事件方法为:该方法处理的点击创建按钮后,动态的生成结构体TestData变量testdata里的所有字段的编辑框

    [AppleScript] 纯文本查看 复制代码
        public void BtnCreate_OnClick()
        {
            List<NP_SingleReflectInfo> tempListReflectInfo = null;
            List<TestData> tempListGeneData;
            //反射创建编辑条信息
            tempListReflectInfo = GetVaule_ReflectMethod(testData, out tempListGeneData);
            if (null != tempListReflectInfo)
            {
                string[] tempStrDropdwonList = null;
                for (int i = 0; i < tempListReflectInfo.Count; i++)
                {
                    bool isInteractable = true;
                    UI2D_SubObjEditorAttr tempSubObjEA = Instantiate(prefabSubObjEA, subObjEAParent);
                    tempSubObjEA.transform.localScale = Vector3.one;
                    tempSubObjEA.Init(tempListReflectInfo.VariableType, tempListReflectInfo.VariableName, tempListReflectInfo.VariableValue, tempStrDropdwonList, testData.GetType(), isInteractable);
                    listSubObjEA.Add(tempSubObjEA);
                }
            }
        }


    3、反射赋值
    在动态的创建了结构体的字段编辑框之后,修改编辑框里面的任何值,点击保存就可以将修改后的值动态的赋值给生成动态编辑栏的变量”testData",保存按钮的代码为:


    [AppleScript] 纯文本查看 复制代码
        public void BtnSave_OnClick()
        {
            for (int i = 0; i < listSubObjEA.Count; i++)
            {
                testData = (TestData)SetValue_ReflectMethod(testData, listSubObjEA.M_VaribleName, listSubObjEA.M_Vaule);
            }
        }




    以及用到的反射赋值的方法“SetValue_ReflectMethod”为:这个方法对比之前的稍微进行了一些修改,将“paramName”的参数类型由


    [AppleScript] 纯文本查看 复制代码
        /// <summary>
        /// 使用反射动态设置结构体的变量值
        /// </summary>
        /// <typeparam name="T">结构体类型</typeparam>
        /// <param name="obj">结构体实例</param>
        /// <param name="paramName">变量的名字</param>
        /// <param name="paramValue">变量的值</param>
        /// <returns></returns>
        public static object SetValue_ReflectMethod<T>(T obj, object paramName, object paramValue)
        {
            //先装箱 变成引用类型的
            object tempObj = obj;
            if (obj != null)
            {
                try
                {
                    Type tempType = obj.GetType();
                    //设置字段
                    FieldInfo tempFI = tempType.GetField(paramName.ToString());
                    if (null != tempFI)
                    {
                         object tempObjValue = Convert.ChangeType(paramValue, tempFI.FieldType);
                        tempFI.SetValue(tempObj, tempObjValue);
                    }
                    //设置属性
                    PropertyInfo tempPI = tempType.GetProperty(paramName.ToString());
                    if (null != tempPI)
                    {
                        tempPI.SetValue(tempObj, Convert.ChangeType(paramValue, tempPI.PropertyType), null);
                    }
                }
                catch (Exception e)
                {
                    Debug.Log("编辑错误" + e.Message);
                    tempObj = null;
                }
            }
            return tempObj;
        }


    原来的“String”类型改为基类”object“类型,因为在将Vector3这样自定义的类型,而非系统基础类型的变量转换的时候不能将字符串进行转换,在” object tempObjValue = Convert.ChangeType(paramValue, tempFI.FieldType);“的时候报错,” Convert.ChangeType()”方法里在处理非基础类型的时候,参数必须是:第一个是该变量值转换成Object类型,第二个是变量的类型。

    三、总结
    1、处理了不同类型输入框的不同,并且输入框内容的控制
    2、处理了自定义类型的输入框动态生成,并且将其生成的输入框内容反射赋值给原结构体实例
    3、不足之处,还需要拓展针对更多的数据类型或自定义组合类型
    4、不能动态的进行界面排布,生成的都是依次往下排
    5、完整的工程下载地址
    游客,如果您要查看本帖隐藏内容请回复

    点评

    qiu
    报了个错啊The namespace `global::' already contains a definition for `NP_SingleReflectInfo'  发表于 2019-5-29 15:15
    怎么没看到下载地址?  发表于 2019-5-10 09:32
    7日久生情
    1958/5000
    排名
    4092
    昨日变化

    0

    主题

    1259

    帖子

    1958

    积分

    Rank: 7Rank: 7Rank: 7Rank: 7

    UID
    254705
    好友
    1
    蛮牛币
    1795
    威望
    0
    注册时间
    2017-11-16
    在线时间
    337 小时
    最后登录
    2019-7-16
    沙发
    2019-5-10 08:03:16 只看该作者
    666666666666666666666666666666
    7日久生情
    1833/5000
    排名
    1989
    昨日变化

    6

    主题

    556

    帖子

    1833

    积分

    Rank: 7Rank: 7Rank: 7Rank: 7

    UID
    54335
    好友
    3
    蛮牛币
    5430
    威望
    0
    注册时间
    2014-11-9
    在线时间
    589 小时
    最后登录
    2019-7-16
    板凳
    2019-5-10 09:00:21 只看该作者
    7日久生情
    1833/5000
    排名
    1989
    昨日变化

    6

    主题

    556

    帖子

    1833

    积分

    Rank: 7Rank: 7Rank: 7Rank: 7

    UID
    54335
    好友
    3
    蛮牛币
    5430
    威望
    0
    注册时间
    2014-11-9
    在线时间
    589 小时
    最后登录
    2019-7-16
    地板
    2019-5-10 09:02:19 只看该作者
    多谢楼主分享
    7日久生情
    1685/5000
    排名
    831
    昨日变化

    2

    主题

    143

    帖子

    1685

    积分

    Rank: 7Rank: 7Rank: 7Rank: 7

    UID
    5714
    好友
    0
    蛮牛币
    3189
    威望
    0
    注册时间
    2013-10-15
    在线时间
    358 小时
    最后登录
    2019-7-16
    5#
    2019-5-10 09:02:47 只看该作者
    关注中。。。
    7日久生情
    1833/5000
    排名
    1989
    昨日变化

    6

    主题

    556

    帖子

    1833

    积分

    Rank: 7Rank: 7Rank: 7Rank: 7

    UID
    54335
    好友
    3
    蛮牛币
    5430
    威望
    0
    注册时间
    2014-11-9
    在线时间
    589 小时
    最后登录
    2019-7-16
    6#
    2019-5-10 09:03:43 只看该作者
    楼主回复了隐藏内容还是没开放
    4四处流浪
    328/500
    排名
    11372
    昨日变化

    0

    主题

    42

    帖子

    328

    积分

    Rank: 4

    UID
    301677
    好友
    0
    蛮牛币
    290
    威望
    0
    注册时间
    2018-10-29
    在线时间
    198 小时
    最后登录
    2019-7-15
    7#
    2019-5-10 09:08:40 只看该作者

    多谢楼主分享
    7日久生情
    3794/5000
    排名
    1487
    昨日变化

    0

    主题

    2143

    帖子

    3794

    积分

    Rank: 7Rank: 7Rank: 7Rank: 7

    UID
    219676
    好友
    1
    蛮牛币
    3706
    威望
    0
    注册时间
    2017-7-12
    在线时间
    797 小时
    最后登录
    2019-7-16

    活力之星

    8#
    2019-5-10 09:09:00 只看该作者
    谢谢分享
    6蛮牛粉丝
    1155/1500
    排名
    3542
    昨日变化

    0

    主题

    319

    帖子

    1155

    积分

    Rank: 6Rank: 6Rank: 6

    UID
    180321
    好友
    8
    蛮牛币
    869
    威望
    0
    注册时间
    2016-11-21
    在线时间
    414 小时
    最后登录
    2019-7-16
    9#
    2019-5-10 09:16:43 只看该作者
    大佬6的很
    排名
    20607
    昨日变化

    0

    主题

    13

    帖子

    85

    积分

    Rank: 2Rank: 2

    UID
    218216
    好友
    0
    蛮牛币
    69
    威望
    0
    注册时间
    2017-4-18
    在线时间
    46 小时
    最后登录
    2019-7-16
    10#
    2019-5-10 09:31:24 只看该作者
    666666666666666666666666666666
    6蛮牛粉丝
    1352/1500
    排名
    2010
    昨日变化

    21

    主题

    221

    帖子

    1352

    积分

    Rank: 6Rank: 6Rank: 6

    UID
    44764
    好友
    0
    蛮牛币
    472
    威望
    0
    注册时间
    2014-9-13
    在线时间
    432 小时
    最后登录
    2019-7-15
    11#
    2019-5-10 10:02:45 只看该作者
    6666666666666666666666666666
    排名
    31431
    昨日变化

    0

    主题

    51

    帖子

    98

    积分

    Rank: 2Rank: 2

    UID
    160425
    好友
    0
    蛮牛币
    10
    威望
    0
    注册时间
    2016-8-3
    在线时间
    37 小时
    最后登录
    2019-7-12
    12#
    2019-5-10 10:10:29 只看该作者
    Unity实用小工具或脚本—利用反射制作动态编辑栏
    5熟悉之中
    668/1000
    排名
    6126
    昨日变化

    0

    主题

    81

    帖子

    668

    积分

    Rank: 5Rank: 5

    UID
    24766
    好友
    0
    蛮牛币
    66
    威望
    0
    注册时间
    2014-5-12
    在线时间
    363 小时
    最后登录
    2019-7-16
    13#
    2019-5-10 10:15:16 只看该作者
    多谢楼主分享
    5熟悉之中
    668/1000
    排名
    6126
    昨日变化

    0

    主题

    81

    帖子

    668

    积分

    Rank: 5Rank: 5

    UID
    24766
    好友
    0
    蛮牛币
    66
    威望
    0
    注册时间
    2014-5-12
    在线时间
    363 小时
    最后登录
    2019-7-16
    14#
    2019-5-10 10:17:49 只看该作者

    多谢楼主分享
    3偶尔光临
    190/300
    排名
    14744
    昨日变化

    0

    主题

    71

    帖子

    190

    积分

    Rank: 3Rank: 3Rank: 3

    UID
    236535
    好友
    0
    蛮牛币
    243
    威望
    0
    注册时间
    2017-8-8
    在线时间
    65 小时
    最后登录
    2019-7-15
    15#
    2019-5-10 10:22:20 只看该作者
    多谢楼主分享
    您需要登录后才可以回帖 登录 | 注册帐号

    本版积分规则

  • 8种家居环境很败“性” 2019-06-28
  • 2018年全军院校招生计划下达:计划招收学员3.05万名 2019-06-15
  • 晋城市举办干部素质提升工程第十八期专题讲座 2019-06-15
  • 抖音广告出现对英烈邱少云不敬内容 今日头条致歉 2019-06-13
  • 超半数巴西民众对世界杯不感兴趣--旅游频道 2019-06-12
  • 外交部举行中外媒体吹风会:王毅介绍上合组织青岛峰会情况 2019-06-12
  • 2018网络中国节·端午 2019-06-04
  • 韩媒:韩美商定暂停原定8月“乙支自由卫士”联演 2019-06-03
  • 重庆市公安局交通管理局互联网交通安全服务管理平台 2019-06-03
  • 俄侦察船穿越英吉利海峡 英国急派军舰战机监视 2019-05-28
  • 网购陷阱多 女子花3000元买5套化妆品只有2套是真的 2019-05-28
  • 环保约谈濂溪区主要负责同志 谢一平要求立行立改真抓真改 2019-05-25
  • 官宣!广东签约北京3冠功勋 大莫助拳阿联未来可期 2019-05-25
  • 党建第一责任与发展第一要务相融合br全面提升机关党建工作水平 2019-05-22
  • 卡纳瓦罗:对比赛结果不满意 晋级机会各占一半 2019-05-22
  • 德州扑克手牌胜率表 福建36选7复式票规则 羽毛球怎么发音 nba百事通极速体育直播吧 江西11选5爱彩乐 福彩杀尾技巧 任选9场胆拖 t天津福彩快乐十分 平特定位公式 五分彩软件下载 3d试机号最近30期列表 内蒙古快三走势图所有 pc蛋蛋组走势图 nba比分直播删除 双色球彩票走势图