Unity の iOS ビルド時に Settings.bundle を組み込む

Unity で iOS アプリを作るとき、iOS の設定に設定画面を追加することができる。 こういうの。

f:id:umai_bow:20180928103728p:plain

アプリ上で設定画面を作ってもいいが、簡単なテスト用アプリや、広く公開しないアプリなら、こっちで設定しまったほうが、バグも出ないし楽である。


iOS の設定画面を追加するには、Settings.bundle というファイルを Xcode のプロジェクトに組み込む必要がある。これは、Xcode のメニューから「File > New > File」を開き、「Settings.bundle」を選択することで作成できる。

設定した項目は、plist の Identifier を使って、Unity から PlayerPrefs で引くことができる。

var userId = PlayerPrefs.GetString("userId");

ここで1つ注意なのが、PlayerPrefs には PlayerPrefs.GetIntPlayerPrefs.GetFloat があるが、なぜか機能せず、数値などを入力させたい場合は、自力でパースする必要があることだ。

int.TryParse(PlayerPrefs.GetString("userId"), out userId);

Settings.bundle は Xcode のメニューからも作成できるが、Unity のビルドプロセスに組み込むこともできる。 これは事前に Settings.bundle を用意しておいて、OnPostprocessBuild で呼び出すことで組み込むことができる。

public class XcodeProjectUpdater
{
    [PostProcessBuild]
    static void OnPostprocessBuild(BuildTarget buildTarget, string path)
    {
        if (buildTarget == BuildTarget.iOS)
        {
            AddSettingsBundle(buildTarget, path);
        }
    }

    static void AddSettingsBundle(BuildTarget buildTarget, string path)
    {
        // PBXプロジェクトファイルのフルパス
        string xcodeProjPath = Path.Combine(path, "Unity-iPhone.xcodeproj/project.pbxproj");

        // プロジェクトファイルの読み込み
        PBXProject proj = new PBXProject();
        string file = File.ReadAllText(xcodeProjPath);
        proj.ReadFromString(file);
        string targetGuid = proj.TargetGuidByName("Unity-iPhone");

        string projectPath = "Settings.bundle";
        string copyFrom = Path.Combine(Application.dataPath, "Editor/Settings.bundle"); // コピー元の Settings.bundle のパス
        string copyTo = Path.Combine(path, projectPath); // コピー先の Settings.bundle のパス

        FileUtil.DeleteFileOrDirectory(copyTo);
        FileUtil.CopyFileOrDirectory(copyFrom, copyTo);

        string fileGuid = proj.AddFile(copyTo, projectPath, PBXSourceTree.Source);
        proj.AddFileToBuild(targetGuid, fileGuid); // プロジェクトに追加する

        proj.WriteToFile(xcodeProjPath);
    }
}

Unity の IEnumerator を返すメソッドの override

Unity には StartCoroutine というメソッドがあり、これは IEnumerator を引数にとって、非同期実行(別スレッドではない)ができるすごいやつである。

詳しくは公式サイト

これは一見魔法のように動作するが、その実仕組みはとても単純で、やっていることは、下記コードとほぼ同等である。

void Start() {
  myEnumerator = GetMyEnumerator();
}

void Update() {
  myEnumerator.MoveNext();
}

Coroutine の実行タイミングが気持ち悪い人間は、Update で自力で回せばいいと思う。

さて、Coroutine は便利な仕組みだが、継承すると、やや厄介な問題が生じる。親が IEnumerator なので、そのまま返すわけにはいかないのだ!

override IEnumerator GetMyEnumerator() {
  yield return base.GetMyEnumerator();
  yield return someValue:
}

これは期待通りに動作しない。親の IEnumerator もすべて回すには、StartCoroutine を使う必要がある。

override IEnumerator GetMyEnumerator() {
  yield return StartCoroutine(base.GetMyEnumerator());
  yield return someValue:
}

