유니티3D 안드로이드 플랫폼 XML WRITE LOAD 질문입니다.


string filename = "Quests";

Type[] questType = { typeof(QUEST) };

FileStream fs = new FileStream(Path.Combine(Application.persistentDataPath,filename+".txt"), FileMode.Create);

StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);

XmlSerializer serializer = new XmlSerializer(typeof(QuestContainer), questType);

serializer.Serialize(sw, questContainer);

sw.Close();

위는 지정된 파일에 WRITE하기 위한 방법입니다.

string filename = "Quests";

Type[] questType = { typeof(QUEST) };

XmlSerializer serializer = new XmlSerializer(typeof(QuestContainer), questType);

TextReader fs = new StreamReader(Application.persistentDataPath + filename + ".txt");

QuestContainer = (QuestContainer)serializer.Deserialize(fs);

fs.Close();

위는 지정된 파일을 LOAD하기 위한 방법입니다.

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

public class QuestContainer
{
    private List<QUEST> confirmed = new List<QUEST>();
    private List<QUEST> complete = new List<QUEST>();
    private List<QUEST> possible = new List<QUEST>();
    private List<QUEST> im_possible = new List<QUEST>();

    public List<QUEST> Confirmed
    {
        get { return confirmed; }
        set { confirmed = value; }
    }

    public List<QUEST> Complete
    {
        get { return complete; }
        set { complete = value; }
    }

    public List<QUEST> Possible
    {
        get { return possible; }
        set { possible = value; }
    }

    public List<QUEST> im_Possible
    {
        get { return im_possible; }
        set { im_possible = value; }
    }
}

위는 QuestContainer 클래스입니다.

public class QUEST
{
    public string Questname { get; set; }
    public string Description { get; set; }
    public string Class { get; set; }
    public int Level { get; set; }
    public int STR { get; set; }
    public int CON { get; set; }
    public int INT { get; set; }
    public int WIS { get; set; }
    public int DEX { get; set; }
    public string Title { get; set; }
    public string Item { get; set; }
    public QUEST_TYPE questType { get; set; }
    public DIFFICULTY difficulty { get; set; }
    public EXPEDIENT eXPEDIENT { get; set; }
    public QUEST_REWARD questReward { get; set; }
    public string target { get; set; }
    public int count { get; set; }
    public bool canClear { get; set; }

    public QUEST()
    {

    }

    public QUEST(string Questname,string Description,string Class,int level,int str,int con, int Int, int wis, int dex,string title,string item,  QUEST_TYPE QuestType, DIFFICULTY Difficulty, QUEST_REWARD quest_reward, EXPEDIENT EXPEDIENT, string Target, int Count, bool canclear)
    {
        this.Description = Description;
        this.Questname = Questname;
        this.questType = QuestType;
        this.difficulty = Difficulty;
        this.eXPEDIENT = EXPEDIENT;
        this.questReward = quest_reward;
        this.Class = Class;
        this.Level = level;
        this.STR = str;
        this.CON = con;
        this.INT = Int;
        this.WIS = wis;
        this.DEX = dex;
        this.Title = title;
        this.Item = item;
        this.target = Target;
        this.count = Count;
        this.canClear = canclear;
    }
 }

위는 Quest클래스입니다.

<?xml version="1.0" encoding="utf-8"?>
<QuestContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Confirmed>
    <QUEST>
      <Questname>시작</Questname>
      <Description>이제 시작이에요!</Description>
      <Class>ALL</Class>
      <Level>0</Level>
      <STR>0</STR>
      <CON>0</CON>
      <INT>0</INT>
      <WIS>0</WIS>
      <DEX>0</DEX>
      <Title />
      <Item />
      <questType>ROOP</questType>
      <difficulty>EASY</difficulty>
      <eXPEDIENT>MOVE</eXPEDIENT>
      <questReward>GOLD</questReward>
      <target>Bank</target>
      <count>10</count>
      <canClear>false</canClear>
    </QUEST>
  </Confirmed>
  <Complete />
  <Possible />
  <im_Possible />
</QuestContainer>

위는 xml파일 입니다. 안드로이드 플랫폼에선 .txt로 변경하여 사용중입니다.

QuestContainer의 리스트에 따라 4가지 프로세스로 나뉘어 xml파일에 저장이됩니다.

read는 이상없이 잘 되나,

게임 중 QuestContainer에 리스트 내용을 바꿔주고 write를 해주는데,

다시 불러올 때 아무 변경이 없는 내용이 불러와지는걸 보니, write에 문제가 있는 것 같은데 이유를 알 수 없네요.

  • 2016년 02월 18일에 작성됨

