前回、第50回では、PUZFLOに導入したTick処理の検証を行いました。
30FPSと20FPSで同じ生産ラインを動かし、
約2分10秒、3,767件のイベントが完全一致。
これによって、画面のFPSが低下しても、
生産結果が変わりにくい仕組みを作ることができました。
しかし、ここで新たな問題が発生しました。
「ゲーム終盤になると、FPSが大きく低下する」という問題です。
生産開始直後は60FPSで動いていたのに、約10秒後には40FPS前後まで低下。
さらに、ゲームを進めると、前回追加した過負荷時の自動Pauseが発生することもありました。
せっかくTick処理で生産結果を安定させたのに、今度はゲーム自体が重くなってしまったわけです。
そこで今回は、ChatGPTとCodexを使って、FPSが低下する原因を調査し、
ゲームの動きを変えずに処理を軽くする方法を考えていきます。
ゲーム開始直後は60FPSなのに、途中から重くなる

今回の問題で特徴的だったのが、
生産を開始してから少し時間が経つとFPSが低下することです。
例えば、ゲーム終盤の大きな工場では、
生産開始直後:60FPS前後
↓
約10秒後:40FPS前後
という変化がありました。
最初から40FPSであれば、
単純に設備や背景の表示が重い可能性も考えられます。
しかし、今回は最初のうちは正常に動いています。
それなのに、時間が経つほど重くなる。
そこでChatGPTへ相談すると、生産中に何かが増えて、
処理の負担が大きくなっている可能性がある。という話になりました。
確かに、PUZFLOでは生産を開始すると、投入機から次々とワークが供給されます。
工場が大きくなるほど、複数のラインが同時に稼働します。
つまり、時間が経つほど、工場内を流れるワークの数が増えることがあります。
ここが今回の原因を探るヒントになりました。
まずはFPSが下がる原因を調査する
以前、第37回と第38回でもFPS低下の調査を行いました。
そのときに学んだのが、「重いからといって、いきなり最適化しない」ということです。
原因が分からないままコードを変更すると、思ったほど軽くならなかったり、
別の不具合を発生させたりする可能性があります。
そこで今回も、まずは状況を確認することにしました。
特に注目したのは、次の情報です。
| 確認する項目 | 知りたいこと |
|---|---|
| FPS | いつから動作が重くなるか |
| ワーク数 | 生産中にどれくらい増えるか |
| 搬送管理中のワーク数 | 不要なワークが残っていないか |
| 切断後のワーク数 | 切断機による増加の影響 |
| Tick実行回数 | FPS低下によって追加処理が増えていないか |
例えば、ワーク数が増えるほどFPSが低下していれば、ワークに関係する処理が疑わしくなります。
反対に、画面上のワーク数が増えていないのに、内部で管理している数だけ増えているなら、
出荷済みのワークが正しく削除されていない可能性もあります。
こうした点を確認しながら、原因を絞り込んでいきます。
原因は「ワーク同士の間隔を確認する処理」だった
ChatGPTとCodexを使って調査を進めた結果、特に負荷が大きくなっていたのが、
Minimum Spacing(ミニマムスペーシング)という処理でした。
名前だけ聞くと難しそうですが、役割はシンプルです。
コンベア上でワーク同士が重ならないように、一定の間隔を保つための処理です。
PUZFLOでは、コンベア上に複数のワークが流れます。
前のワークが停止していたら、後ろのワークもその手前で止まる必要があります。
また、加工機やストッパの前で渋滞が発生した場合も、
ワーク同士が重ならないようにする必要があります。
これはPUZFLOにとって欠かせない仕組みです。
しかし、この処理が、工場の規模が大きくなったときの負担になっていました。
なぜワークが増えると重くなるのか?
問題は、ワーク同士の距離を確認する方法にありました。
以前の仕組みでは、ワークが移動できる距離を確認するときに、
ほかのワークを広く調べる処理がありました。
例えば、工場内にワークが10個あるとします。
1個のワークについて、ほかのワークとの関係を確認する。
それを10個分繰り返す。という形です。
このような処理では、ワーク数が増えるほど、
確認する組み合わせが急激に増える場合があります。
単純化すると、次のようなイメージです。
| ワーク数 | 確認する組み合わせの規模(概算) |
|---|---|
| 10個 | 約100 |
| 50個 | 約2,500 |
| 100個 | 約10,000 |
| 200個 | 約40,000 |
※実際の処理回数を示すものではなく、全件比較に近い処理が増えるイメージです。
ワーク数が2倍になったとき、確認処理が単純に2倍で済むとは限りません。
場合によっては、約4倍に増えることもあります。
これなら、ゲーム開始直後は軽くても、
ワーク数が増えたところから急に重くなる理由が理解できます。
ワークが増える → 間隔確認が増える → CPUの負担が大きくなる。
今回のFPS低下は、この仕組みが大きく関係していました。
Tick処理によって負荷が目立ちやすくなった可能性もある