しかし、これは MonoBehaviour を継承してないときに困る。 MonoBehaviour を継承していないときは、最初の Update の例のように自力で回せば良い。

override IEnumerator GetMyEnumerator() {
  var baseEnumerator = base.GetMyEnumerator();
  while (baseEnumerator.MoveNext()) {
    yield return baseEnumerator.Current;
  }
  yield return someValue:
}

Macアプリの自動起動

展示とかでアプリの自動起動・終了を設定したいときは、launchd でやります。
ユーザー設定からぽちぽちもできるけど、launchdのほうが一気に設定とかできて便利。

1. 実行スクリプトを用意する

Macアプリを起動するならこんな感じ

startup.command

open /Application/Calendar.app

2. plist ファイルを用意する

スクリプトの実行時間とかを書いたXMLファイル。
生成するサイトとかもあるので適当に作る。

Launched

com.umaibow.startup.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.umaibow.startup</string>
    <key>ProgramArguments</key>
    <array>
      <string>sh</string>
      <string>-c</string>
      <string>/my/path/to/script/startup.command</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>

3. plist を登録する

plist を ~/Library/LaunchAgents/ にコピーして、コマンドから登録する

launchctl load -w "~/Library/LaunchAgents/com.umaibow.startup.plist"

解除するときは unload

launchctl unload "~/Library/LaunchAgents/com.umaibow.startup.plist"

テンプレを作った

github.com

最小二乗法が使えると人生が捗る

最小二乗法が使えると人生が捗る!!

{ \displaystyle
{\bf A} {\bf x} = {\bf y}
}

という数式があったとき({ \displaystyle \bf A } は行列、{ \displaystyle {\bf x}, {\bf y} } はベクトル)

{ \displaystyle \bf x } は擬似逆行列 { \displaystyle \bf A^+ } を使って、

{ \displaystyle
{\bf x} = {\bf A^+} {\bf y}
}

で表せる。
なぜかはよくわからないけど、これで解を求めるといい感じに最小二乗法っぽくなっている。

もっと具体的な例をあげる。
ある長さ2のベクトル { \displaystyle \bf a } に対して、2x2の正方行列 { \displaystyle \bf X } をかけたやつ { \displaystyle \bf y } を考える

{ \displaystyle
{\bf X} {\bf a} = {\bf y}
}

{ \displaystyle \bf a } を求めるなら、{ \displaystyle \bf X }逆行列{ \displaystyle \bf y } にかければよいが、
{ \displaystyle \bf X } の要素を求めたいケースがある。

そういうときは、一度行列の掛け算を展開する

{ \displaystyle
\begin{bmatrix}
x_1 & x_2 \\
x_3 & x_4
\end{bmatrix}
\begin{bmatrix}
a_1 \\
a_2
\end{bmatrix} = 
\begin{bmatrix}
y_1 \\
y_2
\end{bmatrix}
}

2本の式に直す

{ \displaystyle
a_1 x_1 + a_2 x_2 = y_1 \\
a_1 x_3 + a_2 x_4 = y_2
}

これを { \displaystyle \bf X } の要素を並べるように行列に戻す
{ \displaystyle
\begin{bmatrix}
a_1 & a_2 & 0 & 0\\
0 & 0 & a_1 & a_2
\end{bmatrix}
\begin{bmatrix}
x_1 \\
x_2 \\
x_3 \\
x_4
\end{bmatrix} = 
\begin{bmatrix}
y_1 \\
y_2
\end{bmatrix}
}

{ \displaystyle
{\bf A} {\bf x} = {\bf y}
}

独立している式が4本(パラメータの数)以上立てば { \displaystyle \bf X } の要素が最小二乗法で解ける。

{ \displaystyle
{\bf x} = {\bf A^+} {\bf y}
}

【ポエム】演技が苦手

