Open
Conversation
tknkaa
reviewed
Mar 15, 2026
Contributor
There was a problem hiding this comment.
変更内容の確認
追加された機能の設計自体はよくできています。decideCollisionOutcome.ts の脱出速度・衝突角・質量比を組み合わせた判定ロジック、mergePlanets.ts の運動量保存に基づく合体計算、そして planetRegistry に velocity を追加した拡張はいずれも適切です。
バグの原因
TypeError: Cannot read properties of undefined (reading 'velocity') は、以下の競合状態(race condition)によって発生しています。
- 惑星AとBが衝突すると、物理エンジンが両方の
onCollideコールバックをほぼ同時に発火します - 先に処理された側(例:惑星A)の
onCollideがonMergeを呼び出し、handleMerge内でplanetRegistry.current.delete(idA)とplanetRegistry.current.delete(idB)を同期的に実行します(index.tsx175〜176行目) - しかし
setPlanets()は非同期のため、両惑星のPlanetMeshコンポーネントはまだマウントされたままです - 直後に惑星B側の
onCollideが発火しますが、このときplanetRegistry.current.get(otherId)はすでに削除済みのためundefinedを返します - その
undefinedに対して.velocityを読もうとしてクラッシュします
PlanetMesh.tsx の72〜73行目にある if (!myPlanet || !otherPlanet) return のガードは、planetRegistry.current.has() が通過した直後に削除が起きるケースを防げないため、このチェックをすり抜けてしまいます。
修正案
index.tsx の Page コンポーネント内に "合体処理中" のIDを管理する useRef<Set<string>> を1つ追加し、onCollide の先頭でそのSetを確認するのが最もシンプルで確実な修正です。
index.tsx
const mergingPlanets = useRef<Set<string>>(new Set());handleMerge の先頭で両IDをSetに登録します。
const handleMerge = (obsoletePlanetIdA: string, obsoletePlanetIdB: string, newPlanetData: Planet) => {
mergingPlanets.current.add(obsoletePlanetIdA);
mergingPlanets.current.add(obsoletePlanetIdB);
// 以降は既存の処理のまま
planetRegistry.current.delete(obsoletePlanetIdA);
...
};PlanetMesh.tsx(onCollide の先頭)
onCollide: (e) => {
const myId = e.target.userData.id;
const otherId = e.body.userData.id;
// どちらかが合体処理中なら即リターン
if (mergingPlanets.current.has(myId) || mergingPlanets.current.has(otherId)) {
return;
}
// 既存の処理...
}このアプローチが最適な理由:
- 最小限の変更で根本原因を解消できる
- 処理が同期的・決定的であり、タイマーや遅延に依存しない
- 合体中の惑星のIDは UUID であるため再利用されず、Setのクリーンアップも不要
- 既存のレジストリ削除タイミングやReactのレンダリングサイクルを変更する必要がない
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
・合体か爆発かを判定する関数を追加
・月を追加
問題
現在のコードで惑星の合体が発生すると
という風にエラーが発生する