もう一つ気になったのが、前回導入したTick処理との関係です。
Tick処理では、画面のFPSが下がっても、できるだけ1秒間に60回の生産処理を維持します。
例えば、
60FPSなら、画面1回の更新で約1Tick。
30FPSなら、画面1回の更新で約2Tick。
20FPSなら、画面1回の更新で約3Tick。
という形です。
つまり、FPSが低下したからといって、
生産処理の回数も同じように減るわけではありません。
これは生産結果を安定させるためには重要です。
しかし、1Tickあたりの処理が重ければ、FPSが低下した際に
追加のTick処理を実行することも負担になります。
そのため、
ワーク数が増える
↓
間隔確認の負荷が増える
↓
FPSが低下する
↓
1画面更新あたりのTick処理が増える
という状況になる可能性があります。
Tick処理そのものが悪いわけではありません。
Tick処理を安定して動かすためにも、
1回あたりの生産処理を軽くする必要があるということです。
ゲーム終盤では自動Pauseまで発生
実際にゲーム終盤まで進めると、FPSが低下するだけでなく、
過負荷による自動Pauseが発生することもありました。
この自動Pauseは、第50回で追加した安全機能です。
PCの処理が大きく遅れた場合、無理に大量のTickを実行せず、生産を一時停止します。
そのため、今回の自動Pause自体は、設定した安全機能が働いた結果です。
ただし、プレイヤーからすれば、ゲーム中に何度も停止するのは困ります。
PUZFLOは、30秒間の安定稼働など、生産ラインの動きを確認するゲームです。
そこで頻繁に一時停止してしまうと、快適に遊べません。
つまり、Tick処理によって生産結果を安定させるだけでなく、
そのTick処理を無理なく実行できる性能も必要になってきたわけです。
改善方針は「全部調べる」から「必要な場所だけ調べる」へ

Minimum Spacingの負荷を減らすには、
どうすればいいのでしょうか。
ChatGPTと相談して考えたのが、

