mattak's blog

人生を1ミリ進める

Boidsを試す

Unite 2018でBoidsの話があったのだけど、面白かったので真似して実装してみる.

Boidsとは

Boids - Wikipedia

群体のシミュレーションをする際に、3つのルールを適用すればObject群がそれっぽく動くということらしい.

wikipediaの画像が分かりやすかった.

ルール1. 分離

  • ローカルの群れを避けるようにステアリングする

ルール2. 整列

  • ローカルの群れたちが向く方向の平均にステアリングする

ルール3. 凝集

  • ローカルの群れの平均位置に向かってステアリングする

実装

雰囲気で実装してみる.

github.com

public class Boid : MonoBehaviour
{
    public bool ApplySeparation = true;
    public bool ApplyAlignment = true;
    public bool ApplyCohesion = true;
    public bool ApplyRandom = true;
    public float Radius = 10f;

    private Transform[] allmates;

    private void OnEnable()
    {
        this.allmates = this.transform.parent.GetComponentsInChildren<Boid>()
            .Where(it => it.gameObject.GetInstanceID() != this.gameObject.GetInstanceID())
            .Select(it => it.transform)
            .ToArray();
    }

    private void FixedUpdate()
    {
        var randomStrength = 0.0001f;
        var flockmates = TransformUtils.SelectLocalFlockmates(this.transform, this.allmates, this.Radius);

        var v1 = this.ApplySeparation
            ? TransformUtils.CalcSeparationRule(this.transform, flockmates) * 10f
            : Vector3.zero;
        var v2 = this.ApplyAlignment
            ? TransformUtils.CalcAlignmentRule(this.transform, flockmates)
            : Vector3.zero;
        var v3 = this.ApplyCohesion
            ? TransformUtils.CalcCohesionRule(this.transform, flockmates)
            : Vector3.zero;
        var vr = this.ApplyRandom
            ? new Vector3(
                Random.Range(-randomStrength, randomStrength),
                Random.Range(-randomStrength, randomStrength),
                Random.Range(-randomStrength, randomStrength))
            : Vector3.zero;
        var diff = v1 + v2 + v3 + vr;

        this.transform.LookAt(this.transform.position + diff);
    }
}

各ロジック

public static class TransformUtils
{
    /// <summary>
    /// Calc boids rule1. steering position by separation.
    /// </summary>
    /// <param name="target">target object</param>
    /// <param name="flockmates">local flockmates without the target object</param>
    /// <returns>stearing vector by separation rule</returns>
    public static Vector3 CalcSeparationRule(Transform target, Transform[] flockmates)
    {
        if (flockmates.Length < 1) return Vector3.zero;
        var v = flockmates.Select(it => target.position - it.position).Aggregate((sum, it) => it);
        return v / (0.00001f + v.sqrMagnitude);
    }

    /// <summary>
    /// Calc boids rule2. steering position by alignment.
    /// </summary>
    /// <param name="target">target object</param>
    /// <param name="flockmates">local flockmates without the target object</param>
    /// <returns></returns>
    /// <returns>stearing vector by alignment rule</returns>
    public static Vector3 CalcAlignmentRule(Transform target, Transform[] flockmates)
    {
        if (flockmates.Length < 1) return Vector3.zero;
        return flockmates.Select(it => it.forward).Aggregate((sum, it) => sum + it) / flockmates.Length;
    }

    /// <summary>
    /// Calc boids rule3. steering position by cohesion.
    /// </summary>
    /// <param name="target">target object</param>
    /// <param name="flockmates">local flockmates without the target object</param>
    /// <returns>stearing vector by cohesion rule</returns>
    public static Vector3 CalcCohesionRule(Transform target, Transform[] flockmates)
    {
        if (flockmates.Length < 1) return Vector3.zero;
        var average = flockmates.Select(it => it.position).Aggregate((sum, it) => sum + it) / flockmates.Length;
        return average - target.position;
    }

    /// <summary>
    /// Select local flockmates within the circle radius
    /// </summary>
    /// <param name="target">target object</param>
    /// <param name="mates">flockmates object without me</param>
    /// <param name="radius">raidus of target flockmates</param>
    /// <returns></returns>
    public static Transform[] SelectLocalFlockmates(Transform target, Transform[] mates, float radius)
    {
        if (mates.Length < 1) return new Transform[0];
        var radius2 = radius * radius;
        return mates.Where(it => (it.position - target.position).sqrMagnitude <= radius2).ToArray();
    }
}

