# SimulationBall

SimulationBall : `PVInstance`

## Overview

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

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

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

## Properties

### BallRadius

`number`

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

#### Code Samples

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

### BallState

`Enum.BallState`

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

* `Simulated` (0): 시뮬레이션이 완료되어 재생 준비가 된 상태입니다.
* `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("공이 현재 재생 중입니다")
elseif ball.BallState == Enum.BallState.Paused then
    print("공이 일시 정지되었습니다")
end
```

### CFrame

`CFrame`

시뮬레이션 볼의 현재 위치와 회전을 나타내는 CFrame입니다. 이 속성을 변경하면 공의 위치와 회전이 즉시 업데이트되며, 시뮬레이션 중에는 `PlaybackTime`에 따라 자동으로 갱신됩니다.

#### Code Samples

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

-- 공의 위치를 (0, 10, 0)으로 설정
ball.CFrame = CFrame.new(0, 10, 0)

-- 공의 위치와 회전을 함께 설정
ball.CFrame = CFrame.new(0, 10, 0) * CFrame.Angles(0, math.rad(45), 0)
```

### Color

`Color3`

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

#### Code Samples

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

-- 공을 빨간색으로 설정
ball.Color = Color3.new(1, 0, 0)

-- 공을 파란색으로 설정
ball.Color = Color3.fromRGB(0, 100, 255)
```

### EnablePathMarker

`bool`

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

#### Code Samples

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

-- 경로 마커 활성화
ball.EnablePathMarker = true

-- 경로 마커 비활성화
ball.EnablePathMarker = false
```

### IsPathMarkerWorldSpace

`bool`

경로 마커가 월드 공간 좌표계를 사용할지 여부를 지정합니다. `true`로 설정하면 경로 마커가 월드 공간에 고정되어 표시되고, `false`로 설정하면 공의 로컬 공간을 기준으로 표시됩니다.

#### Code Samples

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

-- 경로 마커를 월드 공간에 표시
ball.IsPathMarkerWorldSpace = true
```

### Material

`Enum.Material`

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

#### Code Samples

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

-- 공을 플라스틱 재질로 설정
ball.Material = Enum.Material.Plastic

-- 공을 고무 재질로 설정
ball.Material = Enum.Material.Rubber
```

### MaterialVariant

`string`

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

#### Code Samples

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

-- 재질 변형 설정
ball.MaterialVariant = "Smooth"
```

### PathMarkerScale

`number`

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

#### Code Samples

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

-- 경로 마커를 더 크게 표시
ball.PathMarkerScale = 0.5
```

### Position

`Vector3`

시뮬레이션 볼의 현재 월드 위치를 나타내는 속성입니다. 이 값은 현재 `CFrame.Position`과 동일하며, 시뮬레이션 중에는 `PlaybackTime`에 따라 자동으로 갱신됩니다.

#### Code Samples

### SlomoFactor

`number`

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

#### Code Samples

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

-- 절반 속도로 재생
ball.SlomoFactor = 0.5

-- 2배 속도로 재생
ball.SlomoFactor = 2.0
```

### TextureId

`string`

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

#### Code Samples

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

-- 텍스처 설정
ball.TextureId = "ovdrassetid://123456789"
```

## Methods

### ClearPathMarkers

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

#### Parameters

| Parameter | Description |
| --------- | ----------- |
| None      |             |

#### Return

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

#### Code Samples

### FindNextBallBounce

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

#### Parameters

#### Return

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

#### Code Samples

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

-- 다음 바운스 정보 가져오기
local nextBounce = ball:FindNextBallBounce()

if nextBounce.BouncedTime > 0 then
    print("다음 바운스 시간:", nextBounce.BouncedTime)
    print("바운스 위치:", nextBounce.BouncedPosition)
end
```

### GetAngularVelocityAtTime

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

#### Parameters

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

#### Return

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

#### Code Samples

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

