ハトネコエ Web がくしゅうちょう

プログラミングやサーバー関連、チームマネジメントなど得た技術のまとめ

はてなブログの Google Analytics で /realtime_preview などを集計対象外にする

Google Analytics のデータを久しぶりに見たときに思いました。

「あれ? この /realtime_preview ってなに・・・?」

f:id:nekonenene:20190525080702p:plain

他のページの数倍の PV 数を作り出しているんですよ(笑)
これはおかしいな、と思って調べました。

そしてたどり着いたのがこちら : Google AnalyticsのPV数に自分のプレビューとリアルタイムプレビューをカウントさせない方法 - Pocket of time

1. /realtime_preview と /preview の正体

どうやら、記事を書いているときに右側に表示されるのが /realtime_preview にあたるようです。
文字を書くごとに自動更新される箇所なので、それは PV 数もどんどん増えていくわけです。

f:id:nekonenene:20190525081148p:plain
この右側のカラムが realtime_preview

なお、私はあんまり使わないんですが、
編集画面の上部にある『プレビュー』を押したときに表示されるのは
/preview にアクセスしに行ってるそうなので、こちらも除外するのが良さそうです。

f:id:nekonenene:20190525081324p:plain
preview はこちら

2. フィルタ機能を使って集計対象から除外する

このままでは、ブログを書いている日だけ PV 数が上昇してしまい、
PV数の遷移グラフが信用ならないものになってしまいます。
フィルタ設定をおこなうことで、集計結果を正常化させましょう。

Google Analytics のホーム画面 にアクセスしたら、
左下にある歯車マークが添えられた「管理」をクリックしてください。

f:id:nekonenene:20190525082058p:plain

いろいろ出てきますが、一番右のカラムから「フィルタ」を選んでください。

f:id:nekonenene:20190525082315p:plain

「+ フィルタを追加」ボタンを押します。

f:id:nekonenene:20190525082407p:plain

例えば以下のように入力します。

f:id:nekonenene:20190525090300p:plain
/realtime_preview, /preview を除外するフィルタ設定例

  1. フィルタ名は自分のわかりやすいようお好みで
  2. 「フィルタの種類」は「カスタム」
  3. 「フィルタ フィールド」は「リクエスURI
  4. 「フィルタ パターン」には正規表現が使えるので「^/(realtime_)?preview$」と入力。
    これで /realtime_preview も /preview もフィルタの対象となります
  5. 最後に下にある「このフィルタを確認する」でどう変化するのか確認しておくと安心です
  6. 問題なければ「保存」ボタンで設定を保存します

以上です。

3. 下書きプレビュー共有URLも除外対象にする

もうひとつ、はてなブログでは、下書き保存したあとに共有URLの取得ができますが、
それについても除外対象にしておきましょう。

個人ブログではあんまり使わない機能ですが、
会社のブログなどでは使うことの多い機能かと思います。

以下のような設定になりました。

f:id:nekonenene:20190525090511p:plain
/draft ページを除外するフィルタ設定例

2. で記載した設定とほぼ同じですが、
「フィルタ パターン」を「^/draft/.+」としているのが重要な違いです。
下書きプレビュー共有URLは /draft/<文字列> のような作りになっているので、それらを除外しているわけですね。

4. おわりに

一度作ったフィルタ設定は、仮に他のブログを作ったときでも、
「+ フィルタを追加」ボタンを押したあとの画面で「既存のフィルタを適用」を選択することにより、かんたんに再利用できます。

f:id:nekonenene:20190525090755p:plain

フィルタ設定は、設定した後のアクセスのみに反映されますから、
ブログを作ったらすぐにフィルタ設定を入れて、正確な Google Analytics データを最初から取得できるようにしておくことがおすすめです!

Unity Hub でインストールした Unity の C# Script テンプレートを変更

f:id:nekonenene:20190523112647p:plain
ここから追加した際に C# Script Template が使用される

以前の Unity では以下の記事にあるように、 /Applications/Unity/Editor/Data/Resources/ScriptTemplates 以下のファイルを編集することで、
C# Script テンプレートをデフォルトから変更することが出来ていました。

support.unity3d.com

しかし、 Unity Hub で Unity をインストールした場合には、
そのディレクトリは存在しないし、仮にそのディレクトリにファイルを作成したところで Unity は影響を受けません。

では、 Unity Hub でインストールした Unity の C# Script テンプレートがどこにあるのか?
探してみました。

cd /Applications/Unity
find . -name *Script.cs.txt

./Hub/Editor/2019.1.3f1/Unity.app/Contents/Resources/ScriptTemplates/86-C# Script-NewSubStateMachineBehaviourScript.cs.txt
./Hub/Editor/2019.1.3f1/Unity.app/Contents/Resources/ScriptTemplates/81-C# Script-NewBehaviourScript.cs.txt
./Hub/Editor/2019.1.3f1/Unity.app/Contents/Resources/ScriptTemplates/83-C# Script-NewTestScript.cs.txt
./Hub/Editor/2019.1.3f1/Unity.app/Contents/Resources/ScriptTemplates/86-C# Script-NewStateMachineBehaviourScript.cs.txt