結果

なんかたのしい! せっかくなのでちょっと整理したらライブラリとして体裁整える。

試行数4

試行していく

雑に書いていく運動

3冊読んだ.

どれもいい本だった。 失敗の科学は、マージナルゲインの考え方、失敗を隠蔽する組織と失敗を共有し学ぶ組織の違いが印象的だった。 仕事は楽しいかねは、何度もいくつも同時に試行していくことを例示豊富に教えてくれた。 チーズはどこへ消えた?はコンフォータブルゾーンから出て勇気を持って新しいチーズを探していくことことの喜びが示唆されていた.

最近アウトプットが少ない、何かを試行する機会も少ない。 どんどんと何かを試行していきたい。でもって試行したことをカジュアルに残していこうと思う。 できればそれをFB回路に繋げて、少しづつ改善していきたい. 強化学習もそうだけど、どんどん試して試行して、たくさん失敗することは大事だ。

意識して試して、楽しんで、失敗して、少し改善をやっていこうとおもう。 とりあえず今年100個何か新しいことを試行するのが目標.

あと234日. 2日に1個何かを試していくペース. ちょっときついか... 週に1個は何かやっていく感じで行こう. あと33週なので 30個くらいを目標にする。 うーんでもぬるい感じがする。

とりあえず、3冊読んだのであと97個ということにする。

Rider で全体に適用したコードフォーマットを切り替えたい...!

本当はプロジェクトの設定でコードフォーマットを指定するのが良いのかもだけど、自分用メモ。

OSSはデフォルトの設定、業務は特定の設定でのコードフォーマットをRiderに適用したい.

最終的に Riderの設定をgit管理するのが良さそうという結論に至った。

gist.github.com

git check out resharper-host/GlobalSettingsStorage.DotSettings で一発リセットできるので便利!

モバイルプロジェクター MP-CD1 を買った

思ってたよりも、とてもよい!

スペック

www.sony.jp

明るさ

割と明るい

他のメーカーのlumenは中心の明るさ で測っていたりするので、ちょっと比較すると感じ方が違うので注意。 ヨドバシの店頭で比べたのだけど、105 ANSI lmはほかの600lm ~ 800lmとかとくらべてもわりと明るかった。

Lumen (unit) - Wikipedia

とくに環境光が強い場所でなければ、問題になることはなさそうだとおもう。

解像度

超解像度じゃないけど、ぜんぜん許容できる。

はじめは、かなり解像度ひくいなーっておもってた。 で、店頭での展示をみたときも残念に感じた。 よくよく観察すると30cmぐらいの短距離(小さな画面)で投影していたり、ピントが合ってなかったりするだけだった。。 きちんとピントを合わせてみると、そこそこの長距離 (2mくらい) でも見た目がひどく荒い印象はなく、情報がつぶれて見えないってこともなかった。 家で写してみても、実用的に使えそうで良さそう。

重さ・大きさ

重さ: とても軽い

  • 約280g

大きさ: スマホちょいデカくらい

  • 約83.0 mm × 16.0 mm × 150.0 mm

f:id:mattaclj:20180423004943j:plain

配線

f:id:mattaclj:20180423010051j:plain

HDMI (projector) <=> adopter (hdmi to usb-c) <=> type c (mac book)

という感じで出力。 type c の入力もprojectorについているのだけれど、こちらは給電のみ。 給電 + 映像出力できればケーブル減って嬉しかったけどそれはできない...

少しPCのファンを回しているような音がする。 でも静音だと思う。気になるようなうるささではないし、外でも普通に使って問題ないと思う.

用途

仕事

最近は外出したり、家にいたり、コワーキングスペースやら業務委託先やら、いろんな場所で働くことが多い。 モバイルプロジェクターはスペースを取らないし、どこでもデュアルディスプレイが実現できるのがとても良い感じな雰囲気がしている。 (今日買ったばっかりなので実際にどんな感じかはわからない)

f:id:mattaclj:20180423005005j:plain

自宅

自宅は狭いので、ディスプレイは置く場所がかぎられてかつスペースと電源を消費する. その点モバイルプロジェクターはどこでも持っていけて、スペースも取らなくてよさそう!

