万年素人からHackerへの道

万年素人がHackerになれるまで殴り書きするぜ。

YamlDotNetをUnityで使う。

.dllファイルがないので、例の3つのフォルダ「YamlDotNet.Core」「YamlDotNet.RepresentationModel」「YamlDotNet.Converters」ごとUnityのPluginsに取り込むという大技をした。
しかし、以下のエラーが発生する

Scripts named 'AssemblyInfo.cs' exist in multiple locations (Assets/Plugins/YamlDotNet/YamlDotNet.Core/Properties/AssemblyInfo.cs). Please rename one of the scripts to a unique name.

上の例ではAssemblyInfo.csにしてたが、これらのファイルで発生する。

AssemblyInfo.cs
AnchorAlias.cs
DocumentStart.cs
DocumentEnd.cs
Scalar.cs
StreamStart.cs
StreamEnd.cs
EmitterState.cs

これらを、消してみたらやはり存在しないエラーとなった・・・。



↑ここまでは失敗談。

よく分からないので、「Xamarin Studio」でソースをコンパイルしてみた。
参考URL: http://docs.unity3d.com/Documentation/Manual/UsingDLL.html
上記のURLを参考に、
1. Open the menu File > New > Solution

2. Choose C# > Library

の手順で、
YamlDotNet.Core.dllが出来た。

YamlDotNet.RepresentationModel.dllも出来ていた。

これらを「Plugins」へ突っ込んだ。※いろいろ実験で関係ないDLLが混じって汚いですけど(^^)

「YamlDotNet」フォルダを作ってからその中に入れたほうが管理しやすいです。

URL: http://opcdiary.net/?p=25878
↑のサイトを参考にしたが、書き出しはなぜかコンソールといったものだったので、
Unityに特化した書き方を書きました。ほとんど真似してますが・・。

using System.IO;
using System.Collections.Generic;
using YamlDotNet;
using YamlDotNet.RepresentationModel;
using YamlDotNet.RepresentationModel.Serialization;

public class TestForStudy : MonoBehaviour
{
    protected SqliteConnection dbconn;

    void Awake ()
    {
        var calendar = new AdventCalendar();
        calendar.Year = new DateTime(2013, 6, 11);
        calendar.Description = "YAML TEST";
        calendar.Contents.Add(new Content()  {
            Day = 1,
            Author = "shinriyo",
            Description = "test",
            URL = @"http://d.hatena.ne.jp/shinriyo/"
        });
        calendar.Contents.Add(new Content() {
            Day = 2,
            Author = "Unity",
            Description = "Unity Japan",
            URL = @"http://japan.unity3d.com/"
        });

        string fileName = Application.dataPath + "/test.yaml";
        TextWriter textWriter = new StreamWriter(fileName);
        // Write YAML
        var serializer = new Serializer();
        // ※↑でSerializerが存在しないと怒られたら以下ので Genericsを書かないと空のYAMLになるので注意
        // var serializer = new YamlSerializer<AdventCalendar>();
        serializer.Serialize(textWriter, calendar);
        // don't forget Close()
        textWriter.Close();
    }

    public class Content
    {
        public int Day { get; set; }
        public string Author { get; set; }
        public string Description { get; set; }
        public string URL { get; set;}   

    }

    public class AdventCalendar
    {
        public DateTime Year { get; set; }
        public string Description { get; set; }
        public List<Content> Contents { get; set; }

        public AdventCalendar() {
            this.Contents = new List<Content>();
        }

        public AdventCalendar(List<Content> contents) {
            this.Contents = contents;
        }
    }
}

serializerのSerialize()メソッドの第一引数にはtextWriterを渡すのに少しハマった。
そうするとtest.yamlがAssetsフォルダにできます。

もし、出力場所が気に入らなければ、

        TextWriter textWriter = new StreamWriter(Application.dataPath + "/test.yaml");

これ↑の"/test.yaml"あたりをいじりましょう。

・ちなみに書きだし方

Year: 2013-06-11T00:00:00.0000000
Description: YAML TEST
Contents:
- Day: 1
  Author: shinriyo
  Description: test
  URL: http://d.hatena.ne.jp/shinriyo/
- Day: 2
  Author: Unity
  Description: Unity Japan
  URL: http://japan.unity3d.com/

ついでに、ファイルの読み込みは、

        // open
        var input = new StreamReader(fileName, Encoding.UTF8);
        var yaml = new YamlStream();
        yaml.Load(input);
        var mapping = (YamlMappingNode)yaml.Documents[0].RootNode;

        var Year = (YamlScalarNode)mapping.Children[new YamlScalarNode("Year")];
        Console.WriteLine("Year\t{0}", Year.Value);
        var Description = (YamlScalarNode)mapping.Children[new YamlScalarNode("Description")];
        Console.WriteLine("Desciption\t{0}", Description.Value);
        Console.WriteLine("Contents:");
        var items = (YamlSequenceNode)mapping.Children[new YamlScalarNode("Contents")];
        foreach (YamlMappingNode item in items) {
            foreach (var child in item) {
                Debug.Log(((YamlScalarNode)child.Key).Value + "\t" +
                    ((YamlScalarNode)child.Value).Value);
            }
        }

こうした。

残念ながらこれをiOSとかAndroidでは使えなさげだった^^;