imog

主にUnityとかの事を書いています

AndroidでWireguardのVPN接続ができない時の対処法

事象

Pixel7(Android 13)でWireguardを使ってVPN接続を行なっているんだけど、社内に接続できない事象に遭遇した。 ログを見てもらったところ普通に自分のグローバルIPでアクセスしており、WireguardがONになっているがトンネル通ってないよということがわかった。

端末側でも、オプションから「VPN以外の接続のブロック」にチェックを入れたところ全てのページが見れなくなったので、これはトンネル通ってないなと確信した。

対応

とりあえず一回アンインストールしてみるかーということで削除したが、特に状況は変わらなかった。 なので次はインストールのプロファイルを変えるようにした。

現状端末は個人プロファイルと仕事用プロファイルに分かれており、Wireguardは個人プロファイル、社内にアクセスするアプリは仕事用プロファイルに所属していた。

https://support.google.com/work/android/answer/6191949?hl=ja

仕事用でしかVPN使わないのだからWireguardも仕事用プロファイルにインストールしたら、無事にVPN接続できるようになった。 結論としては、VPNはプロファイルごとに適用されるので、実際に接続しにいくアプリと同じプロファイルにまとめましょうという感じでした。

余談

それはそれとしてAndroid13で動かないという不具合報告は結構あるっぽい

https://www.reddit.com/r/GooglePixel/comments/wpcy0n/psa_dont_upgrade_to_android_13_if_you

Bakinのバトルスクリプトのプロジェクトを開くとエラーが発生するときの対応

2023/03/11 追記

この記事の現象は1.2.0.2で解消されました。 store.steampowered.com

1分で終わるけど多分毎回忘れるので備忘録。

結論

本体の lib 以下にdllが揃ってるのでそれを使いましょう

Bakin 1.2でバトルスクリプトの拡張ができるようになりました。

store.steampowered.com

拡張機能」から「バトル関連ソースをゲームファイルにコピーする」を選択すると、csprojファイルとサンプルコード一式が出力されます。

ただ、そのままだとDLLが足りないので怒涛のコンパイルエラーが発生します。

Projects以下を見ると、Common SharpKmyCore Yukar Engine が参照できていないことがわかります。

これらを全部参照してあげたらとりあえずコンパイルエラーは解消できます。

DLLは全部BAKIN本体のプロジェクト以下にあるのでそれを使いましょう。

  • bakinengine.dll
  • common.dll
  • SharpKmyCore.dll

まだアーリーアクセスなので、細かいところは踏み抜いていきましょう

2022年ふりかえり

今年はあんまり表立った活動はしていないなあというアレ。

ゲーム開発

touhou-gamejam.web.app

毎年参加してるゲームジャムで、「Five Elements of wisdom」というパズルゲームを作った。

www.youtube.com

5種類の弾幕の特性を組み合わせて妖精を全滅させるゲームで、いかに最低限の手数で全滅させられるかを競うゲーム。理論上はすべて1手で倒すことができる(頭は使うけど) このパズル部分のシステムをメインで担当しました。

チームメンバーがかなりグローバルで、日本語・英語・ロシア語が飛び交う中で僕は翻訳にかけながらコミュニケーション取ってました。ちゃんと英語は読み書きできたほうがいいぞという自戒。

もう一個は、幻想戦略録というゲームのお手伝いをしております。がんばりますうへぇ。

store.steampowered.com

OSSとか

今年はVContainerとUniTaskのコードを見る機会に恵まれたなという感じでした。

github.com

github.com

だいたい業務や趣味で使ってるときに不具合っぽいのを見つけて対応->PRみたいな流れをやってました。そんなに数をこなしたわけではないのでゴリゴリやってましたとはいえないけど、少なくとも何かあったときにコード読んでここじゃないか?と当たりをつけるくらいはできるようになったのでそれはよかったかもしれない。 両ライブラリにはめちゃめちゃお世話になっております。

転職とか

ご縁があってMIXIを退職してミラティブに転職しました。業務的には引き続きUnityを使った開発がメインです。新卒から数えて3社目ですが、同じ会社というものは殆どなくてそれぞれ違う空気感、スピード感を出してます。 まだ入ったばかりなのでアウトプットはないですが、来年から頑張っていきたいところ。

