• 回复@大雨582:社会人不可能像自然人一样自由,你还得尊重别人的意愿!不然咱随便生产啥都强行让你要,咱是自由了,你呢? 2019-10-12
  • 发改委每月首个工作日公布限制乘坐火车飞机人员名单 2019-10-12
  • 全国啦啦操联赛临汾站开幕 2019-10-08
  • 《爱疯音乐家》陈洁仪:不完美的美其实更美爱疯音乐家陈洁仪 2019-10-08
  • 中冶置业兴隆百万平米新城正式亮相 将打造全配套高铁康养小镇 2019-10-06
  • 以政府拟严打“乱拍摄”以军行为 最高10年监禁 2019-10-03
  • 图解:关于中国梦,习近平总书记这十句话直抵人心 2019-09-20
  • “舌尖”之后, “风味”能否再续辉煌? 2019-09-17
  • 腾讯要花32亿收购《绝地求生》开发商10%股份 2019-09-17
  • 涨知识!文字里的秘密 最全甲骨文书展来了 2019-09-13
  • 晋中市着力将“厕所革命”进行到底 2019-09-05
  • 供应链如何更“智慧” 2019-09-05
  • 红枣食疗效果好 6种吃法最滋补-美食资讯 2019-09-01
  • 党的十九大最重大的理论成就 2019-08-28
  • 余世存:阅读经典不仅是消费,也是责任 2019-08-20
  • 福建体彩31选7开奖走势: zhang273162308 Unity实用小工具或脚本—利用反射制作动态编辑栏(四

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

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

    主题

    595

    帖子

    7011

    积分

    Rank: 9Rank: 9Rank: 9

    UID
    3579
    好友
    109
    蛮牛币
    5550
    威望
    0
    注册时间
    2013-9-10
    在线时间
    1559 小时
    最后登录
    2019-10-12

    专栏作家活力之星游戏蛮牛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日久生情
    2299/5000
    排名
    4093
    昨日变化

    0

    主题

    1549

    帖子

    2299

    积分

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

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

    6

    主题

    565

    帖子

    1874

    积分

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

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

    6

    主题

    565

    帖子

    1874

    积分

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

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

    2

    主题

    154

    帖子

    1736

    积分

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

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

    6

    主题

    565

    帖子

    1874

    积分

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

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

    0

    主题

    42

    帖子

    330

    积分

    Rank: 4

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

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

    0

    主题

    2150

    帖子

    3881

    积分

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

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

    活力之星

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

    0

    主题

    329

    帖子

    1186

    积分

    Rank: 6Rank: 6Rank: 6

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

    0

    主题

    15

    帖子

    90

    积分

    Rank: 2Rank: 2

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

    21

    主题

    225

    帖子

    1405

    积分

    Rank: 6Rank: 6Rank: 6

    UID
    44764
    好友
    0
    蛮牛币
    724
    威望
    0
    注册时间
    2014-9-13
    在线时间
    481 小时
    最后登录
    2019-10-10
    11#
    2019-5-10 10:02:45 只看该作者
    6666666666666666666666666666
    2初来乍到
    101/150
    排名
    31434
    昨日变化

    0

    主题

    54

    帖子

    101

    积分

    Rank: 2Rank: 2

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

    0

    主题

    92

    帖子

    818

    积分

    Rank: 5Rank: 5

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

    0

    主题

    92

    帖子

    818

    积分

    Rank: 5Rank: 5

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

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

    0

    主题

    81

    帖子

    223

    积分

    Rank: 3Rank: 3Rank: 3

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

    本版积分规则

  • 回复@大雨582:社会人不可能像自然人一样自由,你还得尊重别人的意愿!不然咱随便生产啥都强行让你要,咱是自由了,你呢? 2019-10-12
  • 发改委每月首个工作日公布限制乘坐火车飞机人员名单 2019-10-12
  • 全国啦啦操联赛临汾站开幕 2019-10-08
  • 《爱疯音乐家》陈洁仪:不完美的美其实更美爱疯音乐家陈洁仪 2019-10-08
  • 中冶置业兴隆百万平米新城正式亮相 将打造全配套高铁康养小镇 2019-10-06
  • 以政府拟严打“乱拍摄”以军行为 最高10年监禁 2019-10-03
  • 图解:关于中国梦,习近平总书记这十句话直抵人心 2019-09-20
  • “舌尖”之后, “风味”能否再续辉煌? 2019-09-17
  • 腾讯要花32亿收购《绝地求生》开发商10%股份 2019-09-17
  • 涨知识!文字里的秘密 最全甲骨文书展来了 2019-09-13
  • 晋中市着力将“厕所革命”进行到底 2019-09-05
  • 供应链如何更“智慧” 2019-09-05
  • 红枣食疗效果好 6种吃法最滋补-美食资讯 2019-09-01
  • 党的十九大最重大的理论成就 2019-08-28
  • 余世存:阅读经典不仅是消费,也是责任 2019-08-20
  • 365捕鱼游戏中心官网下载 快乐扑克3走势 云南11选5推荐今天的 2013年彩票销售额排名 半全场的赌球赔率网站 斯诺克比赛 幸运28大神预测 3d包胆8开980算中奖吗 体新福建22选5走势图 刘伯温四肖中特料一一 分分彩极速赛车平台 2019码报生肖卡 陕西11选五开奖结果 天津快10专家下载 梭哈发牌教学