-- 2초 후의 각속도 조회
local angularVelocity = ball:GetAngularVelocityAtTime(2.0)
print("각속도:", angularVelocity)
print("회전 속도:", angularVelocity.Magnitude)
```

### GetBallBounceByIndex

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

#### Parameters

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

#### Return

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

#### Code Samples

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

-- 첫 번째 바운스 정보 가져오기
local firstBounce = ball:GetBallBounceByIndex(0)

if firstBounce.BouncedTime > 0 then
    print("첫 번째 바운스 시간:", firstBounce.BouncedTime)
    print("바운스 위치:", firstBounce.BouncedPosition)
end
```

### GetBestDirectionToTargetAtTime

지정된 재생 시간에서 목표 위치로 공을 발사하기 위한 최적의 방향을 계산합니다. 스핀을 고려한 물리 시뮬레이션을 통해 목표에 도달할 가능성이 가장 높은 방향을 반환합니다.

#### Parameters

| `number` InPlaybackTime    | 시뮬레이션 재생 시간입니다. 이 시점에서 공을 발사합니다.   |
| -------------------------- | ---------------------------------- |
| `Vector3` InTargetPosition | 목표 위치입니다.                          |
| `number` InSpeed           | 발사 속도입니다.                          |
| `Vector3` SpinAxis         | 회전축 벡터입니다.                         |
| `number` InSpinSpeed       | 회전 속도입니다.                          |
| `number` InStepCount       | 시뮬레이션 스텝 수입니다.                     |
| `number` InTargetRadius    | 목표 반경입니다. 이 범위 내에 도달하면 성공으로 간주됩니다. |
| `number` InMaxSampleCount  | 최대 샘플링 횟수입니다.                      |

#### Return

| `Vector3` | 목표 위치로 향하는 최적의 방향 벡터입니다. |
| --------- | ------------------------ |

#### Code Samples

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

-- 현재 재생 시간에서 목표로 향하는 최적 방향 계산
local bestDirection = ball:GetBestDirectionToTargetAtTime(
    ball.PlaybackTime,
    targetPosition,
    2000,  -- 속도
    Vector3.new(0, 1, 0),  -- 회전축
    50,  -- 회전 속도
    100,  -- 스텝 수
    5,  -- 목표 반경
    100  -- 최대 샘플 수
)

print("최적 발사 방향:", bestDirection)
```

### GetCFrameAtTime

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

#### Parameters

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

#### Return

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

#### Code Samples

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

-- 3초 후의 공 위치와 회전 조회
local futureCFrame = ball:GetCFrameAtTime(3.0)
print("3초 후 위치:", futureCFrame.Position)

-- AI가 공의 낙하지점 예측
local landingTime = 5.0
local landingCFrame = ball:GetCFrameAtTime(landingTime)
print("예상 낙하지점:", landingCFrame.Position)
```

### GetCurrentPlaybackPosition

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

#### Parameters

#### Return

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

#### Code Samples

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

-- 현재 공의 위치 확인
local currentPosition = ball:GetCurrentPlaybackPosition()
print("현재 공 위치:", currentPosition)
```

### GetCurrentSnapshotIndex

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

#### Parameters

#### Return

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

#### Code Samples

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

-- 현재 스냅샷 인덱스 확인
local snapshotIndex = ball:GetCurrentSnapshotIndex()
print("현재 스냅샷 인덱스:", snapshotIndex)
```

### GetLinearVelocityAtTime

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

#### Parameters

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

#### Return

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

#### Code Samples

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

-- 2초 후의 속도 조회
local velocity = ball:GetLinearVelocityAtTime(2.0)
print("속도:", velocity)
print("속력:", velocity.Magnitude)
```

### GetPlaybackTime

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

#### Parameters

| Parameter | Description |
| --------- | ----------- |
| None      |             |

#### Return

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

#### Code Samples

### GetRemainedTimeForNextBounce

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

#### Parameters

#### Return

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

#### Code Samples

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

-- 다음 바운스까지 남은 시간 확인
local remainingTime = ball:GetRemainedTimeForNextBounce()

if remainingTime < math.huge then
    print("다음 바운스까지 남은 시간:", remainingTime, "초")
else
    print("다음 바운스가 없습니다")
end
```