また、ほぼフルリモートになるので東京を離れて故郷の福岡にお引越し活動中です。

ゲーム

記憶に残ってるやつだけ・・

アルセウスに始まりSVに終わるというポケモンな1年だったかもしれない。 普段スマホゲームはそこまで続かないんだけど、ダダサバイバーだけはかなりハマりました。このゲームがなんで面白いんだろうみたいなのを同僚と結構話してました。ただ、ヴァンパイアサバイバー系は増えまくって食傷気味ではある・・

ちなみに2022年前期はマスターデュエルに時間を根こそぎ奪われていったので封印しました。

今年はこれいいよ!と言われた本をその場で購入するムーブを繰り返してました。

所感

2022年は面白いゲームって何なんだろうなみたいな気持ちになることが多く、その反動もあっていろんなゲームを遊ぶことが増えました。なんで繰り返し遊びたくなるんだろうとか、なぜこの演出が好きなんだろかとか、なんで苦行をしてまでマラソンをするのかみたいな、ハマっている理由を自分の中で言語化する機会が増えた気がします。わりかしレトロゲー好きの自分にとってはエルデンリングをプレイしたことだけでも大きな一歩かもしれない。ゲームを作るプログラマーである以上、現代のゲームのシステムで会話できないのは良くないなと思ったのでした。

とは言え、本業のリリースでいっぱいいっぱいでかつゲームやってたので、正直外部活動に目を向けられてなかったなあというのはあった。それは来年の目標ということで・・

今年もお疲れ様でした。

Zennでアドカレ書いた

今年のアドカレです。

zenn.dev

初めてZennを使ってみたけど、技術記事書くならはてなよりだいぶ楽だな・・と思ってしまった。

とはいえあっちは雑記を書く感じじゃないの使い分けになるんだろうか。それはそれでめんどう

【感想】メイドインアビス 闇を目指した連星

Steamで購入

store.steampowered.com

とりあえず月笛になったので第三階層を今から潜ろうというくらいの状態。 Steam評価が賛否両論になってるのは、だいたい同意。

楽しいところ

探窟家ライフを満喫できる

DeepAbyssは完全オリジナルストーリーで、主人公が見習いから白笛を目指して探窟家として成長していく物語となっている。ちゃんとアビスの世界の探窟家として、遺物を集め、依頼をこなしてどんどん探索範囲を広げていくのは冒険している感がある。アビスがかなり広いので、あちらには何があるんだろうと探索するだけでも結構楽しい。第三階層まで行ったけど、実は第一階層もあんまり探索できていないフロアが未だに残ってたりする。

シビアなローグライク

原作だとリコたちはもうラストダイブ前提なので戻ってくる気はさらさらない感じだったけど、主人公は普通の探窟家なのでアビスで遺物を集めてちゃんと街に帰ってこないといけない。なので常に退路を確保しつつ、食料は十分か、武器は足りているかなどを気にしながら潜っていくのはシビアながらも楽しい。特に持ち運べるアイテムの重さには上限があるので、遺物をひたすら回収していたらすぐに動けなくなるということもままある。このあたりもレベルが上っていけばスキルツリーが開放されて自由度が上がり、戦略の幅が広がって気持ちが良い。

リソース管理が大事な直球のローグライク+アクションという感じなので、ダンジョンに潜って素材集めてビルドしていくみたいなのを繰り返すのが好きな人は楽しめそうな気がする。

気になるところ

QTE

特定の大型生物は倒したあとにQTEイベントが発生して、そこで正しく入力できたら撃破。失敗したら敵のHPが多少回復され、再度HPを0にする→QTEの流れを繰り返す。

これが特定のイベント戦だけならいいんだけど、普通に野生で何度も出てくる大型生物を倒すたびに発生するのでめっちゃテンポ悪い。というかなんでQTEなの・・。

上昇負荷

アビスの呪いもきっちり再現されており、ゲーム中では高いところに移動し続けると上昇負荷が発生し、満腹度を減少させたり幻覚や視界を奪ったりと階層に応じたペナルティが与えられる。

リコたちは常に下っていくからよかったけど、プレイヤーは帰るまでが冒険なので確実に上昇負荷を受けることになる。カートリッジはなさそう。

