Movatterモバイル変換


[0]ホーム

URL:


KAYAC Engineers' Blog

CIVIC TECH FORUM2025に協賛させていただきました!

面白法人グループAdvent Calendar2025の17日目を担当しますbobです!現在はちいき資本主義事業部のフロントエンドエンジニアをしていまして、スマウトという移住を考えている方と移住してきて欲しい地域とのマッチングプラットフォームの開発を行っています。

www.kayac.com

smout.jp

前日は、commojunさんによる「ゴリラが派手に破壊するためのアルゴリズム 〜よく知られたアルゴリズムをゲーム開発へ応用する時の考え方〜」でした。自分は大学院の時に機械学習を勉強していて、k-means法は機械学習でよく出てくる手法として馴染み深かったので、Unityのオブジェクトをクラスタリングする方法にも使えるというのは新鮮でした!Unityも触ってみたくなりますね!

さてさて気づいたらもう年の瀬ですね、あっという間に1年が終わってしまってびっくりしてしまいます。

そんなあっという間に過ぎてしまった2025年でしたが、今年の5月に開催されましたCIVIC TECH FORUM2025(以下CTF)にプラチナスポンサーとして協賛させていただきました!

2025.civictechforum.jp

今回の記事では、CTFでのお話とスポンサーとして参加させていただいた感想を書かせていただきます。

シビックテックとは?

シビックテックとは、市民の方々が住んでいる地域や関わりのある地域をテクノロジーの力を駆使して、課題を解決したりより街をよくしようとする取り組みのことをさします。

最近の例ですと、コロナ禍に非営利団代のCode for Japanが新型コロナウイルス感染症対策のサイトを1週間で構築し公開したことが話題になりましたね。

このサイトはGitHubにオープンソースとして公開され、他の自治体でも簡単に構築が可能となり必要な情報をすぐに提供できるような仕組みが提供されました。

他にも、その地域ごとの情報をオープンデータとして提供するような仕組みであったり、シビックテックは様々な形で世の中に普及されてきました。

CTFとは?

CTFとは、シビックテック領域で活躍されている方やシビックテックに興味のある方が集まって、情報共有や議論を行うためのイベントで2015年から開催されてきました。

エンジニアだけではなくデザイナーさんや学生さん、ITとは無関係なお仕事をされている方まで本当に幅広い方が参加されます。多様なバックグラウンドを持っている方々が集まり、様々な角度からシビックテックについて討論されるのがとても新鮮で学びになります。

私自身も、過去に学生時代に登壇させていただいたりととても思い出深いイベントで、そこに協賛させていただく運びになってとても感慨深い気持ちです!

カヤックでも、カマコンという鎌倉を盛り上げるための団体の一員として活動をしています。鎌倉で活動されている方と交流でき、鎌倉の知らない魅力を知ることができるとても素敵な会になっています。

kamacon.com

CTF2025に参加して

CTF2025は、大阪にあるさくらインターネットさんのblooming campで開催されました。本当に綺麗で素敵な会場でした!

今回のCTFでは、各テーマごとにシビックテック界隈で活躍されている方々がパネルディスカッションを行うような形式となっています。

今回は「準公共とCivicTech」というテーマで、パネルディスカッションが構成されています。

どのパネルディスカッションもすごく興味深くて、勉強になる面がたくさんありました。

この記事では、各パネルディスカッションに関する感想は書いていくと非常に長くなってしまうので、参加させていただいて総合的な感想や個人的にシビックテックについて感じたことを書かせていただきます。

シビックテックはAIの進化で次のステップに、テクノロジーの本当の民主化

ここ2年ほどで、AIは急激な成長を遂げました。私自身エンジニアですが、業務でもAIによる補助はもう生産性の向上という観点でも必須レベルになってきました。

自然言語でアプリケーションを作れてしまうというのは本当に革命的で、今までのシビックテックはどうしても「課題を解決したい人」が「エンジニア」と一緒に解決方法を考えるという構造になりがちでしたが、「課題を解決したい人」が直接プロトタイプを作れてしまうという段階が到来したなと思います。