「本当に関係するワークだけを確認する」
という方法です。
例えば、コンベア上を流れるワークを考えます。
自分のすぐ前にワークがあるなら、そのワークとの距離は重要です。
でも、工場の反対側にいるワークまで毎回確認する必要はありません。
そこで、
- 現在いる場所
- 次に進む場所
- その周辺
- 分岐や合流で関係する場所
など、必要な範囲に絞ってワークを確認する方法を検討しました。
こうすれば、工場全体のワークを毎回調べるよりも、
確認する対象を減らせる可能性があります。
イメージとしては、
これまで:工場全体のワークを広く確認する
改善後:移動に関係する周辺のワークを中心に確認する
という違いです。
重要なのは、ワーク同士の間隔を守るルールを変更するのではなく、
確認する相手の探し方を効率化することです。
「前のワークだけ調べる」ではダメなの?
最初は、「すぐ前にいるワークだけ確認すればいいのでは?」とも思いました。
しかし、PUZFLOには複雑なラインがあります。
例えば、分岐や合流です。
別々の方向からワークが進入する場合、
単純に同じコンベア上の前方だけを確認すればよいとは限りません。
さらに、ストッパや加工機の入口では、
停止中のワークとの関係も考える必要があります。
そのため、今回はいきなり判定方法そのものを変えるのではなく、
既存の間隔判定をできるだけ維持しながら、確認対象を減らすという方針にしました。
これまで正常に動いていたラインを壊さないためにも、慎重に進めたいところです。
最適化で一番怖いのは「動きが変わること」
今回の改善で最も注意したいのが、ここです。
仮にFPSが40から60に改善したとしても、
といった問題が発生したら、改善成功とは言えません。
特にPUZFLOでは、前回Tick処理を導入したばかりです。
ようやく、「同じ条件なら同じ生産結果になる」
という方向へ進めたところで、その再現性を壊したくありません。
そこでCodexへは、
「ワークの搬送ルールは変更せず、無駄な計算を減らす」
という方針で依頼します。
速度や間隔、設備能力などの仕様は維持しながら、内部の計算方法だけを改善することを目指します。
FPSだけでなく、生産結果も比較する
今回も、単純にFPSが上がったかどうかだけでは判断しません。
確認したいのは、処理が軽くなっても、
同じ生産結果が維持されているか?ということです。
そのため、前回のTick処理で使用したTraceも活用できます。
例えば、改善前と改善後で、
| 確認項目 | 比較する内容 |
|---|---|
| FPS | 生産開始直後と10秒後の変化 |
| CPU負荷 | 生産処理が軽くなっているか |
| ワーク数 | 同じ条件で増減が一致するか |
| 出荷数 | 同じ数のワークが出荷されるか |
| NG判定 | 成功・失敗が変わらないか |
| Trace | Tick番号やイベント順が一致するか |
| 自動Pause | 過負荷による停止が減るか |
といった項目を確認します。
特にゲーム終盤のような大規模な工場では、短時間のテストだけでは不十分です。
生産開始直後だけでなく、10秒後、20秒後、30秒後と確認していく必要があります。
最初だけ60FPSではなく、生産中も安定して動くこと。
これが今回の目標です。
今回もChatGPTとCodexを使って改善する

今回のような問題は、コードが分からない自分にとって、かなり難しい内容です。
正直、ゲームを作り始めたころには、こうした言葉を使って
開発することになるとは思っていませんでした。
それでも、やること自体は以前と変わりません。
まず、自分がゲームを遊んで問題を見つけます。
「生産開始から10秒くらいで重くなる」
「ゲーム終盤では自動Pauseが発生する」
という状況をChatGPTへ伝えます。
そこから、考えられる原因を整理してもらい、
Codexへ調査を依頼します。
そして、実際のゲームで確認する。
今回はさらに、FPSだけでなく、
Tick処理やTraceの結果も確認する必要があります。
AIにすべて任せて終わりではなく、改善した結果が本当に正しいのかを
自分で確かめることが大切だと感じています。
最適化の結果、常時60FPSを維持できるようになった!
今回の改善によって、FPSが大幅に改善しました!
これまでは、ゲーム終盤の大規模な工場で生産を開始すると、
生産開始直後:60FPS前後
↓
約10秒後:40FPS前後まで低下
という状態でした。
さらに、出荷場24では処理が追いつかず、
過負荷による自動Pauseが発生することもありました。
しかし、今回のMinimum Spacingの最適化によって、
状況が大きく変わりました。
ワークが大量に流れる大規模な工場でも、
常時60FPSを維持できるようになったのです。
特に大きかったのは、ワーク同士の間隔を確認する際に、
無関係なワークまで調べていた処理を減らせたことです。
これによって、ワーク数が増えてもCPUへの負担を抑えられるようになりました。
しかも、今回目指していたのは、
単純にFPSを上げることだけではありません。
ワーク同士の間隔や搬送ルールを維持したまま、処理を軽くすることです。
見た目にはほとんど変化がありませんが、ゲームの動作はかなり快適になりました。
第49回・第50回で取り組んだTick処理によって、生産結果の再現性を改善。
そして今回、第51回ではMinimum Spacingの最適化によって、大規模な工場でも60FPSを維持。
ようやく、安定性と快適さの両方が整ってきました。
最初は「ワークを動かすだけ」でも苦労していたPUZFLOですが、
今では大量の設備とワークが同時に動く工場を、
安定して稼働させられるところまで進みました。
「正しく動く」だけでなく、「快適に動く」ゲームへ。
Steamでの販売に向けて、また一つ大きな改善ができたと思います。
まとめ|無駄な計算を減らして、常時60FPSを実現!