### GetSpeedAtTime

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

#### Parameters

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

#### Return

| `number` | 지정한 시점의 공의 속력입니다. 단위는 cm/s입니다. |
| -------- | ------------------------------ |

#### Code Samples

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

-- 2초 후의 속력 조회
local speed = ball:GetSpeedAtTime(2.0)
print("2초 후 속력:", speed, "cm/s")
```

### IsValidBounceIndex

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

#### Parameters

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

#### Return

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

#### Code Samples

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

-- 바운스 인덱스 유효성 확인
if ball:IsValidBounceIndex(0) then
    local bounce = ball:GetBallBounceByIndex(0)
    print("첫 번째 바운스 시간:", bounce.BouncedTime)
else
    print("유효하지 않은 바운스 인덱스입니다")
end
```

### Pause

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

#### Parameters

#### Return

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

#### Code Samples

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

-- 시뮬레이션 재생
ball:Play()

-- 2초 후 일시 정지
wait(2)
ball:Pause()

-- 다시 재개
wait(1)
ball:Play()
```

### Play

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

#### Parameters

#### Return

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

#### Code Samples

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

-- 시뮬레이션 파라미터 설정
local params = BallSimParams.new()
params.InitialCFrame = CFrame.new(0, 10, 0)
params.InitialVelocity = Vector3.new(100, 500, 0)
params.Mass = 0.5

-- 시뮬레이션 실행
ball:Simulate(params)

-- 재생 시작
ball:Play()
```

### ReSimulateSpinToTargetWithDelay

{Description Slot}

#### Parameters

| `number` InDelayTime       |   |
| -------------------------- | - |
| `Vector3` InTargetPosition |   |
| `number` InSpeed           |   |
| `Vector3` InSpinAxis       |   |
| `number` InSpinSpeed       |   |
| `number` InStepCount       |   |

#### Return

| `bool` |   |
| ------ | - |

#### Code Samples

### ReSimulateToTargetWithDelay

현재 재생 시간에서 지정된 지연 시간 후에 목표 위치로 향하도록 재시뮬레이션을 수행합니다. 이 메서드는 공이 특정 시점에 목표 지점으로 향하도록 궤적을 재계산합니다. 스핀은 현재 각속도를 기반으로 자동 계산됩니다.

#### Parameters

| `number` InDelayTime       | 현재 재생 시간으로부터의 지연 시간(초 단위)입니다. |
| -------------------------- | ----------------------------- |
| `Vector3` InTargetPosition | 목표 위치입니다.                     |
| `number` InSpeed           | 발사 속도입니다.                     |
| `number` InStepCount       | 시뮬레이션 스텝 수입니다.                |

#### Return

| `bool` | 재시뮬레이션이 성공적으로 시작되면 `true`, 실패하면 `false`를 반환합니다. |
| ------ | ----------------------------------------------- |

#### Code Samples

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

-- 1초 후에 목표로 향하도록 재시뮬레이션
local success = ball:ReSimulateToTargetWithDelay(
    1.0,  -- 1초 후
    targetPosition,
    2000,  -- 속도
    100  -- 스텝 수
)

if success then
    print("재시뮬레이션이 시작되었습니다")
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")

-- 1초 후에 새로운 방향으로 재시뮬레이션
ball:ReSimulateWithDelay(
    1.0,  -- 1초 후
    Vector3.new(1, 0, 0),  -- 방향
    2000,  -- 속도
    Vector3.new(0, 1, 0),  -- 회전축
    50,  -- 회전 속도
    100  -- 스텝 수
)
```

### SetPlaybackTime

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

#### Parameters

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

#### Return

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

#### Code Samples

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

-- 시뮬레이션 실행
ball:Simulate(params)
ball:Play()

-- 2.5초 시점으로 이동
ball:SetPlaybackTime(2.5)

-- 해당 시점의 공 위치 확인
local position = ball:GetCurrentPlaybackPosition()
print("2.5초 시점의 위치:", position)
```

