상세 컨텐츠

본문 제목

[Unity] 유니티 XML 데이터 읽기, 파싱, 파서 관련

게임엔진관련/유니티 엔진

by AlrepondTech 2019. 3. 21. 16:45

본문

반응형

 

 

=================================

=================================

=================================

 

 

출처: https://silisian.tistory.com/7

 

 

this post shows asimple tutorial to do some basic operations with xml file on Unity3D using C#.

How to load?

Put an XML file on Resources folder and load itwith Resources class from Unity3D
xml sample:

 

 

<achievement>

 

 

 <uniqueid>0</uniqueid>

 

 

 <referencename>MyAchievement</referencename>

 

 

 <goal>Solve until 10seconds</goal>

 

 

 <points>10</points>

 

 

</achievement>

 

 

 

using UnityEngine;

 

 

using System.Collections;

 

 

using System.Xml;

 

 

 

 

public class XMLEditor : MonoBehaviour

 

 

{

 

 

 

   void Awake()

 

 

    {

 

 

       //Load

 

 

       TextAsset textXML = (TextAsset)Resources.Load("myxml.xml",typeof(TextAsset));

 

 

       XmlDocument xml = new XmlDocument();

 

 

       xml.LoadXml(textXML.text);

 

 

    }

 

 

}

 

 

Yeah! Using a TextAsset you can make it very simply!

How to read?

Pretty simple! Use .NET framework, XmlDocumentwill turn you live more easy.

 

 

using UnityEngine;

 

 

using System.Collections;

 

 

using System.Xml;

 

 

 

 

public class XMLEditor : MonoBehaviour

 

 

{

 

 

   void Awake()

 

 

    {

 

 

       //Load

 

 

       TextAsset textXML = (TextAsset)Resources.Load("myxml.xml",typeof(TextAsset));

 

 

       XmlDocument xml = new XmlDocument();

 

 

       xml.LoadXml(textXML.text);

 

 

 

       //Read

 

 

       XmlNode root = xml.FirstChild;

 

 

       foreach(XmlNode node in root.ChildNodes)

 

 

       {

 

 

           if (node.FirstChild.NodeType == XmlNodeType.Text)

 

 

                Debug.Log(node.InnerText);

 

 

       }

 

 

    }

 

 

}

 

 


Ok, but if there are multiplehierarchies you will must implement your own ReadMethod to do that bynavigating for all nodes.

How to save?

 

 

using UnityEngine;

 

 

using System.Collections;

 

 

using System.Xml;

 

 

 

 

public class XMLEditor : MonoBehaviour

 

 

{

 

 

   void Awake()

 

 

    {

 

 

       //Load

 

 

       TextAsset textXML = (TextAsset)Resources.Load("myxml.xml",typeof(TextAsset));

 

 

       XmlDocument xml = new XmlDocument();

 

 

       xml.LoadXml(textXML.text);

 

 

 

       //Read

 

 

       XmlNode root = xml.FirstChild;

 

 

        foreach(XmlNode node in root.ChildNodes)

 

 

       {

 

 

           if (node.FirstChild.NodeType == XmlNodeType.Text)

 

 

                node.InnerText ="none";

 

 

       }

 

 

 

       //Simple Save

 

 

       xml.Save(AssetDatabase.GetAssetPath(textXML));

 

 

    }

 

 

}

 

 

The easy way! :)

 

 

 

 

출처 : http://fernandogamedev-en.blogspot.kr/2012/09/how-to-load-read-and-save-xml-on-unity3d.html



출처: https://silisian.tistory.com/7 [:: 게임개발자 놀이터 , 시리시안]

 

 

 

=================================

=================================

=================================

 

 

출처: https://happyryu.tistory.com/364

 

 

유니티에서 xml 파일 불러오는 방법

 

방법만 간단하게 작성하겠습니다.

각자 만든 xml 데이터 클래스 타입이 있다고 치고, 그걸 사용하서 Serializer를 사용해서 불러오는 방법입니다. 

 

  string filePath = string.Empty;

 

        XmlSerializer serializer = new XmlSerializer(typeof(LanguageManager));

        TextAsset tAsset = Resources.Load("MultiLanguage") as TextAsset;

        using (var stream = new StringReader(tAsset.text))

        {

            return serializer.Deserialize(stream) as LanguageManager;

        }

 

 

저는 Xml 파일을 "MultiLanguage.xml" 이라고 지었으며 파일 위치는 Resources/ 아래에 저장해 뒀습니다.

 

 

 

이렇게 해서 불러오니까 Android 와 윈도우 환경에서는 잘 불러오네요. IOS 환경에서는 테스트 못해봤습니다.

