p_chinのおっぱいブログ

UnityとPerlなど

Unityのversionによって起動時にダイアログで警告を出すEditorScript書いた

versionが足りないと、以下の様な表示を出す様にした

取り急ぎ、version比較条件書き換えて表示させた

必要なAPI

(4.2.0なら4.2.0f4と表示されるので、versionを比較する時にSpilitする必要はあると思う)

   

とりあえず以下にコードの片鱗を貼っておく。

なんかx.x.xの様なversion表記をよしなにParseする社内のコードがあったので、それ使っちゃったからハショってる

using UnityEngine;
using UnityEditor;
using System;
using System.Collections;

/// <summary>
/// Initialize editor invokes.
/// 今後使いそうなのでInterfeceのみ置いておく.
/// </summary>
[InitializeOnLoad]
public class OnOpenUnityEditor : Editor {

    private static string requiredUnityVersion = "4.2.0";

    /// Unityを起動した時のみstaticなConstructorが呼ばれる.
    static OnOpenUnityEditor()
    {
        // 起動して少し間を置く
        if (EditorApplication.timeSinceStartup < 10)
        {
            Debug.Log ("Initialized UnityEditor");
            // some initialize code
            UnityVersionCheck();
        }
    }

    static void UnityVersionCheck() {
        #if UNITY_EDITOR
        string diagDescription = "expected version:" + requiredUnityVersion + "\n your version:" + currentVersionStr + "\n Update unity version?";
        if (currentVersion < requiredVersion) {
            if (UnityEditor.EditorUtility.DisplayDialog("Version is not enough", diagDescription, "Update required version", "Exit unity"))
            {
                Debug.Log("Open -> " + "http://japan.unity3d.com/unity/download/archive");
                Application.OpenURL("http://japan.unity3d.com/unity/download/archive");
            } else {
                Debug.Log("Quit");
                Application.Quit();
            }
        }
        #endif
    }
}

まとめ

  • プロジェクトで、継続的にUnityで作業しない、パラメータ調整だけする人とかがたまにUnityを触ると、稀にversionが足りないだけ不具合があったりして、原因の究明に少し時間かかったりするかもなので、雑だけど作ってみた

TestFlightにapkをアップロードする時にInfo.plistやAndroidManifestに日本語が含まれてるから失敗した話

今回はアプリ名を日本語に設定(UnityのPlayerSettingsのProductName欄で)したapkをTestFlightのAPIcurlコマンドで叩いてアップロードしようとして、その事件が起きたのでメモ

具体的にどういう失敗なのか?

  • 試しにAndroidManifestに日本語が含まれてるapkをcurlコマンドに-vオプションを付けて実行してみたログが以下になる(少しハショってる)