もちろん、まだ細かいできる・できないの判断はエンジニアの知識が必要でしたり、本格的にアプリケーションを作るのにはエンジニアの力は必要ですが、仮説を検証したり動くものを簡単にでもすぐにつくれるというのは大きな革命だと思います。

また、少し前のシビックテックではオープンデータの収集や形式化の話題が多かったように記憶していますが、今回のCTFではその話よりも街と人がどのように繋がっていくかという話題が多かったように感じました。

オープンデータ化が進んできた今、それを活かしたアプリケーションの作成や価値提供がより盛んになるのではないかなと思います。

鎌倉の歩行空間ネットワークを可視化してみた!

せっかくのアドベントカレンダーなので、鎌倉の歩行空間ネットワークデータOpenStreetMapを用いて可視化したwebサイトをAIの力だけでつくってみました!

下のリンクからご覧ください。

sonedayusuke.github.io

このような感じで、鎌倉駅周辺の歩道に関する情報をインタラクティブに確認できるツールを1時間ほどで作ってみました。

作り方はシンプルで、GoogleのGeminiを用いてcanvasモードを使用し、「鎌倉の歩行空間ネットワークデータを用いて、OpenStreetMap上に表示できるようにして」とお願いしました。細かい調整も行いましたが、合計5回ぐらいの指示を出してこのクオリティーになりました。

鎌倉の歩行空間ネットワークデータの情報については以下に詳細とデータが提供されています。

www.city.kamakura.kanagawa.jp

この地図を見ていただくと、鎌倉は歩車分離がない道がいくつかあり、また若宮大路という大きな道路には段差が多いことがわかります。鎌倉は観光地な一方古都でもありますので意外と道幅が狭かったり歩道がない箇所もあります。お子様連れの方や足が不自由な方にとって役立つ地図アプリになったのではないかなと思います。

ものの1時間ぐらいで、これぐらいのサイトをAIに指示をするだけで作れてしまうのは画期的ですね!

今回は鎌倉だけですが、同じような手法を使えば他の場所でも同様なことができます。

どのようなオープンデータがあるのかを見るだけでもかなり楽しいですね!

まとめ

コロナ禍以降久しぶりのリアル開催となりましたCTF2025に今回参加させていただきまして、学生時代に大変お世話になった方々にもお会いでき、とても充実した1日を過ごさせていただきました!この度は誠にありがとうございました!

私個人の感想ですが、面白法人カヤックはゼブラ企業としての期待感も高く持っていただけていることを感じるきっかけとなりました。ちいき資本主義事業部として様々なちいきを盛り上げられるように努めてまいりたいです!

AIの進化によって、テクノロジーがどのように非エンジニアの方にとってより身近なものになるかとても楽しみです!

明日はwappyさんによる「Mastra の Agent Networks が解決するコンテキスト汚染とその仕組み」です!

ゴリラが派手に破壊するためのアルゴリズム 〜よく知られたアルゴリズムをゲーム開発へ応用する時の考え方〜

本記事は面白法人グループ Advent Calendar 2025の16日目の記事です。

こんにちは

どうも、ゴリラです。もとい@commojunです。今回はUnityを使って、こちらのゴリラさんが活躍するゲームを作ってみました。動画を御覧ください。

ゲーム動画

ゲームの特徴

これは、ゴリラさんが画面奥方向へ疾走するタイプのランゲームです。このゲームの特徴には、以下のようなものがあります。

  • 自動的に走行するゴリラさんを左右に操作しながら、道中にあるブロックでできた建物を破壊する
  • 破壊したブロックの破片は、ゴール上空に飛んでいき、大きな塊になる
  • ゴールに到着したゴリラさんは大きくジャンプし、大きな塊に最後の一撃!を加える
  • 最後の一撃!ですべての破片が吹っ飛び、スコアボードに着地し、その位置によってスコアが集計される

特にこだわったのは、やはり最後の一撃!ですね。道中の建物を壊せば壊すほど、最後の塊がより大きくなり、ゴリラさんの破壊演出がより派手になるという仕組みになっています。

