Skip to content

Commit 000392b

Browse files
committed
refactor(simulation): remove remaining useRef hooks
1 parent 816fcec commit 000392b

4 files changed

Lines changed: 43 additions & 47 deletions

File tree

src/pages/Simulation/components/CameraController.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import type { PlanetRegistry } from "../core/PlanetRegistry";
77
type CameraControllerProps = {
88
followedPlanetId: string | null;
99
planetRegistry: PlanetRegistry;
10-
orbitControlsRef: React.MutableRefObject<OrbitControls | null>;
10+
orbitControls: OrbitControls | null;
1111
};
1212

1313
export function CameraController({
1414
followedPlanetId,
1515
planetRegistry,
16-
orbitControlsRef,
16+
orbitControls,
1717
}: CameraControllerProps) {
1818
const { camera } = useThree();
1919
const followController = useMemo(() => new CameraFollowController(), []);
@@ -27,7 +27,7 @@ export function CameraController({
2727
followedPlanetId,
2828
planetRegistry,
2929
camera,
30-
controls: orbitControlsRef.current,
30+
controls: orbitControls,
3131
});
3232
});
3333
return null;

src/pages/Simulation/components/Explosion.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useFrame } from "@react-three/fiber";
2-
import { useEffect, useRef, useState } from "react";
2+
import { useEffect, useState } from "react";
33
import * as THREE from "three";
44
import type { ExplosionData } from "@/types/Explosion";
55

@@ -17,7 +17,6 @@ type ExplosionProps = {
1717
};
1818

1919
export function Explosion({ explosion, onComplete }: ExplosionProps) {
20-
const groupRef = useRef<THREE.Group | null>(null);
2120
const [fragments, setFragments] = useState<Fragment[]>([]);
2221

2322
// 爆発初期化
@@ -118,7 +117,7 @@ export function Explosion({ explosion, onComplete }: ExplosionProps) {
118117
});
119118

