Edited at
Unity 2Day 14

他人のシーン編集を見える化するぜ!

More than 1 year has passed since last update.


プロローグ

「Advent Calendar2016Unity 2 Advent Calendar 2016」の記事だよ。

だれかが書こうとしてたけど、12月12日はとっくに過ぎてたんで上書きますw

もとの方はUniRxで書こうとしてたっぽいから、僕もUniRxも使うことにしますね。


前書き

チームでUnity使っていて、シーン編集をするときにいちいちチャット部屋で共有とか、他の人に確認するの手間かと思います。

それを見える化する方法を考えました。


今回使うもの


  • Unity 5.5.0x1-CollabOreview

  • UniRx 5.5.0 (Unityとほぼ同じだw)

  • Python 3.5

  • gunicorn 19.6.0

  • Falcon 1.1.0

※今回DBは面倒なのでプレーンテキストにしますw


サーバ準備

API作るのにFalconが楽そうだったのでそうします。

PHP使いたい人はPHP使って下さい。


バーチャル環境

virtualenv-3.4 falcon_apps

source bin/activate

Falconとgunicorn入れるよ

pip install falcon gunicorn


Pythonのコード


sample.py

#!/usr/bin/env python

# -*- coding:utf-8 *-

import falcon
import json

FNAME = 'text.json'

class QuoteResource:
def on_get(self, req, resp):
str = self.read()
# resp.body = json.dumps(str)
resp.body = str

def on_post(self, req, resp):
resp.status = falcon.HTTP_200
resp.content_type = 'text/plain'
resp.body = 'post!!'
# リクエストボディを読み込んで JSON を解析
body = req.stream.read().decode('utf-8')
print(body)
self.write(body)

# 本当はDBから書く
def write(self, data):
# 追記なのでa
with open(FNAME, 'a') as outfile:
json.dump(data, outfile, indent=4, sort_keys=True, separators=(',', ':'))
# これがないと改行がない
outfile.write('\n')

# 本当はDBから読む
def read(self):
content = ''
with open(FNAME) as fp:
for line in fp:
data = json.loads(line)
dic = json.loads(data)
msg = '{} が {} の {} を編集しました ({})'.format(dic['user'], dic['screenPath'] , dic['sceneName'], dic['time'])
print(msg)
content += msg + '\n'

return content

api = falcon.API()
api.add_route('/quote', QuoteResource())



Falconはここを参考にしました

https://freedom-man.com/blog/python-falcon/


jsonのファイル記載と、読み込み系はここから参考に(Martin Thomaさんのコメント)

http://stackoverflow.com/questions/12309269/how-do-i-write-json-data-to-a-file-in-python


起動

gunicorn sample:api

sampleはファイル名sample.pyから、

apiは中にある変数名。


Unity側

UniRXはAsseetStoreからとってきて下さい。

別にUniRXを使わずにWWWを生で書いてもOKです。

こちらを書きます。Editorフォルダに入れなくてもいいですが、入れた方がいいかも?


MyAssetModificationProcessor.cs

using System;

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UniRx;

public class MyAssetModificationProcessor : AssetModificationProcessor
{
[Serializable]
public class CustomModel
{
public string user;
public string screenPath;
public string sceneName;
public string time;
}

public static string[] OnWillSaveAssets(string[] paths)
{
// Get the name of the scene to save.
string user = "shinriyo";
string scenePath = string.Empty;
string sceneName = string.Empty;

foreach (string path in paths)
{
if (path.Contains (".unity")) {
scenePath = Path.GetDirectoryName (path);
sceneName = Path.GetFileNameWithoutExtension (path);
string msg= string.Format ("{0}が{1}パスの{2}ファイルを編集中です.",
user, scenePath, sceneName
);
Debug.Log (msg);

// Postリクエスト
// form要素設定
var obj = JsonUtility.ToJson(new CustomModel {
user = user,
screenPath = scenePath,
sceneName = sceneName,
time = DateTime.Now.ToString ()
});

WWWForm form = new WWWForm();
form.AddField("data", obj);

// ObservableWWW.Post ("http://127.0.0.1:8000/quote", form)
byte[] data = System.Text.Encoding.UTF8.GetBytes (obj);
ObservableWWW.Post ("http://127.0.0.1:8000/quote", data)
// タイムアウト時間設定.
.Timeout(TimeSpan.FromSeconds(30))
.Subscribe(result =>
{
try
{
// JSONをパース.
Debug.Log("ok");
}
catch (System.Exception e)
{
Debug.Log("JSONのパースに失敗しました.");
}
},
err =>
{
if (err.GetType() == typeof(System.TimeoutException))
{
Debug.Log("タイムアウトしました.");
}
else
{
Debug.Log("通信に失敗しました.");
}
});
}

if (sceneName.Length == 0)
{
return paths;
}
}

return paths;
}
}


これを記載して配置しておくだけで、スクリプトが勝手にPOSTしてくれます。。


Webへの投稿コードはこちらを参考にしました。

http://belhb.hateblo.jp/entry/2016/05/02/025713


ソースについて

CustomModelとかわざわざ作るの面倒なので、無名クラス(new {hoge="val1", bar="val2"})とかでできればよいのに!

Formでやるとdata=パラメータがくっついてしまう。

WWWForm form = new WWWForm();

form.AddField("data", obj);
ObservableWWW.Post ("http://127.0.0.1:8000/quote", form)

substringとかで一生懸命data=を消したりとかやろうとしてしてしまいましたが、

今回のソースコードのようにbyte[]にしました。


この時ここを参考

http://naichilab.blogspot.jp/2014/08/unityunirxrest-apipost.html


実行

シーンを編集して保存してみて下さい。

http://127.0.0.1:8000/quote

にアクセス

こんな感じのログが見えます。


最後に


  • 今回のはほんの小さなサンプルです。

  • 実際はデータベースに入れましょう。

  • quoteのURLもきちんとしましょうね。

  • ファイル名も今回sample.pyとかだったので名前きちんとしましょう。

  • 今回はローカルで行いましが実際はサーバを立てて置きましょう。

  • だれかキチンと作ったらシェアしてね。それか僕が作ったらAssetStoreに置くかも?

  • Prefabも対応するのもいいかも?