아래는 제가 해서 잘 안되었던 경우입니다. 괜히 저처럼 삽질 하셨다면 그냥 위에 코드 사용하시면 될것같습니다. 

 

        string filePath = string.Empty;

 

#if UNITY_EDITOR

        filePath = Path.Combine(Application.dataPath, "Resources/MultiLanguage.xml");

#elif UNITY_ANDROID

        //string androidPath = "jar:file://" + Application.dataPath + "!/assets";

        filePath = Path.Combine(Application.streamingAssetsPath, "Resources/MultiLanguage.xml");

#endif

 

        if (File.Exists(filePath))

        {

            Application.Quit();

            XmlSerializer serializer = new XmlSerializer(typeof(LanguageManager));

            using (FileStream stream = new FileStream(filePath, FileMode.Open))

            {

                return serializer.Deserialize(stream) as LanguageManager;

            }

        }

 

 

=================================

=================================

=================================

 

 

출처: https://devoduck.tistory.com/entry/c%EC%9C%BC%EB%A1%9C-XML%EC%9D%84-%ED%8C%8C%EC%8B%B1%ED%95%B4%EB%B3%B4%EC%9E%90

 

 

보통의 작업에서 XML을 잘 안쓰는 편이지만

편의에 따라서 XML을 사용할일이 있을경우 다음과 같이 사용하기도 한다 

Assets/Resources/XML 

경로를 만들어 두고 

그 안에 파일을 원하는 XML파일을 넣어둔다 

 

List<Dictionary<string,string>> mContainer =  new List<Dictionary<string,string>>();

TextAsset textXml = Resources.Load("경로"typeof(TextAsset)) as TextAsset;

if(textXml != null)
{
    // 플랫폼이 안드로이드 인경우에 파싱이  안되는 경우아가 있는데 그때는 아래와 
    // 같은 방식으로 함수를 호출하면 된다 
    //XmlData.LoadXml(wwwUrl.text.Trim());
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(textXml.ToString());
    XmlNode root = 

xmlDoc

.DocumentElement;
    if(root.HasChildNodes)
    {
        XmlNodeList child = root.ChildNodes;
        for(int i=0  ; i < child.Count ; i++)
        {
            XmlNode temp = child[i];
            XmlNodeList itemList = temp.ChildNodes;
            //itemList[0].InnerXml;
            //  7  
           Dictionary<string , stringtempDic = new Dictionary<string ,string >();
           tempDic.Add("ID",itemList[0].InnerXml);
           tempDic.Add("NAME",itemList[1].InnerXml);
           tempDic.Add("PRICE",itemList[2].InnerXml);
           mContainer.Add(tempDic);
            }
        }
}
불러와서 데이터를 관리하는 방법이야 프로젝트마다 개발자 마다 달라지겠지만

퍼포먼스에 문제가 되지 않으면 가장 손에 익는 방법으로 로딩해와 작성하도록 한다. 



출처: https://devoduck.tistory.com/entry/c으로-XML을-파싱해보자 [빠이팅은 항상 넘치게!!]

 

 

=================================

=================================

=================================

 

 

출처: https://hyunity3d.tistory.com/511

 

 

 

 

 
 
 

 

 

 

xml로 된 데이터 파일은 모두 string 형이므로 적절히 형변환을 해줘서 사용해야됨.

좋아요 공감



출처: https://hyunity3d.tistory.com/511 [Unity3D]

 

 

=================================

=================================

=================================

 

 

반응형

 

 

728x90

 

 

 

 

 

출처: https://wergia.tistory.com/53

 

 

유니티에서 XML 사용하기

 

게임을 제작할 때에, 여러 가지 데이터들을 저장하고 불러와야하는 경우가 많다. 게임 진행 상황을 저장하는 경우도 있을 수 있고, 맵이 랜덤으로 생성되는 게임의 경우에는 현재 생성된 맵의 데이터를 저장해뒀다가 다음에 다시 불러와야 할 수도 있다. 또는 게임의 아이템 정보들의 목록을 저장해둬야 할 수도 있다. 위와 같은 경우에 XML을 사용하면 저런 기능들을 쉽게 구현할 수 있게 된다.

 

XML은 마크업 언어를 정의하기 위한 확장성 마크업 언어라고 하는데, 여기서는 조작하기 쉬운 일종의 로컬 데이터베이스나 데이터를 저장하기 위한 파일로 사용될 것이다.

 

이번 섹션의 예시에서는 게임의 캐릭터 정보를 저장하기 위해서 XML을 사용한다고 가정하고 진행 해보겠다.

 

1. XML 파일 생성하여 저장하기

