在类之间复制具有相同名称的值

时间:2019-04-13 10:52:43

标签: c# unity3d reflection

我试图获取对话JSON的内容,并将其属性(存储到Dialogues类中)复制到另一个源自MonoBehaviour(DialogueManager)的类中。 无论如何,即使GetProperty返回正确的属性名称,GetValue方法也将返回null。 我不能只将Json读到DialogueManager,因为JSONUtility显然需要导出到非MonoBehaviour类。

using System.IO;
using UnityEngine;

public class DialogueManager : MonoBehaviour
{
    //999 IS RETURN TO MENU
    //1000 IS CLOSE GAME
    public static DialogueManager instance = null;
    Dialogues dial;
    public string text1 { get; set; }
    public string choices1 { get; set; }
    public string consequences1 { get; set; }
    public string text2 { get; set; }
    public string choices2 { get; set; }
    public string consequences2 { get; set; }
    public string text3 { get; set; }
    public string choices3 { get; set; }
    public string consequences3 { get; set; }
    public string text4 { get; set; }
    public string choices4 { get; set; }
    public string consequences4 { get; set; }
    public string text5 { get; set; }
    public string choices5 { get; set; }
    public string consequences5 { get; set; }
    public string text6 { get; set; }
    public string choices6 { get; set; }
    public string consequences6 { get; set; }
    public string text7 { get; set; }
    public string choices7 { get; set; }
    public string consequences7 { get; set; }
    public string text8 { get; set; }
    public string choices8 { get; set; }
    public string consequences8 { get; set; }
    public string text9 { get; set; }
    public string choices9 { get; set; }
    public string consequences9 { get; set; }
    public string text10 { get; set; }
    public string choices10 { get; set; }
    public string consequences10 { get; set; }
    public string text11 { get; set; }
    public string choices11 { get; set; }
    public string consequences11 { get; set; }
    public string text12 { get; set; }
    public string choices12 { get; set; }
    public string consequences12 { get; set; }
    public string text13 { get; set; }
    public string choices13 { get; set; }
    public string consequences13 { get; set; }
    public string text14 { get; set; }
    public string choices14 { get; set; }
    public string consequences14 { get; set; }
    public string text15 { get; set; }
    public string choices15 { get; set; }
    public string consequences15 { get; set; }
    public string text16 { get; set; }
    public string choices16 { get; set; }
    public string consequences16 { get; set; }
    public string text17 { get; set; }
    public string choices17 { get; set; }
    public string consequences17 { get; set; }
    public string text18 { get; set; }
    public string choices18 { get; set; }
    public string consequences18 { get; set; }
    public string text19 { get; set; }
    public string choices19 { get; set; }
    public string consequences19 { get; set; }
    public string text20 { get; set; }
    public string choices20 { get; set; }
    public string consequences20 { get; set; }
    public string text21 { get; set; }
    public string choices21 { get; set; }
    public string consequences21 { get; set; }
    public string text22 { get; set; }
    public string choices22 { get; set; }
    public string consequences22 { get; set; }
    public string text23 { get; set; }
    public string choices23 { get; set; }
    public string consequences23 { get; set; }
    string fixedName;

    string[] splits;
    string text;
    int[] consequences;
    private void Awake()
    {
        if(instance == null)
        {
            instance = this;
        }
        else
        {
            enabled = false;
        }
        dial = new Dialogues();
        StreamReader sR = new StreamReader(Application.dataPath + "/GameData/dialogues.json");
        string json = sR.ReadToEnd();
        dial = JsonUtility.FromJson<Dialogues>(json);
        Assign();
    }

