クラウドインフラ、Python / Linux の開発メモ、そして日々の技術探求を綴る個人スペースです。極限まで削ぎ落としたミニマムな構成で運用しています。
FastAPI による軽量マイクロサービスと Webhook 自動化
個人用サーバーでタスク自動化や Webhook 連携を行うためのミニマムな設計手法について。
1GB の VPS に極小ブログと API サーバーを構築した記録
Oracle Cloud の 1GB メモリ VPS 上で、NapCatQQ を稼働させながら、常駐メモリほぼゼロの Hugo + PaperMod と FastAPI を共存させたミニマム構成の紹介。
☝️ 「汎用化したい」という衝動と、開発の現実
📌 この記事は Zenn に投稿した内容のアーカイブです。 プログラマーを数年やっていると、おそらく全員が一度は同じことを考える。 「これ、他のプロジェクトでも使える形にしたい」 最初はただ動けばよかったコードが、だんだん気持ち悪く見えてくる。 コピペも増える。責務も混ざる。依存も汚くなる。 すると自然に、 共通化したい 抽象化したい 再利用可能にしたい という欲求が出てくる。 これは悪いことではない。むしろ健全だと思う。 “設計”を意識し始めた証拠だから。 ただ、この感覚はかなり危ない。 一歩間違えると、 簡単に「過剰設計」に転がり始める。 「将来使うかもしれない」 この一言が、 過剰設計の始まりになることはかなり多い。 今回は、自分がゲーム開発をやる中で感じた、 なぜ人は汎用化したくなるのか なぜそれが失敗しやすいのか 実際どう考えるとちょうどいいのか について書いてみる。 汎用化したくなるのは、実はかなり自然なこと 例えば、最初の頃のコードってかなり局所的になる。 if (isBoss) { hpBar.color = Color.red; } みたいな、「今必要だから書いたコード」が大量にある。 でも経験を積むと、 こういうコードを見るだけで“変更コスト”を想像するようになる。 「これ別のボス出たらどうするんだろう」 「色変えるたびに if 増えるの?」 「そもそも UI が敵情報知ってるのおかしくない?」 みたいなことを考え始める。 つまり汎用化欲求の正体って、単なる意識高い設計趣味ではなく、 “変更に弱いコードへの違和感” なんだと思う。 だからある程度コードを書いた人ほど、自然と抽象化に向かう。 実際、汎用化にはかなり強いメリットがある これは間違いない。 1. 「依存」に敏感になる 再利用を意識すると、まずベタ結合が気になり始める。 直接参照 Singleton ベタ依存 MonoBehaviour 神クラス Inspector 配線地獄 みたいなものを避けたくなる。 結果として、 責務分離 Interface 化 データ駆動 疎結合 みたいな方向へ進む。 ...
🧊 【Unity】10万オブジェクトを回転させたらどこがボトルネックになるのか(後編:ISystemで一桁msへ)
📌 この記事は Zenn に投稿した内容のアーカイブです。 はじめに 前回は、Job System + Burst を使って 10万オブジェクトの回転処理(46ms → 3.5ms) まで最適化しました。 ただしその時点でも、フレーム全体としてはまだ重く、 ボトルネックはレンダリング側に残っていました。 なぜJob Systemだけでは不十分だったのか 前回の時点で回転処理自体はかなり軽くなっていましたが、 それでもフレーム全体としては大きな負荷が残っていました。 原因は、描画周りの処理です。 たとえロジック(Job)が高速でも、メインスレッド側では依然として 10万個の MeshRenderer を個別に処理する必要があります。 具体的には以下のような処理です: Culling(可視判定) Bounding Volume(バウンディング更新) RenderQueue(描画順の整理) これらがすべて「オブジェクト単位」で実行されるため、 結果として大きなCPU負荷になっていました。 この問題に対するアプローチが、Entities Graphicsです。 目標: → GameObjectベースのオブジェクトをEntityに変換する 仕組み: → 変換後は、これらの処理を Entities Graphics が内部的に管理し、 BatchRendererGroup を利用して描画処理をまとめて実行します。 その結果: 数万〜数十万単位のオブジェクトでも、 ごく少数のバッチとして扱えるようになります。 ■ 結果 今回は DOTS(Entities + Entities Graphics)に移行した結果: フレーム時間:約120ms → 約9ms 110FPS前後で安定 ほぼ別物レベルまで改善しています。 ■ 比較 指標 改造前(GameObject) 改造後(Pure DOTS) 改善 Batches ~120,000 74 約1486倍削減 SetPass Calls 56 26 約2.1倍改善 Tris / Verts 不安定 安定 描画の一貫性向上 Frame Time 120ms(8FPS) 9ms(110FPS) 約13倍高速化 ■ Profilerを見ると何が起きているか Profilerを確認すると: ...
🧊 【Unity】10万オブジェクトを回転させたらどこがボトルネックになるのか(前編:LateUpdateとJob System)
📌 この記事は Zenn に投稿した内容のアーカイブです。 最近、DOTS(Data-Oriented Tech Stack)が実際どのくらい効果があるのか気になっていたので、 簡単な検証を兼ねて触ってみることにしました。 せっかくなので「大量のオブジェクトを動かした場合にどこがボトルネックになるのか?」も含めて、 段階的に確認していこうと思います。 この記事ではまず、LateUpdateでの回転処理のボトルネックと、 Job Systemによる最適化の効果にフォーカスします。 レンダリング周り(CullingやDrawCall)については、次回以降で触れる予定です。 ■ 検証環境 CPU:i7-12700K GPU:RTX 3070 Unity:URPの新規プロジェクト オブジェクト数:10万(Cube) ■ テスト内容 シンプルに「10万個のCubeを生成して回転させるだけ」です。 BoxColliderは削除 ランダム位置に配置 各オブジェクトにランダムな回転軸 void Start() { var root = new GameObject(“CubeRoot”).transform; for (int i = 0; i < spawnCount; i++) { var go = Instantiate(prefab, Random.insideUnitSphere * 50f, Quaternion.identity, root); transforms.Add(go.transform); } } void LateUpdate() { float dt = Time.deltaTime; for (int i = 0; i < transforms.Count; i++) { transforms[i].Rotate(rotationAxes[i], 100f * dt); } } ...
🙌 なぜ Unity は C# を選び、Unreal は選ばなかったのかについての個人の考察
📌 この記事は Zenn に投稿した内容のアーカイブです。 はじめに ゲームエンジンの言語の話になると、よくこんな対比が出てきます。 Unity は C#。 Unreal は C++ と Blueprint。 この違い、ただの好みではありません。 エンジンの設計思想そのものに関わっています。 C# が優れているとか、C++ が古いとか、そういう単純な話ではない。 両者はそもそも目指している開発体験が違うのです。 Unity が辿った言語統一の歴史 今でこそ「Unity といえば C#」という印象がありますが、最初からそうだったわけではありません。 初期の Unity では、開発者のバックグラウンドに合わせて複数の言語を選択できるのが特徴でした。 具体的には次の3つです。 C# UnityScript (JavaScript 風の独自言語) Boo (Python 風の言語) 当時の Unity は「スクリプト言語の自由度」を売りの一つにしており、Web 開発者は UnityScript、Python 系に慣れている人は Boo、という具合に選べるようになっていました。 しかし、この方針は長くは続きませんでした。 Unity 2017 頃から段階的に非推奨となり、 Unity 2019.1 を最後に UnityScript と Boo は完全に削除 されます。 結果として、Unity のスクリプト言語は C# のみ に統一されました。 参考 https://discussions.unity.com/t/which-release-removed-support-unityscript-and-boo/1624299 なぜこうなったのか。理由はいくつかあります。 まず、複数言語の維持コストです。 エンジン側はコンパイラ、ツールチェーン、デバッグ環境などをすべてサポートし続ける必要があります。 さらに重要なのは、UnityScript と Boo の実態です。 これらは見た目こそ別言語でしたが、内部では Mono 上で動作するスクリプトでした。 ...
🎉 Git を「完全に理解」するためのデータ構造の話
📌 この記事は Zenn に投稿した内容のアーカイブです。 はじめに Git を使っていて、こんな感覚になったことはありませんか? コマンドは打てるけど、何が起きているか分からない merge と rebase の違いを、説明しろと言われると詰まる conflict が出ると、なぜ衝突したのか理解できない 多くの Git 解説記事は、 「何を打つか」 は丁寧に教えてくれますが、 「なぜそうなるか」 までは踏み込んでくれません。 その結果、 なんとなく使えているが、仕組みはよく分からない という状態に陥りがちです。 この記事では、コマンドの説明はほぼ行いません。 代わりに、Git の内部構造をデータ構造として捉え直す ことで、 「あ、そういうことだったのか」 と腑に落ちる理解を目指します。 少しだけ グラフ理論 と ポインタの概念(C 言語) の素養があると、 かなりスムーズに理解できると思います。 Git の正体:木構造ではなく DAG(有向非巡回グラフ) 多くの人は、Git の履歴を「木構造」としてイメージしています。 しかし、これは正確ではありません。 Git の本質は 有向非巡回グラフです。 Commit は「ノード」 すべての commit は、グラフ上の ノード です。 各 commit は、 ファイルのスナップショット 親 commit への参照(1 個または 2 個) を持っています。 親が 2 個になる瞬間 = merge 通常の commit は親が 1 つですが、 merge commit は 親を 2 つ 持ちます。 ...
☝️ デバッグ UI を書かずに Unity のデバッグ環境を成立させる設計と実装
📌 この記事は Zenn に投稿した内容のアーカイブです。 はじめに Unity で開発していると、 実行中にパラメータを触りながら挙動を確認したい という場面は、ほぼ毎日のように出てきます。 最初のうちは、Unity 標準の仕組みを使って 簡単な Runtime Debug UI を用意すれば十分でした。 ただ、プロジェクトが進み、 デバッグ項目が増える 調整対象が増える 複数人で同時に触る という状況になるにつれ、 「その場しのぎ」で作ったデバッグ UI が、確実に足を引っ張る ようになってきます。 この段階で欲しくなったのが、 壊れにくく、拡張しやすく、 プロジェクトと一緒に「育てていける」デバッグ基盤 でした。 この記事では、 そのために設計した 自作 Runtime Debug システム について、 設計意図と実装の要点 を中心にまとめます。 何が問題だったのか 問題の本質は、「UI をどう実装するか」 ではありませんでした。 本当に困っていたのは、 Debug 項目の追加・削除が面倒 どこに何のデバッグ設定があるのか分からない 不要になった項目が整理されず、蓄積していく という 運用面の破綻 です。 特に後半になると、 「デバッグ環境のせいで、デバッグそのものがやりにくい」 という、本末転倒な状態になりがちでした。 目指したゴール 今回の設計で目指したゴールは、かなり明確です。 UI を書かずに Debug 項目を追加できる 構造が自然に整理され続ける 無効化・除去が簡単 プロジェクト規模が大きくなっても破綻しない つまり、 「運用しても壊れない設計」 を最優先にしました。 全体構成 全体の流れは、次のようになります。 起動 ↓ RuntimeInitializeOnLoadMethod ↓ DebugManager 自動生成 ↓ DebugOption 自動登録 ↓ Reflection による項目収集 ↓ UI 自動生成 & バインディング ここで重視したのは、 ...