첫 번째로 알아볼 것은 XML 파일을 생성하는 것이다. 만약 게임을 시작하고 처음으로 저장을 하는 경우라면 아직 데이터를 저장하기 위한 파일이 생성되어 있지 않을 것이다. 물론 미리 XML 파일을 만들어두고 사용하는 것도 가능하지만, XML 파일을 생성하는 법에 대해서 알아두는 것도 나쁘지 않다.

 

다음이 XML을 생성하여 저장하는 코드의 전체이다 : 

 

public class XmlTest : MonoBehaviour
{
    void Start()
    {
        CreateXml();
    }

    void CreateXml()
    {
        XmlDocument xmlDoc = new XmlDocument();

        // Xml을 선언한다(xml의 버전과 인코딩 방식을 정해준다.)
        xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "yes"));

        // 루트 노드 생성
        XmlNode root = xmlDoc.CreateNode(XmlNodeType.Element, "CharacterInfo", string.Empty);
        xmlDoc.AppendChild(root);

        // 자식 노드 생성
        XmlNode child = xmlDoc.CreateNode(XmlNodeType.Element, "Character", string.Empty);
        root.AppendChild(child);

        // 자식 노드에 들어갈 속성 생성
        XmlElement name = xmlDoc.CreateElement("Name");
        name.InnerText = "wergia";
        child.AppendChild(name);

        XmlElement lv = xmlDoc.CreateElement("Level");
        lv.InnerText = "1";
        child.AppendChild(lv);

        XmlElement exp = xmlDoc.CreateElement("Experience");
        exp.InnerText = "45";
        child.AppendChild(exp);

        xmlDoc.Save("./Assets/Resources/Character.xml");
    }
}

 

저장할 캐릭터 데이터의 내용은 캐릭터의 이름과 레벨, 경험치라고 가정하고 진행했다. 위의 코드를 실행하면 지정된 경로에 Character.xml 파일이 생성된다.

 

 

 

생성된 xml 파일은 다음과 같은 내용이다 :

 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<CharacterInfo>
  <Character>
    <Name>wergia</Name>
    <Level>1</Level>
    <Experience>45</Experience>
  </Character>
</CharacterInfo>

 

작성한 대로 캐릭터의 이름, 레벨, 경험치 값이 저장되었다.

 

2. XML 파일에서 데이터 불러와서 사용하기

데이터를 저장하는데 성공했다면 이 다음에는 저장된 데이터를 불러와서 사용해야할 것이다. 다음의 코드가 저장된 XML 데이터를 불러오는 것이다.

 

using System.Xml;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class XmlTest : MonoBehaviour
{
    void Start()
    {
        LoadXml();
    }

    void LoadXml()
    {
        TextAsset textAsset = (TextAsset)Resources.Load("Character");
        Debug.Log(textAsset);
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(textAsset.text);

        XmlNodeList nodes = xmlDoc.SelectNodes("CharacterInfo/Character");

        foreach (XmlNode node in nodes)
        {
            Debug.Log("Name :: " + node.SelectSingleNode("Name").InnerText);
            Debug.Log("Level :: " + node.SelectSingleNode("Level").InnerText);
            Debug.Log("Exp :: " + node.SelectSingleNode("Experience").InnerText);
        }
    }

}

 

위의 코드를 실행해보면 XML에 저장해둔 캐릭터 데이터가 잘 불러와졌음을 알 수 있다.

 

 

 

불러온 데이터를 캐릭터 오브젝트를 생성해서 그 값을 다시 넣어준다면 캐릭터는 저장되기 직전의 캐릭터와 같은 상태를 가지게 될 것이다.

 

3. 이미 존재하는 XML 파일에 데이터 덮어씌워 저장하기

게임에서 이미 저장하기 기능을 사용해서 XML 파일이 생성되어 있고, 그 XML파일에 덮어 씌워 저장하는 경우도 있을 수 있다. 그럴 땐 다음 코드와 같이 이미 존재하는 XML 파일을 불러온 후에 그 안의 값을 수정하고 저장해주면 된다 :

 

using System.Xml;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class XmlTest : MonoBehaviour
{
    void Start()
    {
        SaveOverlapXml();
    }

    void SaveOverlapXml()
    {
        TextAsset textAsset = (TextAsset)Resources.Load("Character");
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(textAsset.text);

        XmlNodeList nodes = xmlDoc.SelectNodes("CharacterInfo/Character");
        XmlNode character = nodes[0];

        character.SelectSingleNode("Name").InnerText = "wergia";
        character.SelectSingleNode("Level").InnerText = "5";
        character.SelectSingleNode("Experience").InnerText = "180";

        xmlDoc.Save("./Assets/Resources/Character.xml");
    }

}

 