    //This doesn't work for some reason
    public void Assign()
    {
        foreach(var property in typeof(Dialogues).GetProperties())
        {
            typeof(DialogueManager).GetProperty(property.Name).SetValue(this, property.GetValue(dial));
        }
    }
    public string GetText(int currentText)
    {
        fixedName = "text" + currentText;
        string output = typeof(DialogueManager).GetProperty(fixedName).GetValue(this, null).ToString();
        return output;
    }
    public string GetTextChoices(int textNum)
    {
        fixedName = "choices" + textNum;
        string output = typeof(DialogueManager).GetProperty(fixedName).GetValue(this, null).ToString();
        return output;
    }
    public int[] GetChoicesConsequences(int textNum)
    {
        fixedName = "consequences" + textNum;
        string output = typeof(DialogueManager).GetProperty(fixedName).GetValue(this, null).ToString();
        splits = output.Split('§');
        consequences = new int[splits.Length];
        for (int i = 0; i < splits.Length; i++)
        {
            consequences[i] = int.Parse(splits[i]);
        }
        return consequences;
    }
    private void DumbAssign()
    {
        text1 = dial.text1;
        choices1 = dial.choices1;
        consequences1 = dial.consequences1;
        text2 = dial.text2;
        choices2 = dial.choices2;
        consequences2 = dial.consequences2;
        text3 = dial.text3;
        choices3 = dial.choices3;
        consequences3 = dial.consequences3;
        text4 = dial.text4;
        choices4 = dial.choices4;
        consequences4 = dial.consequences4;
        text5 = dial.text5;
        choices5 = dial.choices5;
        consequences5 = dial.consequences5;
        text6 = dial.text6;
        choices6 = dial.choices6;
        consequences6 = dial.consequences6;
        text7 = dial.text7;
        choices7 = dial.choices7;
        consequences7 = dial.consequences7;
        text8 = dial.text8;
        choices8 = dial.choices8;
        consequences8 = dial.consequences8;
        text9 = dial.text9;
        choices9 = dial.choices9;
        consequences9 = dial.consequences9;
        text10 = dial.text10;
        choices10 = dial.choices10;
        consequences10 = dial.consequences10;
        text11 = dial.text11;
        choices11 = dial.choices11;
        consequences11 = dial.consequences11;
        text12 = dial.text12;
        choices12 = dial.choices12;
        consequences12 = dial.consequences12;
        text13 = dial.text13;
        choices13 = dial.choices13;
        consequences13 = dial.consequences13;
        text14 = dial.text14;
        choices14 = dial.choices14;
        consequences14 = dial.consequences14;
        text15 = dial.text15;
        choices15 = dial.choices15;
        consequences15 = dial.consequences15;
        text16 = dial.text16;
        choices16 = dial.choices16;
        consequences16 = dial.consequences16;
        text17 = dial.text17;
        choices17 = dial.choices17;
        consequences17 = dial.consequences17;
        text18 = dial.text18;
        choices18 = dial.choices18;
        consequences18 = dial.consequences18;
        text19 = dial.text19;
        choices19 = dial.choices19;
        consequences19 = dial.consequences19;
        text20 = dial.text20;
        choices20 = dial.choices20;
        consequences20 = dial.consequences20;
        text21 = dial.text21;
        choices21 = dial.choices21;
        consequences21 = dial.consequences21;
        text22 = dial.text22;
        choices22 = dial.choices22;
        consequences22 = dial.consequences22;
    }
}

[System.Serializable]
public class Dialogues
{
    public string text1 { get; set; }
    public string choices1 { get; set; }
    public string consequences1 { get; set; }
    public string text2 { get; set; }
    public string choices2 { get; set; }
    public string consequences2 { get; set; }
    public string text3 { get; set; }
    public string choices3 { get; set; }
    public string consequences3 { get; set; }
    public string text4 { get; set; }
    public string choices4 { get; set; }
    public string consequences4 { get; set; }
    public string text5 { get; set; }
    public string choices5 { get; set; }
    public string consequences5 { get; set; }
    public string text6 { get; set; }
    public string choices6 { get; set; }
    public string consequences6 { get; set; }
    public string text7 { get; set; }
    public string choices7 { get; set; }
    public string consequences7 { get; set; }
    public string text8 { get; set; }
    public string choices8 { get; set; }
    public string consequences8 { get; set; }
    public string text9 { get; set; }
    public string choices9 { get; set; }
    public string consequences9 { get; set; }
    public string text10 { get; set; }
    public string choices10 { get; set; }
    public string consequences10 { get; set; }
    public string text11 { get; set; }
    public string choices11 { get; set; }
    public string consequences11 { get; set; }
    public string text12 { get; set; }
    public string choices12 { get; set; }
    public string consequences12 { get; set; }
    public string text13 { get; set; }
    public string choices13 { get; set; }
    public string consequences13 { get; set; }
    public string text14 { get; set; }
    public string choices14 { get; set; }
    public string consequences14 { get; set; }
    public string text15 { get; set; }
    public string choices15 { get; set; }
    public string consequences15 { get; set; }
    public string text16 { get; set; }
    public string choices16 { get; set; }
    public string consequences16 { get; set; }
    public string text17 { get; set; }
    public string choices17 { get; set; }
    public string consequences17 { get; set; }
    public string text18 { get; set; }
    public string choices18 { get; set; }
    public string consequences18 { get; set; }
    public string text19 { get; set; }
    public string choices19 { get; set; }
    public string consequences19 { get; set; }
    public string text20 { get; set; }
    public string choices20 { get; set; }
    public string consequences20 { get; set; }
    public string text21 { get; set; }
    public string choices21 { get; set; }
    public string consequences21 { get; set; }
    public string text22 { get; set; }
    public string choices22 { get; set; }
    public string consequences22 { get; set; }
    public string text23 { get; set; }
    public string choices23 { get; set; }
    public string consequences23 { get; set; }
}