ただ、上昇負荷は発生の予兆が見えるようになっているので、上昇負荷が起きそうになったら一旦止まるか下れば一定時間で正常な状態に戻る。なので、帰りは登る→休憩→登る→休憩を繰り返せば基本的には上昇負荷は起きない。

なので、実際はそこまで上昇負荷を受けることはなく、結果的にテンポが少し悪いかな・・?くらいの立ち位置になっている気がする。これはもしかしたら第三階層以降でもっとエグいのかもしれない。

無限湧き

いくつかの雑魚敵は倒しても結構な速度で敵がリスポーンする。だいたい3秒くらい。なのでその場で留まって食事したりしようとしたらリスポーンした敵に小突かれてキャンセルされがちでだいぶストレスが溜まる。

倒したら素材を落とすので稼げると前向きに捉えられないこともないけど、このゲームは武器に耐久値があるのでずっと相手してたら武器が壊れる方が早くジリ貧になる。その上、ロープや壁を登っている状況でも平然と虫と鳥が無限に湧いて小突いてくる。崖を掴むあたりで小突かれようものならそのまま勢いで落下死。ハンターハンターで試験会場の壁面を下りようとしたら怪鳥にやられたロッククライマー(試験番号86番)の気分になれる。

ストーリーモードというチュートリアル

最初からオリジナルモード(DEEP IN ABYSS)を遊ぶことはできなくて、先に原作ストーリーを追体験するHELLO ABYSSをクリアする必要がある。こちらはゲームのチュートリアルという側面もあるから色々違うところがある。

  • NPCとしてレグがいる(つよい)
  • スキルツリーがない
  • 武器の耐久値がなく壊れない
  • 途中から街に戻れない

レグはポンコツなので「この敵は強敵なのでしゃがんでやりすごそう!」というチュートリアルメッセージが出たあとに躊躇なく敵に殴りかかってた。しかもそのまま倒してしまうという度し難い脳筋っぷりを発揮してくれる。

レグもいるし武器が壊れないのでそれだけでリソースの心配がないし、楽といえば楽なんだけど、スキルツリーもないし育成的な要素がなく単調になりがち。更に、街に戻れないけど遺物はガッツリ出てくるのと、取得時点だと合成できないなど不要となるアイテムが多い。しかも説明がないのでプレイヤーはそれが不要かどうかも判断できない。なので知らないアイテムが出てきても「?」を浮かべながら遊び続けることになる。

そして、普通に遊んで4時間くらいかかった・・

これがチュートリアルという説明すらないので、この時点で離脱した人多いんじゃないのかという気になった。

所感

いわゆるトルネコシレンといった「裸一貫でサバイバル」という遊び方ではなく、きちんと事前に街で整えていきましょう、最悪道中でサバイバルしましょう、くらいの温度感のゲームだと思う。良くも悪くもアビスの恐ろしさが反映されたものになっていて非常に度し難い。

とはいえ文句言いながらずっとアビスに潜っているので割りと中毒性はありそう。憧れは止められねえんだ。

ZenjectからVContainerに移行する際に気をつけること

ニッチすぎる小ネタです。

DIライブラリのリプレースなので基本的にはそんなに手間ではないですが、微妙に思想の違いがあるのでちょっとだけ気をつけようねというお話。

基本的な移行の流れ

  • SceneContextLifetimeScopeに乗り換える
    • Installerのコードを見ながらLifetimeScopeに同様のオブジェクトを登録していく
  • Zenject.InjectVContainer.Inject に乗り換える
    • シーン上のオブジェクトは LifetimeScopeAutoInjectGameObjects に登録していく

DIコンテナとしての役割は同じなので、スクリプトがそのまま差し替わると理想的です。が、全部が全部とはいきません。

ZenjectにあってVContainerにないもの

この辺は、VContainerがそもそもMonoBehaviourへのInjection自体をあまり推奨していない設計思想だからです。ドキュメントに書かれてたりします。

https://vcontainer.hadashikick.jp/ja/resolving/gameobject-injection

ということで、コードに大きく修正を加えないならば上記2点はどうにかシーンから探し出し AutoInjectGameObjects に登録していく必要があります。

ZenjectBindingが使われているか調べる