위 코드를 실행해보면 다음과 같이 XML 파일이 변경되어 있는 것을 볼 수 있다 : 

 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<CharacterInfo>
  <Character>
    <Name>wergia</Name>
    <Level>5</Level>
    <Experience>180</Experience>
  </Character>
</CharacterInfo>

 

위의 예시처럼 덮어씌워 저장하는 방법 이외에도 새로 노드를 덧붙여서 추가적인 내용을 저장한다던가, 아니면 여러 개의 저장 슬롯을 만들어서 저장하는 방법을 사용할 수 있다.

 

 

4. 취약점

저장 방식으로 사용하기 굉장히 편리한 XML이지만 이것도 굉장한 단점이 하나 있다. 이 XML을 그대로 사용하면 그냥 텍스트 편집기로도 열리기 때문에 사용자들이 쉽게 그 값을 변조할 수 있게 된다. 이것은 하나의 에디터나 다름없는 것이기 때문에 만약 제작하는 게임이 데이터가 변조되면 안되는 경우에는 심각한 문제가 될 수 있다. 만약 XML에 게임 데이터를 저장하고 불러와야 되는 경우에는 별도의 암호화/복호화 기능을 덧붙여서 기능을 만드는 것을 추천한다.



출처: https://wergia.tistory.com/53 [베르의 프로그래밍 노트]

 

 

=================================

=================================

=================================

 

 

 

출처: http://www.devkorea.co.kr/bbs/board.php?bo_table=m03_qna&wr_id=10631

 

현재 xml파일을 Resources/ 파일에 넣고 xml파일을 로드해서 
데이터를 읽으려고 합니다. 
헌데 Resources.Load("xml파일이름"); 하면 에러가나고 
Application.dataPath +"/Resources/xml파일이름" ;  하면 정상 작동하는데 

pc에서는 path를 지정해서 정상작동 한다해도 
ios빌드시에는 에셋을 묶어버리던데 그때 저런 특정 path를 지정한다면 
가능한지 의문입니다. 가능하다면 path를 어떻게 지정해야하는지도 
궁금하네요 ㅠㅠ 이런 문제를 미리 격으셧다면 .. 노하우좀 부탁드리겟습니다~ 
굽신굽신.. 

 

 

-----------------------------------------------------------------------------------------------------------------------------

 

리소스 폴더 내에 있는 것들을  Resources.Load("xml파일이름"); 으로 로드하시면 문제 없을 것이고, 
Application.dataPath +"/Resources/xml파일이름"; 으로 경로지정을 하셨으면 빌드 후 실행파일이 있는 폴더에 파일을 넣어줘야할 것입니다. 
라고 예상합니다. iOS는 경험해보지 못했네요.

 

-----------------------------------------------------------------------------------------------------------------------------

아뇨  Resources.Load("xml파일이름"); 을 사용하면 Deserialize하는 과정에서 
예외 에러를 뱉더라고요 .. 

똑같이 Resources 폴더에 들어잇는 xml파일을 
Application.dataPath +"/Resources/xml파일이름"; 이경로로 읽어들이면 정상적으로 작동합니다

 

-----------------------------------------------------------------------------------------------------------------------------

이상하네요.. 
전 ios , pc 모두 
Resources.Load( "xml파일이름" ); 으로 정상작동 하는데요;;

 

 

--------------------------------------------------------------------------------------------------------------------------------

 

TextAsset spriteText = Resources.Load( "XML/" + fileName ) as TextAsset; 

byte[] arrByte = Encoding.ASCII.GetBytes( spriteText ); 
MemoryStream stream = new MemoryStream( arrByte ); 

XmlReader xmlReader = XmlReader.Create( stream ); 

_Parse( xmlReader ); 

xmlReader.Close(); 


private void _Parse( XmlReader reader ) 

      while( reader.Read() ) 
      { 
                    switch( reader.NodeType ) 
                      { 
                                    case XmlNodeType.Element: 
                                          //      
                                    break; 
                                    case XmlNodeType.Text: 
                                          // 
                                    break; 
                                    case XmlNodeType.EndElement: 
                                          // 
                                    break; 
                      } 
            } 
}

 

--------------------------------------------------------------------------------------------------------------------------------

 

이렇게 해서 정상작동하는걸 보면 Resources.Load 로 정상적으로 xml 파일이 읽혔다는건데요.. 
다른부분에 문제가 있는건 아닌지 한번 살펴보시는것도 괜찮아보입니다;;

 

