ひつまぶし

主にメモと雑記と小ネタ。勉強会のレポートとかも時々。

Unityの初回起動でPC, Mac & Linux Standaloneのリソースインポートを回避する方法

先日の記事でUnityのコマンドライン引数のリファレンスを読んでみて、 使えそうな項目があったのでやってみた。

docs.unity3d.com

cd  "C:\Program Files (x86)\Unity453\Editor\"
Unity -projectPath "" -buildTarget android

初回だけなので、あんまり使いどころがないかもしれませんね

UntiyでiOS64bit対応をする際に、スクリプト側からビルド方法やアーキテクチャを指定する方法

qiita.com 参考サイト様

PlayerSettings.SetPropertyInt("ScriptingBackend", (int)ScriptingImplementation.IL2CPP, BuildTargetGroup.iPhone);
PlayerSettings.SetPropertyInt("Architecture",     (int)iPhoneArchitecture.Universal,   BuildTargetGroup.iPhone);

Unityのローカライズを自動化した話

某Unity製のアプリをリリースする直前で言語設定がおかしいことが判明。
UnityかXcodeのデフォルトの設定が
「en」
になっていたので、どうにかこうにかスクリプト側から
「ja_JP」
に変更できないかってことで、「Info.plist」を直接書き換えるようなスクリプトを書きました。

using System.IO;
using System.Xml;
using System.Xml.XPath;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;

/// <summary>
/// Unityビルド後言語設定をするクラス
/// </summary>
public class LocalizePostprocessor
{
    /// <summary>
    /// 単体テスト用
    /// </summary>
    [MenuItem("Tools/Localize")]
    public static void Exec()
    {
        Debug.Log("call");

        // 自分のファイルパス(フルパスで記述する必要有り
        var path = "D:/workspace/trunk/program/client/unity/app/iOS";
        
        // Postprocessorのインスタンス作成
        var instance = new LocalizePostprocessor();

        // ビルド後の処理を単体実行
        instance.OnPostProcessBuildiOS(path);
    }
    
    /// <summary>
    /// ビルド後直接呼ばれる
    /// </summary>
    /// <param name="target"></param>
    /// <param name="path"></param>
    [PostProcessBuild(1)]
    public static void OnPostProcessBuild(BuildTarget target, string path)
    {
        // iOSビルド時のみ実行
        if (target == BuildTarget.iPhone)
        {
            // Postprocessorのインスタンス作成
            var instance = new LocalizePostprocessor();

            // ビルド後の処理を単体実行
            instance.OnPostProcessBuildiOS(path);
        }
    }

    /// <summary>
    /// iOS版ビルド後の処理
    /// </summary>
    /// <param name="path"></param>
    public void OnPostProcessBuildiOS(string path)
    {
        // .plistのパス作成
        string file = Path.Combine(path, "Info.plist");

        // ファイル存在確認
        if (!File.Exists(file))
        {
            Debug.LogWarning("file not exist");
            return;
        }

        // xml読み込み
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(file);

        // CFBundleDevelopmentRegion変更
        XPathNavigator navigator = xmlDocument.CreateNavigator();
        XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
        foreach (XPathNavigator nav in navigator.Select("//string", manager))
        {
            if (nav.Value == "en")
            {
                nav.SetValue("ja_JP");
            }
        }
        xmlDocument.Save (file);
    }
}

一応できた!ってことで公開。 これよりスマートな方法があれば教えていただけるととてもうれしいです!

Go言語をsublimetext2で実行するためにしたこと。

目的

windows上SublimeText2を使用してGo言語を動かす。

SublimeTextのプラグインのインストール

PackageContollerのInstall Packageで「Go Sublime」をインストール。
PackageContollerはCtrl+Shift+pで開きます。

windows上でGo言語が動くように

golang.jp 参考サイト様

Downloads - The Go Programming Language

自分の環境に応じたものをDLしてください。
僕はwindows7の64bit版だったので「go1.4.2.windows-amd64.zip」を選択しました。

適当な場所に解凍します。

Go言語のインストール - golang.jp

Zip圧縮ファイル版
インストールしたいディレクトリ(c:\Goを推奨)にzipファイルを解凍します。

c:\Go以外のディレクトリにインストールしたときは、環境変数GOROOTにインストールしたパスを設定する必要があります。

Go言語のルートディレクトリ下のbinサブディレクトリ(例: c:\Go\bin)を環境変数PATHに設定してください。

とあるので、Cドライブ直下に言われるがままに移動。 そして環境変数

GOROOT C:\Go;
PATH   $GOROOT/bin;

の二つを追加。あとGitもよく使用するので、なければ追加しておきましょう。

PATH   C:\Program Files (x86)\Git\bin;

実行してみる

hello_world.go

package main

import "fmt"

func main() {
    fmt.Printf("hello world\n")
}

Ctrl+9を押すとGoを実行するためのコマンドラインに移るのでそこで

go run hello_world.go

と打つと先程作ったhello worldが実行されました!

Unityの入力イベントをフックしたい(願望)

UIの自動テストという魅力的な言葉につられ、ホイホイ仕事を請け負ってしまったので調べながら、書きながらやっていきます。

Java

検証1

MotionEvent | Android Developers

MotionEventというのを使えばできそうな雰囲気。

   /**
    * 入力イベントの実行
    *
    */
    public static void Invoke(final int x, final int y) {
        // アクティビティの取得
        final Activity activity = UnityPlayer.currentActivity;

        final long downTime   = SystemClock.uptimeMillis();
        final long eventTime  = SystemClock.uptimeMillis() + 100;

        // 接触時のイベント発行
        MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);

        // イベントを突っ込む
        activity.dispatchTouchEvent(event);

        // 離れた時のイベント発行
        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);

        // イベントを突っ込む
        activity.dispatchTouchEvent(event);
    }

ダメでした。 そもそもUnityPlayer.currentActivityで取得できるActivityのonTouchEventは見てない模様。 そりゃそうかーと思いつつ、もう少し調べてみる。

検証2

UnityPlayerNativeActivityのUnityPlayerで入力制御をしてる雰囲気なので、次はこのあたりを攻めてみます。

UnityPlayerNativeActivityを継承している場合

public class UnityPlayerNativeActivity extends NativeActivity
{
    protected UnityPlayer mUnityPlayer;

    //中略//
}

protectedで宣言されているUnityPlayerが触れるので、

public class InputEventEmitter extends UnityPlayerNativeActivity {
    // Unity側から呼べるようにstaticで。
    private static UnityPlayer mPlayer = null;

    @Override public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        // 参照を保持
        mPlayer = mUnityPlayer;
    }
    @Override protected void onDestroy ()
    {
        super.onDestroy();
        // 参照を破棄
        mPlayer = null;
    }
    /**
    * 入力イベントの実行
    *
    */
    public static void Invoke(final int x, final int y) {
        final long downTime   = SystemClock.uptimeMillis();
        final long eventTime  = SystemClock.uptimeMillis() + 100;

        // 接触時のイベント発行
        MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);

        // イベントを突っ込む
        mUnityPlayer.dispatchTouchEvent(event);

        // 離れた時のイベント発行
        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);

        // イベントを突っ込む
        mUnityPlayer.dispatchTouchEvent(event);
    }
}

こんなことをしてみました。 ダメでした。

結論

アクティビティを継承する形での入力イベントの発生は難しそう。 iOS編はまた今度まとめて書きます。。。