120119
return (
121-
<group ref={groupRef}>
120+
<group>
122121
{fragments.map((f) => (
123122
<primitive key={f.id} object={f.mesh} />
124123
))}

src/pages/Simulation/components/PlanetMesh.tsx

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { useSphere } from "@react-three/cannon";
22
import { Trail, useTexture } from "@react-three/drei";
33
import { useFrame } from "@react-three/fiber";
4-
import { useEffect, useMemo, useRef } from "react";
4+
import { useEffect, useMemo } from "react";
55
import * as THREE from "three";
66
import type { Planet } from "@/types/planet";
77
import { GravitySystem } from "../core/GravitySystem";
8-
import type { PlanetRegistry } from "../core/PlanetRegistry";
8+
import type { PlanetRegistry, PositionRef } from "../core/PlanetRegistry";
99

1010
type PlanetMeshProps = {
1111
planet: Planet;
@@ -20,45 +20,42 @@ export function PlanetMesh({
2020
onExplosion,
2121
onSelect,
2222
}: PlanetMeshProps) {
23-
const [ref, api] = useSphere<THREE.Mesh>(
24-
() => ({
25-
mass: planet.mass,
26-
args: [planet.radius],
27-
position: [planet.position.x, planet.position.y, planet.position.z],
28-
velocity: [planet.velocity.x, planet.velocity.y, planet.velocity.z],
29-
angularVelocity: [0, planet.rotationSpeedY, 0], // 物理エンジンでY軸周りの角速度を設定
30-
linearDamping: 0, // 宇宙空間なので抵抗なし
31-
angularDamping: 0, // 宇宙空間なので回転の減衰もない
32-
onCollide: (e) => {
33-
// 衝突時の衝撃が一定以上なら爆発とみなす
34-
if (e.contact.impactVelocity > 0.5) {
35-
const contactPoint = new THREE.Vector3(
36-
e.contact.contactPoint[0],
37-
e.contact.contactPoint[1],
38-
e.contact.contactPoint[2],
39-
);
40-
onExplosion(contactPoint, planet.radius);
41-
}
42-
},
43-
}),
44-
useRef<THREE.Mesh>(null),
45-
);
23+
const [ref, api] = useSphere<THREE.Mesh>(() => ({
24+
mass: planet.mass,
25+
args: [planet.radius],
26+
position: [planet.position.x, planet.position.y, planet.position.z],
27+
velocity: [planet.velocity.x, planet.velocity.y, planet.velocity.z],
28+
angularVelocity: [0, planet.rotationSpeedY, 0], // 物理エンジンでY軸周りの角速度を設定
29+
linearDamping: 0, // 宇宙空間なので抵抗なし
30+
angularDamping: 0, // 宇宙空間なので回転の減衰もない
31+
onCollide: (e) => {
32+
// 衝突時の衝撃が一定以上なら爆発とみなす
33+
if (e.contact.impactVelocity > 0.5) {
34+
const contactPoint = new THREE.Vector3(
35+
e.contact.contactPoint[0],
36+
e.contact.contactPoint[1],
37+
e.contact.contactPoint[2],
38+
);
39+
onExplosion(contactPoint, planet.radius);
40+
}
41+
},
42+
}));
4643

4744
// Load the texture (you can use any public Earth texture URL)
4845
const [colorMap] = useTexture([planet.texturePath]);
4946

50-
// 物理エンジンの位置を追跡するためのref
51-
const position = useRef([
52-
planet.position.x,
53-
planet.position.y,
54-
planet.position.z,
55-
]);
47+
const position = useMemo<PositionRef>(
48+
() => ({
49+
current: [planet.position.x, planet.position.y, planet.position.z],
50+
}),
51+
[planet.position.x, planet.position.y, planet.position.z],
52+
);
5653
useEffect(() => {
5754
const unsubscribe = api.position.subscribe((v) => {
5855
position.current = v;
5956
});
6057
return () => unsubscribe(); // アンマウント時に購読解除
61-
}, [api.position]);
58+
}, [api.position, position]);
6259

6360
// マウント時に自分のMeshをレジストリに登録し、他の惑星から参照できるようにする
6461
useEffect(() => {
@@ -77,7 +74,7 @@ export function PlanetMesh({
7774
return () => {
7875
planetRegistry.unregister(planet.id);
7976
};
80-
}, [planet.id, planetRegistry, planet.mass, planet.radius, ref]);
77+
}, [planet.id, planetRegistry, planet.mass, planet.radius, ref, position]);
8178

8279
// 計算用ベクトルをメモリに保持しておく(毎フレームnewしないため)
8380
const gravitySystem = useMemo(() => new GravitySystem(), []);

src/pages/Simulation/index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Physics } from "@react-three/cannon";
22
import { OrbitControls, Stars, useTexture } from "@react-three/drei";
33
import { Canvas } from "@react-three/fiber";
44
import { button, useControls } from "leva";
5-
import { Suspense, useMemo, useRef, useState } from "react";
5+
import { Suspense, useMemo, useState } from "react";
66
import type { OrbitControls as Controls } from "three-stdlib";
77
import { earth, jupiter, mars, sun, venus } from "@/data/planets";
88
import { CameraController } from "./components/CameraController";
@@ -27,7 +27,7 @@ useTexture.preload(planetTexturePaths);
2727
const planetTemplates = { earth, sun, mars, jupiter, venus } as const;
2828

2929
export default function Page() {
30-
const orbitControlsRef = useRef<Controls | null>(null);
30+
const [orbitControls, setOrbitControls] = useState<Controls | null>(null);
3131
const planetRegistry = useMemo(() => new PlanetRegistry(), []);
3232
const simulationWorld = useMemo(() => new SimulationWorld([earth]), []);
3333

@@ -100,10 +100,10 @@ export default function Page() {
100100
showAxes: true,
101101
showPreview: true,
102102
resetCameraPosition: button(() => {
103-
if (orbitControlsRef.current) {
104-
orbitControlsRef.current.reset();
105-
orbitControlsRef.current.target.set(0, 0, 0);
106-
orbitControlsRef.current.update();
103+
if (orbitControls) {
104+
orbitControls.reset();
105+
orbitControls.target.set(0, 0, 0);
106+
orbitControls.update();
107107
}
108108
}),
109109
});
@@ -150,7 +150,7 @@ export default function Page() {
150150
<CameraController
151151
followedPlanetId={worldState.followedPlanetId}
152152
planetRegistry={planetRegistry}
153-
orbitControlsRef={orbitControlsRef}
153+
orbitControls={orbitControls}
154154
/>
155155

156156
<Physics gravity={[0, 0, 0]}>
@@ -205,7 +205,7 @@ export default function Page() {
205205
fade
206206
speed={1}
207207
/>
208-
<OrbitControls ref={orbitControlsRef} enableZoom={true} />
208+
<OrbitControls ref={setOrbitControls} enableZoom={true} />
209209
</Canvas>
210210
<div className="absolute left-4 top-4 w-80 max-h-[75vh] overflow-y-auto rounded-lg bg-black/70 p-3 text-sm text-white backdrop-blur-sm">
211211
<div className="flex items-center justify-between">

0 commit comments

Comments
 (0)