派手な破壊

フレームレート落ち問題

ゴリラ界ではなかなか好評な演出でしたが、一つ問題がありました。それは、破片が増えすぎると処理が重くなり、フレームレートが落ちてしまう問題です。

破片が増えれば増えるほど、物理運動を計算しなければいけないオブジェクトの数が増えるのはもちろんのこと、破片同士の衝突判定を計算しなければならない数もn2オーダーで増えてしまいます(私の調査不足の可能性もありますが、レイヤーの設定を調整して破片同士の衝突を無効にしても衝突判定の計算自体は減らすことができませんでした)。

このゲームはスマートフォンでプレイすることを想定したものであるため、ミドル〜ロースペックのスマートフォンでもある程度サクサクと動作する必要があります。ですが、何も考えずに実装するとこの通り、実機の映像では、フレームレートが落ちて画面がカクカクになってしまいます。

スマートフォン実機での映像

これでは、せっかくこだわった破壊演出の気持ちよさが台無しです。何か軽量化のための対策をする必要があります。

クラスタリングする

そこで今回取った作戦は、近くにある破片同士をある程度グループにまとめるクラスタリングを行い、物理エンジンの計算をさせるオブジェクトの個数を削減させるという方法です。例えば、オブジェクトの数が500個の場合と200個の場合で比較するとこうなります。

  • 500個の場合
    • 物理演算: 500個/フレーム
    • 衝突判定: 250,000ペア/フレーム
  • 200個の場合
    • 物理演算: 200個/フレーム (60%削減)
    • 衝突判定: 40,000ペア/フレーム (84%削減)

このように、計算対象とするオブジェクト数を削減することによる効果は大きく、一定の上限を設定可能な方法でクラスタリングできれば、ある程度の性能が担保できると言えます。

k-meansアルゴリズム

バラバラのオブジェクト同士を近隣の者同士でまとめるクラスタリング手法といえば…k-meansというアルゴリズムを思い浮かべる方も多いかと思います。アルゴリズムの概要をざっくり説明すると以下のような感じです。

  1. k個の初期centroid(クラスタ中心)をランダムに選択
  2. 各データ点を最も近いcentroidに割り当て
  3. 各クラスタのcentroidを、そのクラスタに属する点の平均位置として再計算
  4. centroidの変化が閾値以下になるまで2-3を繰り返す(収束まで)

k-meansアルゴリズム

このアルゴリズムを利用すれば、多数の破片を効率的にまとめ上げ、物理シミュレーションさせるオブジェクトの個数を最大k個に抑えることができそうです。

それでは実際に実装してみようと思ったのですが、私の直感が「待てよ」と訴えかけてきました。

内なるゴリラの声を聴く

ここでいったん立ち止まり、私の内なるゴリラが訴えかけてくる直感に耳を傾けることにしました。

アルゴリズムのステップを教科書通りにすべて実装する必要はないのではないか?

私は、このゲーム特有の前提事項や、演出上「これで十分」とできる品質のラインを鑑みると、k-meansアルゴリズムのステップのうち、かなりの部分が必要ないことに気が付きました。

centroid(クラスタ中心)をランダムに選択する必要がない

まず、クラスタの中心であるcentroidをランダムに選択する必要がないことに気が付きました。なぜなら、ステージの道中に破壊した建物の破片はランダムに飛び散り、ゴール上空で塊を形成します。破片が塊のどの位置に付着するかは完全にランダムです。つまり、塊に到着した先着k個の破片をそのままcentroidとするだけで、centroidをランダム選択することとほぼ同義の手続きを達成できるのです。これでk-meansアルゴリズムのステップ1が不要となりました。

centroidの位置を再計算する必要がない