--------------------------------------------------------------------------------------------------------------------------------

 
자답구햇어용~ 무슨 이유에서인지  돌봉님은 제 코드가 잇으셔서 아시겟지만 LoadXmlFromResource 함수에서 Textasset.text 로 리턴받으면 xml파일을 스트링으로 읽엇을때 맨앞에 널값이 들어가더라고요 
그걸 강제로 뺏는데 혹시 이 이유도 알고계신가요? 마이 찝찝하네요 ㅠㅠ
 

--------------------------------------------------------------------------------------------------------------------------------

TextAsset txtAsset = Resources.Load( "txt파일이름" ) as TextAsset; 

StringReader stringReader = new Stringreader( txtAsset.text ); 

string line; 
while( (line = stringReader.ReadLine()) != null ) 

      string fileName = line; 
      FileStream fileStream = File.Open( fileName, FileMode.OpenOrCreate ); 
      
        // TODO something 


      fileStream.Close(); 
 }

 

 

 

=================================

=================================

=================================

 

 

출처: https://forum.unity.com/threads/basic-xml-access-via-c.159495/

 

 

First off, I'm aware that there are some other threads right now on a similar topic, but they seem to be a bit more than I need and honestly I just can't wrap my head around them.
I'd appreciate it if anyone could provide an "explain like I'm 5" explanation of some simple XML access via C#.

Say I've got the following XML:

Code (csharp):
  1. <records>
  2.     <patient name="john" age="25" status="fine" />
  3.     <patient>
  4.         <name>jane</name>
  5.         <age>30</age>
  6.         <status>not fine</status>
  7.     </patient>
  8. </records>

Now, I've got 2 sets of similar data here. This is because I'm not sure which is the best, or "proper" way to organize it. But, the goal is the same.
In C#, I'd like to be able to simply pull that data and assign it to a variable in Unity. For example, putting the "age" property into an int or the "status" into a string.

I've been reading some of the threads here and its just not "clicking" for me. I'd be grateful if someone could give me a very basic explanation on this.

Edit: I should add that I'd like to access the XML locally, rather than via a web page.

Thanks.

 

---------------------------------------------------------------------------------------------------------------------------------------------------

 

Code (csharp):
  1.  
  2. XmlDocument mydoc = new XmlDocument();
  3. mydoc.Load("file.xml");
  4. XmlNodeList nodelist = mydoc.SelectNodes("records/patient");
  5.  
  6. if (nodelist.Count > 0)
  7. {
  8.     for (int i = 0; i < nodelist.Count; i++)
  9.     {
  10.         XmlNode node = nodelist[i];
  11.         XmlAttributeCollection collection= node.Attributes; // here attreibutes  like age, name, status
  12.     }
  13. }
  14.  
 
 

--------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Noooo - Serialization is your friend. Honest! :)

Code (csharp):
  1.  
  2. using System.Xml.Serialization;
  3.  
  4. [XmlRoot(ElementName = "records")]
  5. public class Records
  6. {
  7.     [XmlElement(ElementName = "patient")]
  8.     public Patient[] Patients { get; set; }
  9. }
  10.  
  11. // this assumes the 2nd example where properties
  12. // are child nodes and not attributes
  13. public class Patient
  14. {
  15.     [XmlElement(ElementName = "name")]
  16.     public string Name { get; set; }
  17.    
  18.     [XmlElement(ElementName = "age")]
  19.     public int Age { get; set; }
  20.  
  21.     [XmlElement(ElementName = "status")]
  22.     public string Status { get; set; }
  23. }
  24.  
Then to load all your data into a Records object-
Code (csharp):
  1.  
  2. Records records;
  3. using (FileStream file = new FileSteam("data.xml", FileMode.Open))
  4. {
  5.     XmlSerializer serial = new XmlSerializer(typeof(Records));
  6.     records = (Records)serial.Deserialize(file);
  7. }
  8.  
This discards all the XML related junk after it's loaded and serialized and leaves you with a nice object that you can query and manipulate as much as you like. Also makes saving the data back to a file easier (XmlSerializer comes with a Serialize method that goes the other way).

Code (csharp):
  1.  
  2. using System.Linq;
  3.  
  4. // get the first record of a guy named 'john'
  5. var john = records.Patients.First(=> p.Name == "john");
  6.  
  7. // get all patients that are 25 or older
  8. var oldGuys = records.Patients.Select(=> p.Age >= 25);
  9.  
Double edit - I see you're in Philadelphia - me too! (close anyway)
 

 

 

=================================

=================================

=================================

 

 

 

*기타관련링크

 

https://ssscool.tistory.com/341

 

 

 

=================================

=================================

=================================

 

반응형


관련글 더보기

댓글 영역