昔からなのですが、人が何かを演じている姿というのが苦手です。共感性羞恥の亜種と言うのでしょうか、ドラマや映画で、人が大げさな演技をしているのを見るのが、非常に苦手なのです。何か驚いたときに、目を見開いて「わあ!」と声を上げたりだとか、怒り心頭で拳をわなわなと震わせながら、怒鳴り散らしたりだとか、そういうのを見ると、一気に冷めてしまうのです。もともと、自分が感情の発露が少ない人間だということもあり、自分なら絶対にしないような立ち振る舞いを見ると、何か、同じ人間の形をした別の生き物を見たような気持ちになりますし、嬉しくないのに笑ったり、悲しくないのに泣いているという事実に、ある種の恐怖のようなものも覚えます。同じ理由で、大げさなリアクションを取る芸人や、アイドルも苦手です。これらのようなことが、テレビの中だけならいいのですが、たまに現実でもこういった大げさなリアクションをする人がいて、たぶん、それはおそらく、そういったリアクションがテレビから逆輸入されたものだと思うのですが、まあ、とにかくそういう振る舞いに乗っかれればいいのですが、どうしてもスッと冷めてしまって、素っ気ない態度を取ってしまったりして、でも、それはそれでその人なりの愛なのだろうとも思うと、とても心苦しくなったりして……。それでもガッとテンションを上げて、あるいはお酒の力を借りたりして、応えることもできるのですが、どうしても嘘を吐いているような気分になり、あとで後悔をしたり、そういうコミュニケーションを重ねれば重ねるほど、逆に距離が離れていくように感じてしまったりして、結局、どこかでプツンと糸が切れてしまい、どうしようもない自己嫌悪や申し訳なさに襲われることになります。他人に嘘を吐くことは得意なのですが、自分に嘘を吐くことが非常に苦手なのだと思います。だから、自分に対して平気で嘘を吐ける、ように見える、人が苦手という部分もあるのかもしれません。それでも、自分に嘘を吐いていることが透けて見えるような人は、それが逆に愛おしく思えたりするのですが、それすら見えない、テレビに出ているタレントのような振る舞いをする人は、怖くて仕方がないです。

リズと青い鳥の

www.youtube.com

GWの最終日にリズと青い鳥という映画を見たのですが、これが死ぬほどよかった!

僕はアニメ映画は結構見るのですが、ここまで好き好きの好き状態になるのは何年振りか。

ただ、人を選ぶ気がします。

感想文を書こうと思ったのですが、何を書いても文章にならないので、感想単語を書きます。

  • スカート
  • 給水機
  • ポニーテール
  • ポリリズム
  • 互いに素
  • 貸出図書
  • あじついてておいしい
  • リード
  • 音大
  • 髪を触る
  • フグ
  • ワンピース
  • 音楽室
  • 光の反射
  • 本番
  • 逆転
  • 岩波文庫
  • 鍵の開け方
  • オーボエ
  • アイスクリーム

【宇宙よりも遠い場所】なぜめぐっちゃんは赦され、日向のチームメイトは赦されないのか

宇宙よりも遠い場所』を全話見て、練られたプロットとキャラクター、技巧的な演出に感銘を受けました。 ここ数年で見たアニメ作品の中でも、トップに入ると思います。 見ていない方はプライムビデオとかで見られるので全話見てください。

www.amazon.co.jp

ただ、どうしても引っかかった部分が一つだけあって、それが表題の件なのですが、言及しているレビューやブログも多かったので、少し自分なりの考えを整理してみました。

めぐっちゃんと日向のチームメイトは何が違うのか

めぐっちゃんのエピソードは5話で、ずっと自分が世話を焼いていると思っていたキマリが、いつの間にか目標を見つけ、自分の道を進んでいることにショックを受け、陰口を裏で流してしまうというものです。

