> For the complete documentation index, see [llms.txt](https://docs.overdare.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.overdare.com/korean/development/api-reference/classes/simulationball.md).

# SimulationBall

SimulationBall : `PVInstance`

## Overview

시뮬레이션 볼은 게임 내에서 물리 엔진의 부정확한 동기화 문제를 해결하기 위해 설계된 Ball 오브젝트입니다. 기존의 피직스 기반 공은 각 클라이언트가 서버 레이턴시의 영향을 받아 서로 다른 위치에 공을 렌더링하는 문제가 있었지만, SimulationBall은 사전에 시뮬레이션된 궤적 데이터를 기반으로 모든 클라이언트가 동일한 위치, 속도, 회전을 공유하도록 합니다.

이 방식을 통해 다음과 같은 장점을 얻을 수 있습니다:

* 레이턴시 보정: 서버-클라이언트 간 지연 시간에 상관없이 동일한 공 움직임 유지
* 고성능 처리: 프레임 단위 물리 연산을 제거하여 성능 향상
* 예측 가능한 결과: 시뮬레이션된 결과를 기반으로 특정 시점의 위치, 속도, 회전을 쉽게 조회 가능
* 복잡한 물리 효과 구현: 마그누스 효과 등 회전에 따른 비선형 움직임 구현 가능

## Properties

### BallCFrame

`CFrame`

시뮬레이션 볼의 콜리전 스피어(collision sphere)가 현재 위치한 실제 월드 위치와 회전을 나타내는 읽기 전용 CFrame입니다. `CFrame` 프로퍼티가 새로운 시뮬레이션을 시작할 발사 위치(입력)로 사용되는 것과 달리, `BallCFrame`은 재생 중 매 틱마다 갱신되는 실제 위치/회전을 나타냅니다.

> **참고:** 이 값을 직접 설정할 수는 없습니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Check the actual position of the collision sphere
print("Collision sphere position:", ball.BallCFrame.Position)
```

### BallMeshCollisionProfile

`string`

시뮬레이션 볼의 메시 컴포넌트에 적용되는 콜리전 프로파일 이름을 지정합니다. 이 값을 설정하면 다른 오브젝트와의 충돌/오버랩 처리 방식이 결정됩니다.

> **참고:** 이 속성은 메시 컴포넌트의 실제 충돌/오버랩 동작에만 영향을 미치며, `Simulate` 호출로 수행되는 궤적 시뮬레이션 과정에는 관여하지 않습니다.

#### Code Samples

### BallRadius

`number`

공의 반지름을 지정합니다. 시뮬레이션에서 사용되는 물리적 충돌 및 렌더링 크기를 결정하며, 실제 게임에서 공의 크기와 충돌 판정을 일치시키는 데 사용됩니다. 값이 클수록 공의 질량 및 공기 저항 계산에 영향을 줄 수 있습니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")
ball.BallRadius =50
```

### BallState

`Enum.BallState`

시뮬레이션 볼의 현재 상태를 나타냅니다. 다음과 같은 상태값을 가질 수 있습니다:

* `Playing` (1): 시뮬레이션이 현재 재생 중인 상태입니다.
* `Stopped` (2): 시뮬레이션이 정지된 상태입니다.
* `Paused` (3): 시뮬레이션이 일시 정지된 상태입니다.

이 속성은 읽기 전용이며, `Play()`, `Pause()`, `Stop()` 메서드를 통해 상태가 변경됩니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

if ball.BallState == Enum.BallState.Playing then
    print("The ball is currently playing")
elseif ball.BallState == Enum.BallState.Paused then
    print("The ball is paused")
end
```

### CFrame

`CFrame`

시뮬레이션 볼의 시작 위치와 회전을 나타내는 CFrame입니다. Play 중인 아닌 상태에서 변경할 수 있습니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Set the ball's position to (0, 10, 0)
ball.CFrame = CFrame.new(0, 10, 0)

-- Set the ball's position and rotation together
ball.CFrame = CFrame.new(0, 10, 0) * CFrame.Angles(0, math.rad(45), 0)
```

### Color

`Color3`

공의 색상을 지정합니다. 이 속성은 공의 시각적 표현만을 제어하며, 물리적인 움직임에는 영향을 주지 않습니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Set the ball to red
ball.Color = Color3.new(1, 0, 0)

-- Set the ball to blue
ball.Color = Color3.fromRGB(0, 100, 255)
```

### EnablePathMarker

`boolean`

공의 이동 궤적을 시각적으로 표시하는 경로 마커의 표시 여부를 제어합니다. `true`로 설정하면 시뮬레이션된 공의 경로가 시각적으로 표시되어 디버깅이나 시각화에 유용합니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Enable path markers
ball.EnablePathMarker = true

-- Disable path markers
ball.EnablePathMarker = false
```

### Material

`Enum.Material`

공의 표면 재질을 지정합니다. 재질에 따라 공의 시각적 표현과 물리적 반응(마찰, 반발 등)이 달라질 수 있습니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Set the ball to Plastic material
ball.Material = Enum.Material.Plastic

-- Set the ball to Rubber material
ball.Material = Enum.Material.Rubber
```

### MaterialVariant

`string`

재질의 변형(variant)을 지정하는 문자열입니다. 일부 재질은 여러 변형을 지원하며, 이 속성을 통해 특정 변형을 선택할 수 있습니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Set material variant
ball.MaterialVariant = "Smooth"
```

### PathMarkerScale

`number`

경로 마커의 크기 스케일을 지정합니다. 값이 클수록 경로 마커가 더 크게 표시됩니다. 기본값은 0.2입니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Display path markers larger
ball.PathMarkerScale = 0.5
```

### PlaybackTime

`number`

시뮬레이션의 현재 재생 시간(초 단위)을 나타내는 읽기 전용 프로퍼티입니다. `GetPlaybackTime()` 메서드가 반환하는 값과 동일합니다.

> **참고:** 이 값은 읽기 전용이며 직접 대입할 수 없습니다. 재생 시간을 변경하려면 `SetPlaybackTime()` 메서드를 사용해야 합니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Check current playback time
print("Current playback time:", ball.PlaybackTime)
```

### Position

`Vector3`

시뮬레이션 볼의 현재 월드 위치를 나타내는 속성입니다. 이 값은 현재 `CFrame.Position`과 동일합니다.

#### Code Samples

### SlomoFactor

`number`

시뮬레이션 재생 속도의 배율을 지정합니다. 1.0이면 정상 속도, 0.5면 절반 속도, 2.0이면 2배 속도로 재생됩니다. 슬로모션 효과나 타임랩스 구현에 사용할 수 있습니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Play at half speed
ball.SlomoFactor = 0.5

-- Play at double speed
ball.SlomoFactor = 2.0
```

### StaticObjectTypes

`Array`

시뮬레이션 중 정적 오브젝트와의 충돌 판정에 사용할 `Enum.CollisionChannel` 값의 배열입니다. 오브젝트 타입(ObjectType) 기준으로 충돌 대상을 필터링하며, 배열이 비어 있으면 기본값으로 `WorldStatic` 채널만 대상이 됩니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Limit static object collisions to WorldStatic and WorldDynamic
ball.StaticObjectTypes = {Enum.CollisionChannel.WorldStatic, Enum.CollisionChannel.WorldDynamic}
```

### TextureId

`string`

공 표면에 적용할 텍스처의 Asset ID입니다. 시각적인 표현만을 제어하며, 물리적인 움직임에는 영향을 주지 않습니다. 예를 들어 축구공, 농구공 등 다양한 스타일을 표현할 수 있습니다.

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Set texture
ball.TextureId = "ovdrassetid://123456789"
```

### Transparency

`number`

공의 투명도를 설정합니다. 0은 완전 불투명, 1은 완전 투명을 의미합니다.

#### Code Samples

## Methods

### ClearPathMarkers

시뮬레이션 경로를 시각화하기 위해 생성된 모든 경로 마커를 제거합니다. 새로운 경로를 다시 표시하기 전에 기존 마커를 초기화할 때 유용합니다.

#### Parameters

#### Return

| `void` |   |
| ------ | - |

#### Code Samples

### FindNextBallBounce

현재 재생 시간(`PlaybackTime`) 이후에 발생할 다음 바운스(충돌) 정보를 반환합니다. 바운스가 없거나 슬라이딩 충돌인 경우 빈 `BallBounce` 객체가 반환될 수 있습니다.

#### Parameters

#### Return

| `BallBounce` | 다음 바운스 정보를 담은 `BallBounce` 객체입니다. 바운스가 없으면 빈 객체가 반환됩니다. |
| ------------ | ------------------------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Get next bounce information
local nextBounce = ball:FindNextBallBounce()

if nextBounce.BouncedTime > 0 then
    print("Next bounce time:", nextBounce.BouncedTime)
    print("Bounce position:", nextBounce.BouncedPosition)
end
```

### GetAngularVelocityAtTime

시뮬레이션이 시작된 후 특정 시간(Time)이 경과했을 때의 공의 각속도(Vector3)를 반환합니다. 이 값은 공의 회전 방향과 속도를 나타내며, 마그누스 효과나 회전 기반의 궤적 예측 등에 활용할 수 있습니다.

#### Parameters

| `number` Time | 시뮬레이션이 시작된 이후 경과한 시간(초 단위)입니다. 지정한 시점의 공의 각속도를 조회합니다. |
| ------------- | ----------------------------------------------------- |

#### Return

| `Vector3` | 지정한 시점의 공의 각속도입니다. 방향은 회전축을, 크기는 각속도를 나타냅니다. |
| --------- | -------------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Query angular velocity after 2 seconds
local angularVelocity = ball:GetAngularVelocityAtTime(2.0)
print("Angular velocity:", angularVelocity)
print("Rotation speed:", angularVelocity.Magnitude)
```

### GetBallBounceByIndex

지정된 인덱스에 해당하는 바운스 정보를 반환합니다. 인덱스는 시뮬레이션 중 발생한 바운스의 순서를 나타내며, 0부터 시작합니다. 유효하지 않은 인덱스인 경우 빈 `BallBounce` 객체가 반환될 수 있습니다.

#### Parameters

| `number` bounceIndex | 조회할 바운스의 인덱스입니다. 0부터 시작하며, 시뮬레이션 중 발생한 바운스의 순서를 나타냅니다. |
| -------------------- | ------------------------------------------------------ |

#### Return

| `BallBounce` | 지정된 인덱스의 바운스 정보를 담은 `BallBounce` 객체입니다. |
| ------------ | --------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Get first bounce information
local firstBounce = ball:GetBallBounceByIndex(0)

if firstBounce.BouncedTime > 0 then
    print("First bounce time:", firstBounce.BouncedTime)
    print("Bounce position:", firstBounce.BouncedPosition)
end
```

### GetBestVelocityToTargetAtTime

지정된 재생 시간에서 목표 위치로 공을 발사했을 때 도달 가능한 최적의 속도 벡터를 계산합니다. 반환값은 방향과 속력이 결합된 벡터(단위: km/h)이며, 스핀에 의한 마그누스 효과를 고려하여 목표 반경(`InTargetRadius`) 내에 도달할 수 있는 조합을 탐색합니다. `UseDesiredPitchAngle`을 `true`로 설정하면 `InDesiredPitchAngle`에 지정한 발사 피치 각도로 고정하여 탐색하고, `false`이면 피치 각도도 함께 자유롭게 탐색합니다.

#### Parameters

| `number` InPlaybackTime        | 시뮬레이션 재생 시간입니다. 이 시점의 공 위치를 기준으로 발사 궤적을 계산합니다.                                            |
| ------------------------------ | ----------------------------------------------------------------------------------------- |
| `Vector3` InTargetPosition     | 목표 위치입니다.                                                                                 |
| `number` InDesiredSpeed\_Kmh   | 발사 속도입니다(km/h 단위).                                                                        |
| `Vector3` SpinAxis             | 회전축 벡터입니다.                                                                                |
| `number` InSpinSpeed\_RPM      | 회전 속도입니다(RPM 단위).                                                                         |
| `number` InStepCount           | 탐색에 사용할 시뮬레이션 스텝 수입니다.                                                                    |
| `number` InTargetRadius        | 목표 반경입니다. 이 범위 내에 도달하면 성공으로 간주됩니다.                                                        |
| `number` InMaxSampleCount      | 최대 샘플링 횟수입니다.                                                                             |
| `boolean` UseDesiredPitchAngle | `true`이면 `InDesiredPitchAngle`로 지정한 발사 피치 각도를 고정하여 탐색합니다. `false`이면 피치 각도도 함께 자유롭게 탐색합니다. |
| `number` InDesiredPitchAngle   | `UseDesiredPitchAngle`이 `true`일 때 사용할 고정 발사 피치 각도입니다.                                     |

#### Return

| `Vector3` | 목표 위치에 도달하기 위한 최적의 속도 벡터입니다. 방향과 속력(km/h 단위)이 함께 담겨 있습니다. |
| --------- | --------------------------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")
local targetPosition = Vector3.new(100, 0, 50)

-- Calculate the optimal velocity toward the target at the current playback time
local bestVelocity = ball:GetBestVelocityToTargetAtTime(
    ball.PlaybackTime,
    targetPosition,
    2000,  -- speed (km/h)
    Vector3.new(0, 1, 0),  -- spin axis
    50,  -- spin speed (RPM)
    100,  -- step count
    5,  -- target radius
    100,  -- max sample count
    false,  -- search pitch angle freely
    0  -- unused since UseDesiredPitchAngle is false
)

print("Optimal launch velocity:", bestVelocity)
```

### GetCFrameAtTime

시뮬레이션 시작 후 지정된 시간(Time)의 공의 위치 및 회전(CFrame)을 반환합니다. 이 메서드는 미래 혹은 과거 시점의 공의 정확한 위치를 얻을 때 유용하며, NPC나 AI가 공의 낙하지점을 예측하는 데 자주 사용됩니다.

#### Parameters

| `number` Time | 시뮬레이션이 시작된 이후 경과한 시간(초 단위)입니다. 지정한 시점의 공 CFrame을 조회합니다. |
| ------------- | ------------------------------------------------------- |

#### Return

| `CFrame` | 지정한 시점의 공의 CFrame입니다. 위치와 회전값을 알 수 있습니다. |
| -------- | ---------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Query ball position and rotation after 3 seconds
local futureCFrame = ball:GetCFrameAtTime(3.0)
print("Position after 3 seconds:", futureCFrame.Position)

-- AI predicts the ball's landing spot
local landingTime = 5.0
local landingCFrame = ball:GetCFrameAtTime(landingTime)
print("Expected landing spot:", landingCFrame.Position)
```

### GetCurrentPlaybackPosition

현재 재생 시간(`PlaybackTime`)에서의 공의 위치를 반환합니다. 이 메서드는 `GetCFrameAtTime(ball.PlaybackTime).Position`과 동일한 결과를 반환합니다.

#### Parameters

#### Return

| `Vector3` | 현재 재생 시간에서의 공의 위치입니다. |
| --------- | --------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Check current ball position
local currentPosition = ball:GetCurrentPlaybackPosition()
print("Current ball position:", currentPosition)
```

### GetCurrentSnapshotIndex

현재 재생 시간(`PlaybackTime`)에 해당하는 스냅샷의 인덱스를 반환합니다. 스냅샷 인덱스는 시뮬레이션 중 생성된 스냅샷 배열에서의 위치를 나타냅니다.

#### Parameters

#### Return

| `Value` | 현재 재생 시간에 해당하는 스냅샷의 인덱스입니다. |
| ------- | --------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Check current snapshot index
local snapshotIndex = ball:GetCurrentSnapshotIndex()
print("Current snapshot index:", snapshotIndex)
```

### GetLinearVelocityAtTime

시뮬레이션 시작 후 지정된 시간(Time)의 선형 속도(Vector3)를 반환합니다. 공의 이동 방향과 속도를 계산할 때 사용되며, 충돌 시 반사각 계산이나 공의 궤적 시각화에 활용됩니다.

#### Parameters

| `number` Time | 시뮬레이션이 시작된 이후 경과한 시간(초 단위)입니다. 지정한 시점의 공 속도를 조회합니다. |
| ------------- | --------------------------------------------------- |

#### Return

| `Vector3` | 지정한 시점의 공의 속도입니다. 방향은 이동 방향을, 크기는 속도를 나타냅니다. |
| --------- | -------------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Query velocity after 2 seconds
local velocity = ball:GetLinearVelocityAtTime(2.0)
print("Velocity:", velocity)
print("Speed:", velocity.Magnitude)
```

### GetNextSnapshot

현재 재생 시간(`PlaybackTime`)을 기준으로, 캐시된 시뮬레이션 스냅샷 배열에서 다음 순서의 `BallSnapshot`을 반환합니다. 별도의 시간 인자를 받지 않으며, 항상 공의 현재 재생 시간을 기준으로 동작합니다. 유효한 다음 스냅샷이 없으면 빈 `BallSnapshot`이 반환됩니다.

#### Parameters

#### Return

| `BallSnapshot` | 현재 재생 시간 다음 순서의 스냅샷입니다. 유효한 스냅샷이 없으면 빈 객체가 반환됩니다. |
| -------------- | ------------------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Query the next snapshot
local nextSnapshot = ball:GetNextSnapshot()
print("Next snapshot position:", nextSnapshot.CFrame.Position)
```

### GetPlaybackTime

시뮬레이션의 현재 재생 시간을 반환합니다. 이 값은 시뮬레이션 궤적 타임라인에서 현재 어느 시점까지 진행되었는지를 나타냅니다.

#### Parameters

#### Return

| `number` | 시뮬레이션의 현재 재생 시간(초 단위)입니다. |
| -------- | ------------------------- |

#### Code Samples

### GetPrevSnapshot

현재 재생 시간(`PlaybackTime`)을 기준으로, 캐시된 시뮬레이션 스냅샷 배열에서 이전 순서의 `BallSnapshot`을 반환합니다. 별도의 시간 인자를 받지 않으며, 항상 공의 현재 재생 시간을 기준으로 동작합니다. 유효한 이전 스냅샷이 없으면 빈 `BallSnapshot`이 반환됩니다.

#### Parameters

#### Return

| `BallSnapshot` | 현재 재생 시간 이전 순서의 스냅샷입니다. 유효한 스냅샷이 없으면 빈 객체가 반환됩니다. |
| -------------- | ------------------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Query the previous snapshot
local prevSnapshot = ball:GetPrevSnapshot()
print("Previous snapshot position:", prevSnapshot.CFrame.Position)
```

### GetRemainedTimeForNextBounce

현재 재생 시간부터 다음 바운스까지 남은 시간을 반환합니다. 바운스가 없거나 슬라이딩 충돌인 경우 매우 큰 값(FLT\_MAX)이 반환됩니다.

#### Parameters

#### Return

| `number` | 다음 바운스까지 남은 시간(초 단위)입니다. 바운스가 없으면 매우 큰 값이 반환됩니다. |
| -------- | ------------------------------------------------ |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Check time remaining until next bounce
local remainingTime = ball:GetRemainedTimeForNextBounce()

if remainingTime < math.huge then
    print("Time remaining until next bounce:", remainingTime, "seconds")
else
    print("No next bounce")
end
```

### GetServerWorldTime

서버의 현재 월드 시간을 초 단위로 반환합니다. 유효한 게임 상태(`GameState`)가 있으면 서버와 동기화된 월드 시간을 반환하며, 그렇지 않은 경우 로컬 월드 시간으로 대체됩니다. 여러 클라이언트 간 시간을 동기화해야 하는 네트워크 환경에서 사용됩니다.

#### Parameters

#### Return

| `number` | 서버의 현재 월드 시간(초 단위)입니다. |
| -------- | ---------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Check server world time
print("Server world time:", ball:GetServerWorldTime())
```

### GetSpeedAtTime

시뮬레이션이 시작된 후 지정된 시간(Time)의 스칼라 속력을 반환합니다. `GetLinearVelocityAtTime`과 달리 방향 정보는 없으며, 단순히 속도의 크기만 제공합니다.

#### Parameters

| `number` Time | 시뮬레이션이 시작된 이후 경과한 시간(초 단위)입니다. 지정한 시점의 공 속력을 조회합니다. |
| ------------- | --------------------------------------------------- |

#### Return

| `number` | 지정한 시점의 공의 속력입니다. |
| -------- | ----------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Query speed after 2 seconds
local speed = ball:GetSpeedAtTime(2.0)
print("Speed after 2 seconds:", speed)
```

### GetStartTime

현재 재생이 시작된 시각을 반환합니다. 이 값은 `Play()`가 호출될 때 서버 월드 시간을 기준으로 기록되며, 아직 재생이 시작되지 않았다면 0을 반환합니다.

#### Parameters

#### Return

| `number` | 재생이 시작된 시각입니다(서버 월드 시간, 초 단위). 아직 재생되지 않았다면 0입니다. |
| -------- | ------------------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

ball:Play()

-- Check the server time when playback started
print("Playback start time:", ball:GetStartTime())
```

### IsValidBounceIndex

지정된 인덱스가 유효한 바운스 인덱스인지 확인합니다. 인덱스가 시뮬레이션 중 발생한 바운스의 범위 내에 있는지 검증합니다.

#### Parameters

| `number` bounceIndex | 확인할 바운스 인덱스입니다. |
| -------------------- | --------------- |

#### Return

| `boolean` | 인덱스가 유효하면 `true`, 그렇지 않으면 `false`를 반환합니다. |
| --------- | ----------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Check bounce index validity
if ball:IsValidBounceIndex(0) then
    local bounce = ball:GetBallBounceByIndex(0)
    print("First bounce time:", bounce.BouncedTime)
else
    print("Invalid bounce index")
end
```

### Pause

현재 진행 중인 시뮬레이션을 일시 정지합니다. 이 메서드는 `Play()`로 다시 재개할 수 있으며, 정지된 동안의 시간은 시뮬레이션에 반영되지 않습니다. 게임 일시정지나 슬로모션 효과 구현 시 사용됩니다.

#### Parameters

#### Return

| `void` | 반환값이 없습니다. |
| ------ | ---------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Play simulation
ball:Play()

-- Pause after 2 seconds
wait(2)
ball:Pause()

-- Resume
wait(1)
ball:Play()
```

### Play

시뮬레이션 데이터를 재생하여 공의 움직임을 실제로 실행합니다. 모든 클라이언트에서 동일한 타이밍과 결과로 재생되며, `Pause()` 이후 다시 이어서 재생하는 것도 가능합니다.

#### Parameters

| `boolean` bReset | 재생할 때, Plabacktime을 초기화 할지 여부 입니다. 아무 것도 넣지 않으면 기본값 `false`로 동작합니다. |
| ---------------- | ------------------------------------------------------------------- |

#### Return

| `void` | 반환값이 없습니다. |
| ------ | ---------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Set simulation parameters
local params = BallSimParams.new()
params.InitialCFrame = CFrame.new(0, 10, 0)
params.InitialVelocity = Vector3.new(100, 500, 0)
params.Mass = 0.5

-- Run simulation
ball:Simulate(params)

-- Start playback
ball:Play()
```

### ReSimulateSpinToTargetWithDelay

현재 재생 시간에서 지정된 지연 시간 후에, 지정한 스핀 축과 스핀 속도를 사용하여 목표 위치로 향하도록 재시뮬레이션을 수행합니다. `UseDesiredSpeed`가 `true`이면 `InDesiredSpeed`에 지정한 속도를 그대로 사용하여 방향만 계산하고, `false`이면 목표에 도달할 수 있는 속도와 방향을 함께 탐색합니다.

#### Parameters

| `number` InDelayTime       | 현재 재생 시간으로부터의 지연 시간(초 단위)입니다.                                                      |
| -------------------------- | ---------------------------------------------------------------------------------- |
| `Vector3` InTargetPosition | 목표 위치입니다.                                                                          |
| `number` InDesiredSpeed    | 발사 속도입니다.                                                                          |
| `Vector3` InSpinAxis       | 회전축 벡터입니다.                                                                         |
| `number` InSpinSpeed       | 회전 속도입니다.                                                                          |
| `number` InStepCount       | 시뮬레이션 스텝 수입니다.                                                                     |
| `boolean` UseDesiredSpeed  | `true`이면 `InDesiredSpeed`로 지정한 속도를 그대로 사용합니다. `false`이면 목표에 도달할 수 있는 속도를 함께 탐색합니다. |

#### Return

| `BallSimTargetResult` | 재시뮬레이션 결과입니다. 목표에 도달하는 궤적을 찾았는지 여부(`bHit`), 실제 사용된 속도(`ActualSpeed`)와 방향(`Direction`), 목표 도달 시각(`HitTime`)을 포함합니다. |
| --------------------- | ------------------------------------------------------------------------------------------------------------------ |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")
local targetPosition = Vector3.new(100, 0, 50)

-- Resimulate with spin toward the target after 1 second
local result = ball:ReSimulateSpinToTargetWithDelay(
    1.0,  -- after 1 second
    targetPosition,
    2000,  -- speed
    Vector3.new(0, 1, 0),  -- spin axis
    50,  -- spin speed (RPM)
    100,  -- step count
    true  -- use the specified speed as-is
)

if result.bHit then
    print("Hit time:", result.HitTime)
end
```

### ReSimulateToTargetWithDelay

현재 재생 시간에서 지정된 지연 시간 후에 목표 위치로 향하도록 재시뮬레이션을 수행합니다. 이 메서드는 공이 특정 시점에 목표 지점으로 향하도록 궤적을 재계산하며, 스핀은 현재 각속도를 기반으로 자동으로 계산됩니다(각속도가 거의 없으면 임의의 축으로 최소한의 스핀이 대신 적용됩니다). `UseDesiredSpeed`가 `true`이면 `InDesiredSpeed`에 지정한 속도를 그대로 사용하여 방향만 계산하고, `false`이면 목표에 도달할 수 있는 속도와 방향을 함께 탐색합니다.

#### Parameters

| `number` InDelayTime       | 현재 재생 시간으로부터의 지연 시간(초 단위)입니다.                                                      |
| -------------------------- | ---------------------------------------------------------------------------------- |
| `Vector3` InTargetPosition | 목표 위치입니다.                                                                          |
| `number` InDesiredSpeed    | 발사 속도입니다.                                                                          |
| `number` InStepCount       | 시뮬레이션 스텝 수입니다.                                                                     |
| `boolean` UseDesiredSpeed  | `true`이면 `InDesiredSpeed`로 지정한 속도를 그대로 사용합니다. `false`이면 목표에 도달할 수 있는 속도를 함께 탐색합니다. |

#### Return

| `BallSimTargetResult` | 재시뮬레이션 결과입니다. 목표에 도달하는 궤적을 찾았는지 여부(`bHit`), 실제 사용된 속도(`ActualSpeed`)와 방향(`Direction`), 목표 도달 시각(`HitTime`)을 포함합니다. |
| --------------------- | ------------------------------------------------------------------------------------------------------------------ |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")
local targetPosition = Vector3.new(100, 0, 50)

-- Resimulate toward the target after 1 second
local result = ball:ReSimulateToTargetWithDelay(
    1.0,  -- after 1 second
    targetPosition,
    2000,  -- speed
    100,  -- step count
    true  -- use the specified speed as-is
)

if result.bHit then
    print("Hit time:", result.HitTime)
end
```

### ReSimulateWithDelay

현재 재생 시간에서 지정된 지연 시간 후에 지정된 방향과 속도로 재시뮬레이션을 수행합니다. 이 메서드는 공의 궤적을 특정 시점에서 새로운 방향과 속도로 재계산합니다.

#### Parameters

| `number` InDelayTime  | 현재 재생 시간으로부터의 지연 시간(초 단위)입니다. |
| --------------------- | ----------------------------- |
| `Vector3` InDirection | 발사 방향 벡터입니다.                  |
| `number` InSpeed      | 발사 속도입니다.                     |
| `Vector3` InSpinAxis  | 회전축 벡터입니다.                    |
| `number` InSpinSpeed  | 회전 속도입니다.                     |
| `number` InStepCount  | 시뮬레이션 스텝 수입니다.                |

#### Return

| `void` |   |
| ------ | - |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Resimulate with a new direction after 1 second
ball:ReSimulateWithDelay(
    1.0,  -- after 1 second
    Vector3.new(1, 0, 0),  -- direction
    2000,  -- speed
    Vector3.new(0, 1, 0),  -- spin axis
    50,  -- spin speed
    100  -- step count
)
```

### SetPlaybackTime

시뮬레이션의 진행 시간을 임의의 시점으로 변경합니다. 이를 통해 특정 순간으로 되감거나, 미래 시점의 상태를 즉시 확인할 수 있습니다. 예를 들어, `SetPlaybackTime(2.5)`를 호출하면 시뮬레이션이 2.5초 진행된 상태로 설정됩니다. Play 중에도 변경이 가능합니다.

#### Parameters

| `number` InPlaybackTime | 시뮬레이션 내에서 이동할 목표 시점(초 단위)입니다. 0 이상의 실수 값을 지정하며, 0은 시뮬레이션 시작 시점을 의미합니다. |
| ----------------------- | ---------------------------------------------------------------------- |

#### Return

| `void` |   |
| ------ | - |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Run the simulation
ball:Simulate(params)
ball:Play()

-- Move to the 2.5 second mark
ball:SetPlaybackTime(2.5)

-- Check the ball position at that point
local position = ball:GetCurrentPlaybackPosition()
print("Position at 2.5 seconds:", position)
```

### Simulate

시뮬레이션 볼의 물리 시뮬레이션을 수행하고, 지정된 파라미터(`BallSimParams`)를 기반으로 공의 움직임 궤적을 미리 계산합니다. `AutoPlay`가 `true`이면 시뮬레이션이 끝난 후 즉시 재생을 시작하며, `false`이면 재생을 시작하기 위해 `Play()`를 별도로 호출해야 합니다.

#### Parameters

| `BallSimParams` InBallSimParams | 시뮬레이션에 사용할 물리 파라미터 구조체입니다. 질량, 중력, 초기 속도, 스핀, 감쇠, 충돌 특성 등의 물리적 특성을 포함하며, 이 값들에 따라 궤적 결과가 달라집니다. |
| ------------------------------- | ----------------------------------------------------------------------------------------------- |
| `boolean` AutoPlay              | `true`이면 시뮬레이션 완료 후 즉시 재생을 시작합니다. `false`이면 `Play()`를 호출해야 재생이 시작됩니다.                           |

#### Return

| `void` |   |
| ------ | - |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Create simulation parameters
local params = BallSimParams.new()
params.InitialCFrame = CFrame.new(0, 10, 0)
params.InitialSpeed = 2000
params.InitialDirection = Vector3.new(0, 1, 0)
params.Mass = 0.5
params.InitialSpinAxis = Vector3.new(0, 1, 0)
params.InitialSpinSpeed = 50

-- Run the simulation (start playback separately)
ball:Simulate(params, false)

-- Start playback
ball:Play()
```

### SimulateToTarget

지정된 물리 파라미터(`BallSimParams`)를 기반으로, 목표 위치(`InTargetPosition`)에 도달할 수 있는 최적의 발사 속도와 방향을 자동으로 계산하여 시뮬레이션을 실행합니다. `Simulate()`와 달리 초기 속도·방향을 직접 지정하는 대신 목표 지점을 향하도록 궤적을 역산(solve)합니다. `UseDesiredSpeed`가 `true`이면 `InBallSimParams`에 지정된 속도를 그대로 사용하여 방향만 계산하고, `false`이면 목표에 도달할 수 있는 속도와 방향을 함께 탐색합니다. `AutoPlay`가 `true`이면 시뮬레이션 완료 후 즉시 재생을 시작하며, `false`이면 `Play()`를 별도로 호출해야 재생이 시작됩니다.

#### Parameters

| `BallSimParams` InBallSimParams | 시뮬레이션에 사용할 물리 파라미터 구조체입니다. `UseDesiredSpeed`가 `true`인 경우 이 값의 `InitialSpeed`가 발사 속도로 그대로 사용됩니다. |
| ------------------------------- | ----------------------------------------------------------------------------------------------- |
| `Vector3` InTargetPosition      | 목표 위치입니다.                                                                                       |
| `boolean` UseDesiredSpeed       | `true`이면 `InBallSimParams`에 지정된 속도를 그대로 사용합니다. `false`이면 목표에 도달할 수 있는 속도를 함께 탐색합니다.             |
| `boolean` AutoPlay              | `true`이면 시뮬레이션 완료 후 즉시 재생을 시작합니다. `false`이면 `Play()`를 호출해야 재생이 시작됩니다.                           |

#### Return

| `BallSimTargetResult` | 시뮬레이션 결과입니다. 목표에 도달하는 궤적을 찾았는지 여부(`bHit`), 실제 사용된 속도(`ActualSpeed`)와 방향(`Direction`), 목표 도달 시각(`HitTime`)을 포함합니다. |
| --------------------- | ----------------------------------------------------------------------------------------------------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

local params = BallSimParams.new()
params.InitialCFrame = CFrame.new(0, 10, 0)
params.InitialSpeed = 2000
params.Mass = 0.5

local targetPosition = Vector3.new(100, 0, 50)

-- Calculate the velocity toward the target, simulate, and play immediately
local result = ball:SimulateToTarget(params, targetPosition, false, true)

if result.bHit then
    print("Hit time:", result.HitTime)
    print("Actual launch speed:", result.ActualSpeed)
end
```

### Stop

현재 진행 중인 시뮬레이션을 정지합니다. `Pause()`와 달리 재생을 중단하며, `Play()`를 다시 호출하면 시뮬레이션 시작 시점부터 다시 재생됩니다.

#### Parameters

#### Return

| `void` |   |
| ------ | - |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

-- Play the simulation
ball:Play()

-- Stop after 3 seconds
wait(3)
ball:Stop()

-- Replay (from the beginning)
ball:Play()
```

## Events

### Bounded

시뮬레이션 볼이 다른 파트와 바운스(충돌 반사)했을 때 호출되는 이벤트입니다. `Touched` 이벤트와 달리 바운스가 발생한 경우에만 호출되며, 슬라이딩 충돌은 포함되지 않습니다.

#### Parameters

\| `BasePart` otherPart | 공과 충돌한 파트입니다. |

| `BallBounce` bounce | 공이 바운스 되는 시점의 정보입니다. |
| ------------------- | -------------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

ball.Bounded:Connect(function(otherPart)
    print("Ball bounced with", otherPart.Name)

    -- Get bounce information
    local bounce = ball:FindNextBallBounce()
    print("Bounce position:", bounce.BouncedPosition)
    print("Velocity after bounce:", bounce.BouncedSpeed)
end)
```

### Paused

시뮬레이션이 일시 정지되었을 때 호출되는 이벤트입니다. `Pause()` 메서드가 호출되면 이 이벤트가 발생합니다.

#### Parameters

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

ball.Paused:Connect(function()
    print("Simulation paused")
end)

ball:Pause()
```

### Played

시뮬레이션이 재생되기 시작했을 때 호출되는 이벤트입니다. `Play()` 메서드가 호출되면 이 이벤트가 발생합니다.

#### Parameters

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

ball.Played:Connect(function()
    print("Simulation started playing")
end)

ball:Play()
```

### Stopped

시뮬레이션이 정지되었을 때 호출되는 이벤트입니다. `Stop()` 메서드가 호출되면 이 이벤트가 발생합니다.

#### Parameters

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

ball.Stopped:Connect(function()
    print("Simulation stopped")
end)

ball:Stop()
```

### Touched

시뮬레이션 볼이 다른 파트와 충돌했을 때 호출되는 이벤트입니다. 이 이벤트를 사용하여 골 판정, 반사 처리, 사운드 재생 등 충돌 기반 로직을 구현할 수 있습니다.

#### Parameters

| `BasePart` otherPart | 공과 충돌한 파트입니다. |
| -------------------- | ------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

ball.Touched:Connect(function(otherPart)
    print("Ball collided with", otherPart.Name)

    -- Goal detection example
    if otherPart.Name == "Goal" then
        print("Goal!")
    end
end)
```

### TouchEnded

시뮬레이션 볼이 다른 파트와의 접촉이 끝났을 때 호출되는 이벤트입니다. 공이 파트와 충돌한 후 떨어져 나갈 때 발생합니다.

#### Parameters

| `BasePart` otherPart | 공과 충돌했던 파트입니다. |
| -------------------- | -------------- |

#### Code Samples

```lua
local ball = workspace:FindFirstChild("SimulationBall")

ball.TouchEnded:Connect(function(otherPart)
    print("Ball ended contact with", otherPart.Name)
end)
```

## See also

{% content-ref url="/pages/iYYwRA7LVMPQ75P1DqUW" %}
[SimulationBall](/korean/manual/studio-manual/object/simulationball.md)
{% endcontent-ref %}