天井に映して寝転びながらゲームしたり、映画見たり

f:id:mattaclj:20180423005048j:plain

台所の壁にレシピを映しておいたり

f:id:mattaclj:20180423005113j:plain

他にも、ガラス越しに投影して風呂場でYoutubeみたりとか アイデア次第で結構色々できそうな気がする.

家のどこにでスクリーンを持ってこれるっていう体験が画期的でした!

GDC 2018 帰宅編

帰るまでがGDC! 最終日は夜中フライトだったのでちょっと観光してた。

観光

GoldenGate Park 外周が20km弱くらいある感じの超広い公園

f:id:mattaclj:20180324091555j:plain

California academy of Science 世界各国の水性生物の展示が地下にあって(水族館っぽい)、規模もすごかった。 水族館好きの人とか一日中楽しめると思う

f:id:mattaclj:20180324101355j:plain

de Young Musium 世界各国の絵画展示など. ちょうど世界の機械の歴史展みたいなのをやっていた。 絵画との距離がとてもちかくて (柵とかもほぼない)、展示スペースも大胆に使っているのが印象的だった。 たぶん、監視カメラやら監視員が常駐して見回っていたから、少しでも変なことをするとしょっぴかれるんだろうけれど、 観客を信頼して自由にスペースを取っている感じがした。

f:id:mattaclj:20180324132124j:plain

ゴールデンゲートブリッジ

f:id:mattaclj:20180328234843j:plain

例のチョコが売っている街の一画 小売店が密集していている感じだった。

f:id:mattaclj:20180324181005j:plain

丘から見えるアルカトラズ島

f:id:mattaclj:20180328234806j:plain

航空トラブル

観光も一通りしたし、ナイトフライトで寝るぞ!っておもっていたが・・・ 飛行機の機器トラブルで5時間機内に閉じ込め.... 再フライトは12時間後とのこと、

そこで航空会社から2つの選択子を提示される

  1. $300まで支払うので各自ホテル取って!領収書ちょうだいね!
  2. ホテル予約するので列に並んで待っていてね!

現地の通話もできないし、外に出て戻れなくなるのも怖かったので2を選んだんだ. けれど予約が直前過ぎて一部の客までしか対応できず... 飛行場で12時間過ごす...

暇だったので、調子にのってSFO内のカフェでコードを書いてました。

f:id:mattaclj:20180325102011j:plain

5時に搭乗開始!って思っていたのだけど、実際には4:30 登場開始. ギリギリまでコード書いていて、よし行くぞ!っておもったら、搭乗ゲートにはだけもいない!! ???ってなって、ウロウロしているとCAらしき人が来て、12番の受付にこいっていわれた。 え、ゲートはA12誰も居ないけれど・・・ってなって、flight boardを確認しても昨日の情報のまま更新されていない! 入国審査付近のおばちゃんに事情を説明して聞いてみたら、〜航空は8番ゲートだから戻れ!って言われて戻っているときにCAに12番に来いって言われる。 よく考えると航空会社ごとの受付の12番のことで、一度通過した荷物検査場所を出なきゃいけない感じだった。 一度出たら戻れない恐怖があって外に出る確信が持てなかったのだけれど、CAの人に連れて行かれて12番へ.

再受付をして、国際線とは反対の国内線ウィングのG99ゲートへ。 荷物検査を再度受ける。このときにすでに16:30過ぎていたのでやべーってなった。 よく見ると列に同じ便の若者が並んでいたんで、冷や汗ダラダラになりつつ、ちょっと落ち着く。 途中でアナウンスがあって、G95 => G99ゲートへ登場変更したとのこと. G95についたときは出発時刻の5分後だったのだけど、まだ乗客が全員集まっていなくて、20分ぐらいそのまま他の客を待機する. なんだかんだでフライト開始するまでに2時間ぐらいまた待機。

11時間かけて、Incheon空港に到着!って思ったら、天候不良によってJeju空港に離陸変更を余儀なくされる.

f:id:mattaclj:20180326082611j:plain

その時機内で流れていた広告。

"すべての道はIncheonにつづく" (ただし止まるとはいってない)

f:id:mattaclj:20180326084958j:plain

他の乗客から話を聞くと、Jejuは韓国の沖縄的な場所らしい。 結構高いホテルにとまった。 この時現地時間で夜4時、バスが9時に出るので、3時間ほど寝て朝食をとってGO。