编辑1:我现在已经编辑了脚本,仅对属性使用Dialogues类,但是我仍然不知道如何获取属性(我需要这样做,因为会有250多个文本)

using System.IO;
using UnityEngine;

public class DialogueManager : MonoBehaviour
{
    //999 IS RETURN TO MENU
    //1000 IS CLOSE GAME
    public static DialogueManager instance = null;
    string fixedName;
    private Dialogues dial;
    public Dialogues Dial { get { return dial; } }

    string[] splits;
    string text;
    int[] consequences;
    private void Awake()
    {
        if(instance == null)
        {
            instance = this;
        }
        else
        {
            enabled = false;
        }
        dial = new Dialogues();
        StreamReader sR = new StreamReader(Application.dataPath + "/GameData/dialogues.json");
        string json = sR.ReadToEnd();
        dial = JsonUtility.FromJson<Dialogues>(json);
    }
    public string GetText(int currentText)
    {
        fixedName = "text" + currentText;
        string output = instance.Dial.GetType().GetProperty(fixedName).GetValue(dial).ToString();
        return output;
    }
    public string GetTextChoices(int textNum)
    {
        fixedName = "choices" + textNum;
        string output = typeof(DialogueManager).GetProperty(fixedName).GetValue(this, null).ToString();
        return output;
    }
    public int[] GetChoicesConsequences(int textNum)
    {
        fixedName = "consequences" + textNum;
        string output = typeof(DialogueManager).GetProperty(fixedName).GetValue(this, null).ToString();
        splits = output.Split('§');
        consequences = new int[splits.Length];
        for (int i = 0; i < splits.Length; i++)
        {
            consequences[i] = int.Parse(splits[i]);
        }
        return consequences;
    }
}

[System.Serializable]
public class Dialogues
{
    public string text1;
    public string choices1;
    public string consequences1;
    public string text2;
    public string choices2;
    public string consequences2;
    public string text3;
    public string choices3;
    public string consequences3;
    public string text4;
    public string choices4;
    public string consequences4;
    public string text5;
    public string choices5;
    public string consequences5;
    public string text6;
    public string choices6;
    public string consequences6;
    public string text7;
    public string choices7;
    public string consequences7;
    public string text8;
    public string choices8;
    public string consequences8;
    public string text9;
    public string choices9;
    public string consequences9;
    public string text10;
    public string choices10;
    public string consequences10;
    public string text11;
    public string choices11;
    public string consequences11;
    public string text12;
    public string choices12;
    public string consequences12;
    public string text13;
    public string choices13;
    public string consequences13;
    public string text14;
    public string choices14;
    public string consequences14;
    public string text15;
    public string choices15;
    public string consequences15;
    public string text16;
    public string choices16;
    public string consequences16;
    public string text17;
    public string choices17;
    public string consequences17;
    public string text18;
    public string choices18;
    public string consequences18;
    public string text19;
    public string choices19;
    public string consequences19;
    public string text20;
    public string choices20;
    public string consequences20;
    public string text21;
    public string choices21;
    public string consequences21;
    public string text22;
    public string choices22;
    public string consequences22;
    public string text23;
    public string choices23;
    public string consequences23;
}

2 个答案:

答案 0 :(得分:2)

首先不要为Dialogues类使用属性!属性(没有任何后备字段)永远不会(反)序列化。

这就是为什么您从未从null获得GetValue的原因,因为这些属性从未设置。

删除所有{get; set;},并将这些变量设置为简单字段

public string text1;
public string choices1;
....

您应该只在真正需要它们的地方使用属性-通常是只读的accesor属性,或者为了在从外部设置它们之前检查一些值。

这同样适用于DialogueManager中的所有那些属性。