### Simulate

시뮬레이션 볼의 물리 시뮬레이션을 수행하고, 지정된 파라미터(`BallSimParams`)를 기반으로 공의 움직임 궤적을 미리 계산합니다. 이 함수는 `Play()`로 재생하기 전에 미리 궤적을 준비하거나, 시뮬레이션 결과를 별도로 분석할 때 사용됩니다. 결과는 각 시점별로 계산된 위치, 속도, 회전 등의 정보를 포함한 배열 형태로 반환됩니다.

#### Parameters

| `BallSimParams` InBallSimParams | 시뮬레이션에 사용할 물리 파라미터 구조체입니다. 질량, 중력, 초기 속도, 스핀, 감쇠, 충돌 특성 등의 물리적 특성을 포함하며, 이 값들에 따라 궤적 결과가 달라집니다. |
| ------------------------------- | ----------------------------------------------------------------------------------------------- |

#### Return

| `array` | 시뮬레이션 결과를 담은 배열로, 각 원소는 시간순으로 정렬된 공의 상태(`BallSnapshot`)를 나타냅니다. |
| ------- | --------------------------------------------------------------- |

#### Code Samples

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

-- 시뮬레이션 파라미터 생성
local params = BallSimParams.new()
params.InitialCFrame = CFrame.new(0, 10, 0)
params.InitialVelocity = Vector3.new(100, 500, 0)
params.Mass = 0.5
params.BaseGravity = Vector3.new(0, -980, 0)
params.InitialSpinAxis = Vector3.new(0, 1, 0)
params.InitialSpinSpeed = 50

-- 시뮬레이션 실행
local snapshots = ball:Simulate(params)

print("시뮬레이션 완료. 총 스냅샷 개수:", #snapshots)

-- 재생 시작
ball:Play()
```

### Stop

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

#### Parameters

#### Return

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

#### Code Samples

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

-- 시뮬레이션 재생
ball:Play()

-- 3초 후 정지
wait(3)
ball:Stop()

-- 다시 재생 (처음부터)
ball:Play()
```

## Events

### Bounded

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

#### Parameters

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

#### Code Samples

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

ball.Bounded:Connect(function(otherPart)
    print("공이", otherPart.Name, "와 바운스했습니다")
    
    -- 바운스 정보 가져오기
    local bounce = ball:FindNextBallBounce()
    print("바운스 위치:", bounce.BouncedPosition)
    print("바운스 후 속도:", bounce.BouncedSpeed)
end)
```

### Paused

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

#### Parameters

#### Code Samples

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

ball.Paused:Connect(function()
    print("시뮬레이션이 일시 정지되었습니다")
end)

ball:Pause()
```

### Played

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

#### Parameters

#### Code Samples

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

ball.Played:Connect(function()
    print("시뮬레이션이 재생되기 시작했습니다")
end)

ball:Play()
```

### Stopped

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

#### Parameters

#### Code Samples

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

ball.Stopped:Connect(function()
    print("시뮬레이션이 정지되었습니다")
end)

ball:Stop()
```

### Touched

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

#### Parameters

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

#### Code Samples

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

ball.Touched:Connect(function(otherPart)
    print("공이", otherPart.Name, "와 충돌했습니다")
    
    -- 골 판정 예시
    if otherPart.Name == "Goal" then
        print("골!")
    end
end)
```

### TouchEnded

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

#### Parameters

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

#### Code Samples

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

ball.TouchEnded:Connect(function(otherPart)
    print("공이", otherPart.Name, "와의 접촉을 끝냈습니다")
end)
```

## See also

{% content-ref url="../../../manual/studio-manual/object/simulationball" %}
[simulationball](https://docs.overdare.com/korean/manual/studio-manual/object/simulationball)
{% endcontent-ref %}