というわけで、目的のファイルは

/Applications/Unity/Hub/Editor/2019.1.3f1/Unity.app/Contents/Resources/ScriptTemplates/81-C# Script-NewBehaviourScript.cs.txt

にありました。
(※「2019.1.3f1」の部分は、インストールした Unity のバージョンによって変わります)

いちおう変更前に、念のためバックアップをとっておきます。

cd /Applications/Unity/Hub/Editor/2019.1.3f1/Unity.app/Contents/Resources/ScriptTemplates
cp "81-C# Script-NewBehaviourScript.cs.txt" "81-C# Script-NewBehaviourScript.cs.txt.bak"
ls

81-C# Script-NewBehaviourScript.cs.txt                 86-C# Script-NewSubStateMachineBehaviourScript.cs.txt
81-C# Script-NewBehaviourScript.cs.txt.bak             87-Playables__Playable Behaviour C# Script-NewPlayableBehaviour.cs.txt
83-C# Script-NewTestScript.cs.txt                  88-Playables__Playable Asset C# Script -NewPlayableAsset.cs.txt
83-Shader__Standard Surface Shader-NewSurfaceShader.shader.txt     90-Shader__Compute Shader-NewComputeShader.compute.txt
84-Shader__Unlit Shader-NewUnlitShader.shader.txt          91-Assembly Definition-NewAssembly.asmdef.txt
85-Shader__Image Effect Shader-NewImageEffectShader.shader.txt     92-Assembly Definition-NewEditModeTestAssembly.asmdef.txt
86-C# Script-NewStateMachineBehaviourScript.cs.txt         92-Assembly Definition-NewTestAssembly.asmdef.txt

81-C# Script-NewBehaviourScript.cs.txt をこのように変更してみました。

using UnityEngine;

namespace Hatone {
    public class #SCRIPTNAME# : MonoBehaviour {
        #region Unity Methods
        void Start() {
            
        }
    
        void Update() {
            
        }
        #endregion
    }
}