シーン内をひたすら ZenjectBinding で検索します。Prefabに潜んでいる可能性もあるのでそちらも検索します。がんばる。

ちなみにRiderやReSharper使ってるとクラスからUnityプロジェクト内の参照検索ができるので、ZenjectBindingがアタッチされているPrefabやシーンのGameObjectが洗い出せます。

https://pleiades.io/help/rider/Features_Unity.html#find-usages

シーン内にアタッチされたInject属性のついたコンポーネントを探す

Zenjectはシーン内のInject属性を全検索してInjectionするので追加する分には何も考えなくていいので非常に楽。

その一方で「ヒエラルキー上のどのGameObjectがInjectionの対象なのか」を洗い出したいときに結構手間がかかります。そういう絞り込みができないので・・・。ということで今回は次の方法で調査しました。

  • シーンにLifetimeScopeを置く
  • おもむろにシーン内のSceneContextを削除する
  • 実行したらものすごい数のエラーが出る
    • だいたいInjectionされなくなったことによるnull参照エラー
  • エラーが出たクラスの Zenject.Inject 属性に VContainer.Inject を重ねる
[VContainer.Inject]
[Zenject.Inject]
public void Construct(Foo foo) {}
  • エラーが出たオブジェクトを全部 AutoInjectGameObjects に登録する
  • Zenject.Inject を消す

これを1シーンごとにやっては修正する・・を繰り返しましょう。

所感

インジェクションに限らず、特定のルールに沿うだけで自動で設定してくれるという感じの機能は開発速度を向上させる頼もしい仕組みです。しかし、何が自動化の対象になっているのかが把握、またはロールバックする方法もセットで用意されていないと利用者側はただ把握できないだけになってしまうので、技術選定する際はこの辺気をつけたほうがいいな~と思ったのでした。

追記

SubContainerだったりOptionalInjectionだったりとSignalだったりZenjectにしかない機能はいっぱいあるので、その辺まで含めた場合の乗り換えはコードの見直しからが必要なのでもっと大変です。頑張って・・。

とはいえ、そこまでZenjectに乗っかっているならVContainerに移行する必要はないんじゃないとも思う。

UnityでTDDハンズオンRepositoryを作っている

最近更新したのでちょっと宣伝。

github.com

なにこれ

最近、副業だったりプライベートなどでUnityを使う人でテストに興味ある方を対象にTDDについてお話する活動などをしています。その際に座学としてお話することもあれば、ハンズオン形式で実際に手を動かして書いてもらうということもあります。その際に使うサンプルリポジトリです。 ぜひお手元で考えながら書いてみてください。勉強会の資料などで使っていただいても大丈夫です。

なぜやってるのか

ゲーム開発はソフトウェア開発の中でもかなり複雑性が高いと感じています。そして性質上変更頻度も高い。ゲームごとに作り方が変わる以上これは仕方ないことだと考えています。だからこそより変化に対応できるようにテスタビリティの高いコードになっていてほしいと考えていますがその難易度、そしてそもそものテストコード文化というものがないためにテストコードが書かれていることは少ないです。 まずはUnity界隈でテストコードを書く、という文化を作っていきたい。そんな気持ちで活動を行っています。

TDDという観点で話をすることもあれば、単純にテストコードの書き方、どこの品質を担保すべきかみたいなトリアージの話をすることもあります。ちなみにE2E側の知識は乏しいです。

課題02について

Unityでよくあるボタンを自作しようというテーマで資料を作ってみました。あ~あるある、と思えるようなストーリーにしています。というか実際僕が経験したことを抽象化したものです。

おもしろポイントはこの辺りです。

  • 既存コードを壊さずにどうやって交換していくかの一例がわかる
  • 単純な機能のはずなのにケースが増えて複雑化していく過程がわかる
  • その際にテストがどのような効果を発揮するのかがわかる

一応、1例としてのコードをunitypackageとして含んでいるので参考までにご利用ください。

もし興味があればTwitterなどでもお気軽にお声がけください。

twitter.com

謝辞

ハンズオン資料を作ったら、いつもUnityゲーム開発者ギルドの方に練習台になってもらっています。毎回お付き合いいただきありがとうございます。

unity-game-dev-guild.github.io