f:id:mattaclj:20180327031348j:plain

Jejuはちょうど桜の開花時期で、テキサスから来たっていってた韓国のおばちゃんにbeojkko (ボッコ)って桜はいうんだよってのを教えてもらう。 彼女も5日間の予定で韓国に帰国する予定だったんだけれど、おかげで2日間は予定が潰れたっていってた。

またJejuからIncheonに入るときに、入国審査をしたのだけど、日本人のパスポートだけ全回収される事案が発生。 日本語がわかるCAの人が、私は日本に就職していたから安心してみたいなことをいわれて、日本人の他の客と??? ってなりながらパスポートを取り上げられてしまう。 たぶん、入国審査が甘くて日本の誰かを再審査したいけれど、誰かわからんからとりあえず全再審査したんだと予想。

f:id:mattaclj:20180329000553j:plain

なんだかんだあって、Incheon空港に到着して、羽田に行きたいんだけれどっていうと、他の日本人組とわかれてしまう (彼らは熊本経由で成田/愛知などに帰宅)。 理由は自分の飛行機の便のとり方が特殊で、Incheon空港 => Gimpo空港に電車移動して羽田にFlightする感じの便だったから。 CAの人が超困りつつ、成田でもいいからなんか便ない?って聞くと他の航空会社と連絡取ってなんとかIncheon => 成田行きの便を用意してくれた。

という感じで色々面白い体験ができました! いろいろ怒っている人はいたんだけれど、トラブルもなかなか楽しい感じでした。(ただしとても疲れた)

GDC 2018 3日目

セッション

assassin's creedのmeta ai、horizonの植物objectの管理、GoWのアニメーション遷移の手法、freelancerの話などを聞いてきました。 horizonの人のスライドがひたすらかっこよかった。 関係ないけれど、海外のエライ系のエンジニアとかの役職は Principal ~ っていう肩書がおおいのだろうか...

f:id:mattaclj:20180324215909j:plain

展示

最近 vtuber とかでよく見る getting over it.

f:id:mattaclj:20180324215454p:plain

観光

Goden Gate Park

f:id:mattaclj:20180324215925j:plain

めし (生春巻き)

f:id:mattaclj:20180324215934j:plain

サラダ系は Fresh ~ ってパターンで呼ぶ感じっぽい..

GDC 2018 2日目

昨日はかなり時差ボケが厳しくて終盤眠くて仕方なかったんだけど、だいぶ治った感じがある.

セッション

monument valley 2, monster hunter, detroid: become a human, Horizon, supercell, apple ARとかなり豪華なセッションをひと通り見ました。 どれも知見に溢れていて、素晴らしかった。 (monument valley 2だけ、時差ボケの眠気に勝てなかったのが悔しいけれど...) とくにsupercellがかなりレベルデザインシンプルに明瞭に設計しているんだなぁとか、モンハンはプロトタイプで50-70人って規模すごいなぁとか感じてました。 コンシューマのプロトタイプ、各社違いがあって面白かった。

展示

amazon

f:id:mattaclj:20180322131422j:plain

deepmind

f:id:mattaclj:20180322130907j:plain

mapbox

f:id:mattaclj:20180322130836j:plain

なんか一通りの企業は出ていた感じがします。

めし

ずっと雨だったんですが、久々に晴れて良い感じ! ここでPokemonGoのルギア & GDC限定のアンノーン取りまくってました。 (すぐにPokeGOユーザが集まって狩りやすい。自分と同じくらいのレベルユーザが多く、東京よりもユーザのレベルは-10ぐらい低い感じがした。東京異常だ)

f:id:mattaclj:20180323213719p:plain

シンプルにパンとドリンク. でもでかい

f:id:mattaclj:20180322132217j:plain

その他

コインランドリーで洗濯をしたのだけれど、洗剤が買えない! insert coinってなっているところに25 cent入れるのだけど狭すぎてむりだーってなった。 結局隣のスーパーから買うことに...

f:id:mattaclj:20180322194319j:plain

クレープ屋に並んでいるときにワシントンのお兄さんとお話したのだけど、 GDCスタップは半分働いて、半分見放題みたいなシフトらしい。 行きたい人でチケット代が高くて払えない!って人は申し込むと良さそう。