조회수 560


1 답변


다음과 같이 하니 안드로이드에서 잘 동작하네요. 파일의 내용을 불러와서 값을 바꿔서 쓴 다음 다시 불러와서 출력해 봤습니다.

pathForDocumentsFile에서 경로를 불러오세요. 그리고 파일을 불러올때 실패하게되면 resources의 파일을 불러오는 방식을 이용했습니다.

using UnityEngine;
using System.Collections;
using System.Xml;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.Text;
using System;


public class NewBehaviourScript : MonoBehaviour {
    QuestContainer container;
    void Start () {
        loadXML ();
        Debug.Log ("###before###");
        foreach (QUEST quest in container.Confirmed) {
            Debug.Log (quest.Description);
            quest.Description="!!!"+quest.Description;
        }

        writeXML ();
        loadXML ();
        Debug.Log ("###after###");
        foreach (QUEST quest in container.Confirmed) {
            Debug.Log (quest.Description);
        }


    }

    void loadXML(){
        try{
            TextReader fs = new StreamReader(pathForDocumentsFile("Catalog.txt"));
            var serializer = new XmlSerializer(typeof(QuestContainer));
            container = serializer.Deserialize(fs) as QuestContainer;
            fs.Close();
        }
        catch(Exception e){
            TextAsset textAsset = (TextAsset) Resources.Load("Catalog");  
            var serializer = new XmlSerializer(typeof(QuestContainer));
            StringReader stream = new StringReader (textAsset.ToString ());
            container = serializer.Deserialize(stream) as QuestContainer;
            stream.Close();
        }
    }

    void writeXML(){
        var serializer = new XmlSerializer (typeof(QuestContainer));
        var stream = new FileStream(pathForDocumentsFile("Catalog.txt"), FileMode.Create);
        StreamWriter sw = new StreamWriter (stream, Encoding.UTF8);
        serializer.Serialize(sw, container);
        stream.Close();
    }

    public string pathForDocumentsFile( string filename ) 
    {
        if (Application.platform == RuntimePlatform.IPhonePlayer)
        {
            string path = Application.dataPath.Substring( 0, Application.dataPath.Length - 5 );
            path = path.Substring( 0, path.LastIndexOf( '/' ) );
            return Path.Combine( Path.Combine( path, "Documents" ), filename );
        }
        else if(Application.platform == RuntimePlatform.Android)
        {
            string path = Application.persistentDataPath; 
            path = path.Substring(0, path.LastIndexOf( '/' ) ); 
            return Path.Combine (path, filename);
        } 
        else 
        {
            string path = Application.dataPath; 
            path = path.Substring(0, path.LastIndexOf( '/' ) );
            return Path.Combine (path, filename);
        }
    }
}

그리고 serializer를 이용하기 위해서는 각 클래스에 다음과 같은 annotation을 붙여주어야 합니다.

using System.Xml.Serialization;
using System.Collections.Generic;

[XmlRoot("QuestContainer")]
public class QuestContainer{
    [XmlArray("Confirmed")]
    [XmlArrayItem("QUEST")]
    public List<QUEST> Confirmed = new List<QUEST> ();
}


public class QUEST{
    public string Questname;
    public string Description;
    public int Level;
}
  • 2016년 02월 18일에 작성됨
    루비와 파이썬을 좋아합니다. 새로운 언어를 배우는것도 좋아해요. 모바일 게임도 조금 만들어 봤습니다.

  • 정말 토나오네요. 프로그램 로직짜는것보다 파일 하나 입출력하는게 더 힘드니 무슨 .. 화딱지나서 죽겠네요. annotation을 붙일 때 리스트 별로 하나씩 붙이는 겁니까? 답변 감사합니다. 지금은 너무 고통스러워서 있다가 실행 확인하겠습니다..    정우진   2016.2.18 18:09     
  • 네. 리스트별로 다 따로 붙입니다.    정두식   2016.2.18 18:43     
  • 아 정말 감사합니다.. ㅡㅡ write가 안되는게 annotation을 안 붙여준 것 때문이었나요? application.persistent로 접근한 것은 같은데.. 왜 안되는지 이유를 알 수 없었는데 아 쾌감 때문에 미치겠네요.    정우진   2016.2.18 20:02     
  • Json를 사용하시면 훨씬 편하게 할 수 있을거 같습니다. https://github.com/SaladLab/Json.Net.Unity3D 이놈 한번 써보세용.    SangMin Choi   2016.3.15 23:22     

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close