なお、個人的な好みで { が始まる前の改行を無くしていますが、
Microsoft の C# コーディング規約 としては
{ の前に改行を入れることを要求していますので、上のは一般的な書き方ではないことにご注意ください。

デフォルトのテンプレートに namespace を毎回付けるのが面倒だったり、
なにげに文字エンコーディングUTF-8 with BOM であることも気になっていましたので(BOM無しの UTF-8 にしたい)、
テンプレートを変えることで作業効率がアップできそうだと思います!

デフォルトのテンプレートが肌に合わない方はぜひお試しください。

macOS の Unity_lic.ulf の場所

Unity のライセンスファイルの場所についてメモ。

Linux$HOME/.local/share/unity3d/Unity/Unity_lic.ulf にあるが、
macOS/Library/Application\ Support/Unity/Unity_lic.ulf にある。

ついでに暗号化と復号についてもメモ。

export UNITY_LICENSE_ENCODE_KEY="secret_keyword"

# 暗号化の例
openssl aes-256-cbc -e -in Unity_lic.ulf -out Unity_lic.ulf.enc -k $UNITY_LICENSE_ENCODE_KEY

# 復号の例(復号しつつ Linux の適切なディレクトリに置く)
openssl aes-256-cbc -md md5 -d -in Unity_lic.ulf.enc -out $HOME/.local/share/unity3d/Unity/Unity_lic.ulf -k $UNITY_LICENSE_ENCODE_KEY

参考

はぁー、今日は Unity の Android ビルドを CircleCI で回したいなぁって挑戦してたんですけど、
1日かけても全く出来ませんでした。

いちおう Unity の Docker イメージ はあるんですけど、
Android SDK などは内包されていないので、このままだと Android ビルドに使えず……。
いろいろ試してはいたんですが普通に疲れてしまいました。難しい……

Unity の Android ビルドを CLI からおこなう

現在開いている Unity をいったん終了しないと実行できないので、
あんまり Unity の CLI は使い勝手よくないんですが、ハマりどころもあったので、いったんメモとして。

1. ビルドのために実行するコマンド

公式ドキュメントでは、 macOS の場合 /Applications/Unity/Unity.app/Contents/MacOS/Unity に Unity コマンドがあることになっていますが、
私は Unity Hub でインストールしているため、
/Applications/Unity/Hub/Editor 以下に Unity.app があります。

よって今回は、以下のような実行コマンドとなりました。

/Applications/Unity/Hub/Editor/2019.1.3f1/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -executeMethod BuildBatch.DebugBuildAndroid

Unity のバージョンアップのたびに Unity コマンドの位置が変わるのか……と考えると、
Unity Hub を使うのはなんとも微妙な気持ちになります……。

それはさておき、 -executeMethod BuildBatch.DebugBuildAndroid が大事なところで、
Android ビルドの場合、面倒ですがスクリプトを用意してあげる必要があります。
次の項でそれを紹介します。

2. ビルド用スクリプトの用意

今回は以下のようなスクリプトを、 Assets ディレクトリの下に Editor という名前のディレクトリを作り、その中に置きました。
この Editor という名前が大事なポイントで、
Unity は Assets ディレクトリ下にある Editor ディレクトリを特殊扱いします。
(参考: https://docs.unity3d.com/ja/current/Manual/SpecialFolders.html

もし仮に以下のスクリプトを Editor ディレクトリ下に置かないと、

The type or namespace name 'Build' does not exist in the namespace 'UnityEditor' (are you missing an assembly reference?)

と言われビルドエラーになってしまいます。

「Editor ディレクトリを作りたくない! 横着したい!」という場合は、
スクリプトの最初の行に #if UNITY_EDITOR 、最後の行に #endif と書くことで、
ビルド時にコンパイル対象とならないので回避できます。

話を戻しまして、以下のようにスクリプトを書きました。

using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;

public class BuildBatch {
    static void DebugBuildAndroid() {
        BuildSummary summary = BuildAndroid();
        if (summary.result == BuildResult.Failed) {
            EditorApplication.Exit(1);
        }
    }

    [MenuItem("File/Build Android", false, 220)]
    static void DebugBuildAndroidMenuItem() {
        BuildTargetGroup currentBuildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
        BuildTarget currentBuildTarget = EditorUserBuildSettings.activeBuildTarget;

        BuildSummary summary = BuildAndroid();

        EditorUserBuildSettings.SwitchActiveBuildTargetAsync(currentBuildTargetGroup, currentBuildTarget);
    }

    static BuildSummary BuildAndroid() {
        BuildPlayerOptions options = new BuildPlayerOptions();
        options.target = BuildTarget.Android;

        string[] scenes = new string[EditorBuildSettings.scenes.Length];
        for (int i = 0; i < scenes.Length; ++i) {
            scenes[i] = EditorBuildSettings.scenes[i].path;
        }
        options.scenes = scenes;

        string assetsDir = Application.dataPath;
        options.locationPathName = $"{assetsDir}/../Build/{Application.productName}.apk";

        options.options = BuildOptions.Development;

        // https://docs.unity3d.com/ja/current/ScriptReference/BuildPipeline.BuildPlayer.html
        BuildReport report = BuildPipeline.BuildPlayer(options);
        BuildSummary summary = report.summary;

        if (summary.result == BuildResult.Succeeded) {
            Debug.Log("Build succeeded: " + summary.totalSize + " bytes");
        }

        if (summary.result == BuildResult.Failed) {
            Debug.LogError("Build failed");
        }

        return summary;
    }
}

基本的にはこちらの記事を参考にしつつ、
Unity 2018.1 からは BuildPipeline.BuildPlayer が string 型でなく BuildReport クラスを返すので、
そこを変更したり一般化させたりしています。

今回はトップディレクトリに作った Build ディレクトリに apk ファイルを書き出すようにしています。(なお、同名ファイルがすでに存在する場合は上書きされます)

また、開発用ビルドとなるように options.options = BuildOptions.Development; と指定しています。
(参考: https://docs.unity3d.com/ja/current/ScriptReference/BuildOptions.html
BuildOptions を複数指定したい場合にどう書けばいいかはまだわかっていません……。

私としては Unity を閉じなくても Android ビルドをしたかったので、
DebugBuildAndroidMenuItem というメソッドを足していますが、不要な方は削除してください。

f:id:nekonenene:20190522183038p:plain

3. まとめ

上記のスクリプトを用意することで、 BuildBatch クラスの DebugBuildAndroid メソッドが存在することになったので、
-executeMethod BuildBatch.DebugBuildAndroid の指定が可能になります。

現在起動中の Unity がある場合はそれを閉じたあと、 1. で書いた

/Applications/Unity/Hub/Editor/2019.1.3f1/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -executeMethod BuildBatch.DebugBuildAndroid

を実行することで、 apk ファイルを出力してくれます。

うーん、面倒ですね……。
CI でビルドをおこなえるようにすれば意義が出てくるんでしょうけど、
まだそこまで作り込んではいないので、この状態では旨味が薄いです。

以前書いたこの記事と組み合わせて、CircleCI による Android ビルドをおこないたいですねー。

復習としては

  • Android ビルドの場合はスクリプトを書く
  • スクリプトは Assets/Editor ディレクトリ下に置く
  • DebugBuildAndroid メソッドを用意したのち Unity -quit -batchmode -nographics -executeMethod BuildBatch.DebugBuildAndroid で実行(※ Unity コマンドの場所は要確認!)

というのがポイントでした。

せっかくここまで書いたなら、CI でビルド回して deployagate に飛ばしたいですね!
がんばります!

【追記】
CircleCI でのビルド、Docker 内に Unity と Android SDK を入れた上で Android ビルドに成功させるのがそうとう困難でしたので、手動運用か、
もしくは Unity, Android SDK, Jenkins を入れたパソコンを用意して自宅サーバー化し、
Jenkins の Unity3dBuilder Plugin を利用してビルドしてあげるのが良さそうです……