curl -v http://testflightapp.com/api/builds.json \
-F file=@/Users/pchin/oppai/dekai/fugu.apk \
-F api_token='fugufugufugufugufugufugufugufugufug' \
-F team_token='oppaioppaioppaioppaioppaioppaioppai' \
-F notes="build by fugu" \
-F notify=True \
-F distribution_lists='macopy'
* About to connect() to testflightapp.com port 80 (#0)
*   Trying 110.173.143.147... connected
* Connected to testflightapp.com (110.173.143.147) port 80 (#0)
> POST /api/builds.json HTTP/1.1
> Host: testflightapp.com
> Accept: */*
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=----------------------------dbee02dceeab
>
< HTTP/1.1 100 Continue
< HTTP/1.1 400 BAD REQUEST
< Server: nginx
< Date: Wed, 18 Sep 2013 13:11:57 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Authorization, Cookie
<
* Connection #0 to host testflightapp.com left intact
* Closing connection #0
'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)%

   

'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)%

   

このエラーは何なのか

  • エラー自体をぐぐると、pythonのエラーの記事しか出て来ない(Testflight側のpythonのエラー?)
  • 0xe3はUTF-8のCJKの1バイト目らしい
  • 2013年の8月中旬からtestflightでInfo.plistまたはAndroidManifestに日本語が含まれるとアップロードがこける事象が良く起こってるらしい

というのを@acidlemon先生から助言頂いて、何とか解決出来た。

 

UTF-8のCJKとは

気になったので少し調べた

@kanonjiさんの旧ブログが引っかかった

*UTF-8 (CJK) : CJK (中国語、日本語、韓国語) 用の文字幅に対応している UTF-8 *

という事らしい。

rubyファイルを実行すると、shebangの書いてある1行目でInvalid charエラーが出た時の対処

Xvideos.rb:1: Invalid char `\357' in expression
Xvideos.rb:1: Invalid char `\273' in expression
Xvideos.rb:1: Invalid char `\277' in expression

上記の様なエラーが出る。

原因は、rubyやshファイルをBOM付きutf-8で保存してしまうと、何故かshebangrubyやshだと解釈して出るエラーらしい

そもそもvimのfileencodingsの設定がおかしいのは後述するが、vimの-bオプションでBOMを可視化した状態で編集出来るので、shebangの先頭にある<feff>を消してやる

.vimrcのfileencodingsの一番最初にucs-bomと書いてたのでそれでrubyファイルが保存されてたっぽいので、最初にutf-8と指定するようにした(先頭から優先的に適用するので)

foreachでコレクションを回す時に、回してるコレクションを操作してしまった時に起こるinvalidOperationException~

なんか、foreachの部分でエラーが出てびびった

// 実際にはhogeList.Clear使えばいいけどforeachで全要素を消したい時
foreach (hoge in hogeList) {
    hogeList.Remove(hoge);
}

これをやると、invalidOperationExceptionが投げられる

invalidOperationException: Collection was modified;

『コレクションが変更されてるぞ!』みたいな感じだ。

foreachでまさに回してるコレクションを削除したり入れ替えたりすると怒られるのだ

先輩達に聞いたら、C++やLLでは、これをやっても大丈夫な言語もあるらしい

 

全要素じゃないけど、任意の要素を複数消したい時はどうしよう?

現状、c#の機能だとこういうのよしなにしてくれないので

コレクションの要素を消す処理は、2段階に分けてやるしかないっぽい

以下の様な例でも、同じくinvalidOperationExceptionが発生する

// idが10以上のhogeオブジェクトを要素から削除する
foreach (hoge in hogeList) {
    if (hoge.id >= 10) {
        hogeList.Remove(hoge);
    }
}


// invalidOperationException!!!!!!!!!!!!!!!!!!!!

下のやり方ならば、要素のオブジェクトが何かユニークなメンバを持っている時に限って、エラーは出さないで、要素を消す事は出来る(DBっぽい)

// コレクションの要素を特定出来る値を取ってから一気に要素を消す
List<int> rmHogeIds = new List<int>();
foreach (hoge in hogeList) {
    if (hoge.id >= 10) {
        rmHogeIds.Add(hoge);
    }
}

//取得した要素毎のユニークなメンバリストから要素を突き止めて削除する!
foreach (id in hogeIds) {
    RemoveHogeListById(id, hogeList);
}

void RemoveHogeListById(int id, List<Hoge>) {
    // ここにidが一致したList消す処理書けばいいんじゃね
}

まとめ

金曜日の夜にこのエラーが出てテンパったけど

エラー文そのままじゃんって感じなので

『見た事無いエラー』ってだけで動揺しないでちゃんと読めよって感じだと思った

エラーの有無に限らず、今回の問題になった実装は分かりにくいかもねって思った

みなとみらいのドッグヤードで行われたプロジェクションマッピングみてきた

[イベント公式サイト]

http://www.yokohama-landmark.jp/web/pickup/special/13dockyard_pm/top.html


なんか、みなとみらいの過去から未来の建造を船に乗って冒険する感じの演出だった。

整理券が各時間帯毎に500枚まで配られてる。

その整理券が若い番号なら、その分前で見れるから、頑張って若い番号の整理券を手に入れた方が、より楽しめると思う。

(横にも映像がマッピングされるが、正直正面以外はよく見えない感じだった。)

(多分、整理券貰えなくて会場に入れない人が上から見る用なのかなって思ってる。)