今回、第51回では、ゲーム終盤で発生していたFPS低下の原因調査と最適化に取り組みました。
問題になっていたのは、ワーク同士の間隔を確認するMinimum Spacingの処理です。
工場が大きくなり、ワーク数が増えるほど、間隔を確認するための計算も増えていました。
その結果、生産開始直後は60FPSで動いていたのに、約10秒後には40FPS前後まで低下。
さらに、ゲーム終盤では過負荷による自動Pauseが発生することもありました。
そこで今回は、
「ゲームの動きは変えずに、無駄な計算だけを減らす」
という方針で最適化を進めました。
具体的には、工場内のワークを広く確認していた処理を見直し、
移動に関係する周辺のワークを中心に確認する仕組みへ改善しました。
そして、その結果は予想以上でした。
これまで40FPS前後まで低下していた大規模な工場でも、
常時60FPSを維持できるようになったのです!
しかも今回重要だったのは、単純にFPSを上げることだけではありません。
といった、ゲームの基本ルールを維持しながら処理を軽くすることを目指しました。
第49回・第50回では、Tick処理によって生産結果の再現性を改善。
そして今回、第51回ではMinimum Spacingの最適化によって、
大規模な工場でも快適に動く性能を実現できました。
「軽く動くけど結果が変わるゲーム」ではなく、
「軽く動いて、同じ結果を再現できるゲーム」へ。
派手な新設備を追加したわけではありませんが、
PUZFLOの完成度を高めるうえで、かなり大きな改善になったと思います。
Steamでの販売に向けて、ゲームの安定性と快適さの両方が少しずつ整ってきました。
これからも、プレイヤーが安心してライン設計を楽しめるPUZFLOを目指して、開発を進めていきます。
次回は「組立機」を追加してゲーム性を広げる
今回のFPS改善によって、ゲーム終盤の大規模な工場でも、
常時60FPSを維持できるようになりました。
これで、動作の安定性については大きく前進できたと思います。
そこで次回は、久しぶりに新しい設備の追加へ戻ります。
追加するのは、以前から実装を考えていた「組立機」です。
これまでのPUZFLOでは、基本的に1個のワークを加工して、出荷する流れが中心でした。
しかし、実際の工場では、複数の部品を組み合わせて1つの製品を作る工程もあります。
そこで、PUZFLOにも、
「複数のワークを組み合わせて、1つの製品を作る」
という新しい仕組みを追加していきます。
例えば、2つのワークを組み立てる場合、単に加工するだけでなく、
必要な部品をどのように集めて、組立機へ供給するかも考える必要があります。
これによって、今までとは違うライン設計ができそうです。
ただし、組立機を追加すれば、それだけゲームが面白くなるとは限りません。
組立機を使うメリットと、使わないメリットの両方がある設備にしたいところです。
次回、第52回では、ChatGPTとCodexを使って組立機の仕様を考えながら、実装に挑戦していきます。
「ワークを加工して流すゲーム」から「部品を組み合わせて製品を作るゲーム」へ。
PUZFLOの生産ラインを、さらに工場らしく進化させていきます。




コメント