如果您确实想保留属性(在DialogueManager中),则应该直接阅读并写入您在其中拥有的dial参考,例如

public string text1 
{ 
    get { return dial.text1; }
    set { dial.text1 = value; }
}

但是如果您只是简单地做一个

public Dialogues Dial;

或至少为其赋予只读属性

private Dialogues dial;

public Dialogues Dial
{
    get { return dial; }
}

任何其他组件都可以简单地通过该字段intead访问这些值:

dialogueManagerReference.Dial.text1

,您无需复制任何值。

此外,如果使用

public Dialogues Dial;

[SerializeField] private Dialogues Dial;

您还可以直接在Unity Inspector中编辑/调试这些值。


最后,数据结构看起来有些奇怪,用数字重复所有这些名称和类型...我没有您的JSON文件,所以也许这是获取它们的方式,但是您确定其中不涉及列表/数组?我宁愿期望像这样的数据结构

[Serializable]
public class Dialogues
{
    public Dialogue[] DialogueList;
}

[Serializable]
public class Dialogue
{
    public string Text;
    public string[] Choices;
    public string[] Consequences;
}

和相应的JSON看起来像例如

{
    "DialogueList" : [
        {
            "Text" : "some text",
            "Choices" : [
                "Option A" , "Option B", "Option C"
            ],
            "Consequences" : [
                "Good Boy!", "Oh No!", "Well maybe acceptable ..."
            ]
        },

        {
            "Text" : "some other text",
            "Choices" : [
                "Option Left" , "Option Right"
            ],
            "Consequences" : [
                "Yeay :)", "Neyy :("
            ]
        },

        ... and 21 more entries
    ]
}

答案 1 :(得分:0)

最后,我弄清楚了。 在JsonHelper的帮助下,我将代码更改为使用对象数组。

Dialogues.json:

{
  "Items": [
    {
      "id": "1",
      "text": "7:15 A.M. School starts at 8:05",
      "choices": "",
      "consequences": "2"
    },
    {
      "id": "2",
      "text": "What do you want to do?",
      "choices": "1: Sleep for a while; 2: Get up",
      "consequences": "3?5"
    }
  ]
}

DialogueManager.cs:

using System.IO;
using UnityEngine;
using System;
using System.Security.Cryptography;
using System.Text;

public static class JsonHelper
{
    public static T[] FromJson<T>(string json)
    {
        Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
        return wrapper.Items;
    }

    public static string ToJson<T>(T[] array)
    {
        Wrapper<T> wrapper = new Wrapper<T>();
        wrapper.Items = array;
        return JsonUtility.ToJson(wrapper);
    }

    public static string ToJson<T>(T[] array, bool prettyPrint)
    {
        Wrapper<T> wrapper = new Wrapper<T>();
        wrapper.Items = array;
        return JsonUtility.ToJson(wrapper, prettyPrint);
    }

    [Serializable]
    private class Wrapper<T>
    {
        public T[] Items;
    }
}

public class DialogueManager : MonoBehaviour
{
    [Serializable]
    public class Dialogue
    {
        public int id;
        public string text;
        public string choices;
        public string consequences;

        public Dialogue(int id, string text, string choices, string consequences)
        {
            this.id = id;
            this.text = text;
            this.choices = choices;
            this.consequences = consequences;
        }
    }

    Dialogue[] dial;
    public static DialogueManager instance = null;

    string[] splits;
    int[] consequences;
    private void Awake()
    {
        if(instance == null)
        {
            instance = this;
        }
        else
        {
            enabled = false;
        }
        StreamReader sR = new StreamReader(Application.dataPath + "/GameData/dialogues.json");
        //NON CRITTOGRAFIA
        string json = sR.ReadToEnd();
        //CRITTOGRAFIA
        //string crypted = sR.ReadToEnd();
        //string json = Encrypt.DecryptString(crypted, "think");
        dial = JsonHelper.FromJson<Dialogue>(json);
    }
    public string GetText(int currentText)
    {
        return dial[currentText - 1].text;
    }
    public string GetTextChoices(int textNum)
    {
        return dial[textNum - 1].choices;
    }
    public int[] GetChoicesConsequences(int textNum)
    {
        string output = dial[textNum - 1].consequences;
        splits = output.Split('?');
        consequences = new int[splits.Length];
        for (int i = 0; i < splits.Length; i++)
        {
            consequences[i] = int.Parse(splits[i]);
        }
        return consequences;
    }
}