本来のk-meansアルゴリズムでは、centroidの位置を何回も再計算する手続きがありますが、これも不要であると気が付きました。そもそもこのアルゴリズムは、データマイニングや機械学習などの分野で用いられているものであり、各ノードを意味のあるクラスタに分類することと、centroidがそのクラスタの特性を代表する正確な重心点であることへの関心が高い場合に有用なものです。翻ってこのゲームにおいては、クラスタ分類にもcentroidにも意味は求められておらず、なんとなく近所で固まってれば十分であるため、ステップ3、ステップ4のcentroid再計算の手続きは不要となります。

シンプルなクラスタリングアルゴリズム

すると、本ゲームにおける、破片のクラスタリングアルゴリズムはかなりシンプルになります。

  1. 先着k個の破片をcentroidとする
  2. k+1番目以降に到着した破片は、最も距離が近いcentroidの子要素にする

これだけで、必要なクラスタリングが完了します。

コライダーの統合

無事にクラスタを形成し、物理計算するオブジェクトの個数を削減できたのですが、これだけでは性能の改善には至りませんでした。原因は、クラスタリングしてもなお、そのクラスタに属する破片一つ一つが個別にコライダー(当たり判定を行う箱)を持っていたためでした。そのため、衝突判定を行うペア数の削減には至っていなかったのです。この問題を解決するためには、おのおのが持つコライダーを、クラスタを内包する大きなコライダーへと統合する必要がありました。

コライダーの統合自体は、UnityのBoundsクラスに用意されたEncapsulate()関数を応用すれば比較的簡単に実装できます。

privatevoid Integrate(Crust parent, Crust child){    BoxCollider parentCollider= parent.rb.GetComponent<BoxCollider>();    Collider childCollider= child.rb.GetComponent<Collider>();// バウンディングボックスを統合    Bounds parentBounds= parentCollider.bounds;    Bounds childBounds= childCollider.bounds;    parentBounds.Encapsulate(childBounds);// 親のコライダーを拡張    parentCollider.size=        parentCollider.transform.InverseTransformVector(parentBounds.size);    parentCollider.center=        parentCollider.transform.InverseTransformPoint(parentBounds.center);// 子のコライダーを無効化    childCollider.enabled=false;}

しかしこの時、親要素となるオブジェクトが中途半端な向きに回転していると、期待した結果が得られないことがわかりました。問題を特定して、親要素が回転していても期待した結果を得るためにはかなり深い理解と複雑な実装が必要になりそうであったため、親要素の回転をリセットしてからこのロジックを適用することにしました。割り切りも重要です。

親となるブロックの向きがリセットされている

これらの工夫を組み合わせることで、破片同士を効率的にクラスタリングし、パフォーマンスの向上に寄与することができました。

クラスタリングされている様子

比較

クラスタリングの適用前と後の比較動画を見てみましょう。

before ← → after

ウホッ!これは全然違いますね!物理エンジンの計算対象とするオブジェクト数の削減により、目に見えて爽快感が向上していることが感じ取れます。

さいごに

いかがでしたか?ゴリラさんもこの通り、ニッコリですね。

本記事では、ゴリラさんが疾走するランゲームで、多くのオブジェクトを効率的に破壊するためのクラスタリング手法について解説しました。k-meansアルゴリズムのように、教科書に載っているような様々なアルゴリズムの知識を引き出しに多く持っておくことは、エンジニアとして問題解決の手札を増やすことができて有用だと思います。その一方で、世の中で知られているアルゴリズムを今取り組んでいる問題にそのまま適用するのではなく、その問題のバックグラウンドや、どこまでの水準で問題を解決すれば十分なのかを同時に鑑みることも重要だと思います。その上で、必要に応じて必要な分だけアルゴリラズムのエッセンスを取り入れ、応用できるエンジニアが実務上で信頼されるのではないかと思います。ゴリラさんが教えてくれました。

カヤックではゲームのパフォーマンスチューニングを楽しみながら実装できるエンジニアを募集しています。

人気記事10選
検索
Powered by はてなブログ

引用をストックしました

引用するにはまずログインしてください

引用をストックできませんでした。再度お試しください

限定公開記事のため引用できません。

読者です読者をやめる読者になる読者になる

[8]ページ先頭

©2009-2025 Movatter.jp