日向のチームメイトのエピソードは11話。 陸上部だった日向は、上級生とのレギュラー争いで手を抜こうとするが、同じ部活のチームメイトの励ましで、手を抜かずに走り、レギュラーを勝ち取ります。 しかし、それが上級生の逆鱗に触れ、上級生に問い詰められたチームメイトは「自分は止めた」と蝙蝠のような対応をしてしまいます。 それを陰で聞いていた日向は、虚しさから部活を辞め、さらにいじめは続き、高校を辞めることになります。

これらの行いは、いじめに加担した、陰で嘘をついたという点では大きく変わらないものです。 しかし、めぐっちゃんはキマリから絶交を断られ、友人として関係を続けていくことになりますが、一方で、日向のチームメイトは報瀬から二度と関わるなと拒絶されることになります。

実際にこの2つのエピソードは対立的で、3話で日向は創作名言で「人には悪意があるんだ。悪意に悪意で向き合うな。胸を張れ。」と言い放ち、実際にキマリは悪意には悪意で返さずに、めぐっちゃんと和解します。 11話でも日向はこの言葉の通り、チームメイトやいじめの悪意には向き合わず、無視しようとしますが、最終的には報瀬の反論、ともすれば悪意と呼んでもいいほどの暴言でチームメイトらと絶交することになります。

めぐっちゃんは誠実だから赦されたのか

さて、文章にすると如何にもフェアでない審判に思えますが、実際に鑑賞すると、受ける印象はかなり違います。 なぜなら、めぐっちゃんは、涙ながらに自分の行いを告白し、キマリに絶交しようと迫りますが、11話で謝りに来た日向のチームメイトは、髪をいじり談笑しながら出番を待ったりしていて、いかにもいじめられていた日向とは関係なく明るい学生生活を送っていたように見えるからです。 なので、話の流れとして、めぐっちゃんは赦され、日向のチームメイトは赦されないというのは、それほど不自然ではありません。

しかし、これだけでは、シナリオが変わる理由としては少し弱いと思います。 なぜなら、実際のところ、日向のチームメイトは喋る前にカメラを切られてしまったり、一方的にまくし立てられたりしてしまって、ほとんど何も喋れていないからです。 もし、態度の問題であるなら、明確に行動やセリフで違いを表現するはずです(よりもいはそういうところをキッチリするアニメだと信じています)。

キマリは傷つかず、日向は傷ついたからなのか

また、もう一つの見方として、キマリはあまり傷ついていないが、日向は退学するほどに傷ついたからだというものがあると思います。 しかし、これもやはり決定的でないように思えます。

そもそも、キマリはめぐっちゃんの告白を受けて、泣くほど動揺してるわけですし、度合いの話なら「じゃあどれぐらいならいいの?」という漠然とした疑問が残ります。

もちろん、上にも書いたように、話の流れとしては、日向はほとんどトラウマになっているぐらいですから、別にそのような解釈でも違和感はないのです。 ただ、一つの作品として見たときに、かなり似たエピソードをやりながら、シナリオの流れが大きく違うからには、明確な理由が存在しないといけないように思えます。

『よりもい』は友情のアニメで、倫理のアニメではない

「日向のチームメイトが赦されるプロットでも良くない?」と、11話初見時は強く感じたものでした。 友情をテーマにした『よりもい』というアニメで、より戻そうとした友情を無碍にするエピソードなのです。 倫理的な話なら、罪を赦すほうが正しいように思えます。 それは、日向自身も最後まで決めかねたことですし、前述の通り、演出として正解は示されていません。

でも、報瀬は倫理に従って行動しているのか?という点で見ると、そもそも、報瀬は倫理や常識など、まったく気にしていません。 報瀬は、友達の日向が傷つけられたことに激昂しただけであって、日向のチームメイトを裁いたわけではないのです。

これこそが、5話と11話の違いを決める答えです。 5話は、少しの歪みでは揺るがない厚い友情の物語で、11話は、倫理や常識を意に介さない強い友情の物語なのです。

見直してみると、報瀬がキレたすぐ後に、結月がまるっとそのままの答えを言っているのでした。

『いいじゃないですか!友情じゃないですか!』