# SimulationBall

SimulationBall : `PVInstance`

## Overview

Simulation Ball is a Ball object designed to solve the problem of inaccurate synchronization of the physics engine in games. Traditional physics-based balls had issues where each client rendered the ball at different positions due to server latency effects. However, SimulationBall allows all clients to share the same position, velocity, and rotation based on pre-simulated trajectory data.

By using this method, you can obtain the following advantages:

* Latency Compensation: Maintains the same ball movement regardless of server-client latency.
* High Performance: Improves performance by eliminating frame-by-frame physics calculations.
* Predictable Results: Easily query position, velocity, and rotation at a specific point in time based on simulated results.
* Complex Physics Implementation: Enables implementation of non-linear movements based on rotation, such as the Magnus effect.

## Properties

### BallMeshCollisionProfile

`string`

Specifies the name of the collision profile applied to the Simulation Ball's mesh component. This value determines how collisions and overlaps with other objects are handled. The default value is `"OverlapAll"`, which means the ball does not physically block other parts when overlapping and only generates overlap events. Depending on your game scenario, you can switch to another profile such as `"BlockAll"` to adjust the collision response.

> **Note:** This property only affects the actual collision/overlap behavior of the mesh component and does not participate in the trajectory simulation performed by the `Simulate` call. Collision detection during the simulation stage is handled through `BallTraceChannel`.

#### Code Samples

### BallRadius

`number`

Specifies the radius of the ball. It determines the physical collision and rendering size used in the simulation, and is used to match the ball's size with collision detection in the actual game. Larger values can affect the calculation of the ball's mass and air resistance.

#### Code Samples

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

### BallState

`Enum.BallState`

Indicates the current state of the Simulation Ball. It can have the following state values:

* `Simulated` (0): The simulation is complete and ready for playback.
* `Playing` (1): The simulation is currently playing.
* `Stopped` (2): The simulation is stopped.
* `Paused` (3): The simulation is paused.

This property is read-only, and the state changes via the `Play()`, `Pause()`, and `Stop()` methods.

#### 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
```

### BallTraceChannel

`number`

Specifies the trace channel used when the Simulation Ball performs sweep tests along its trajectory. This channel is passed to the internal ball simulator component's `TraceChannel` value and determines the range of objects targeted for collision detection. The default value is the `InteractionTrace` channel, and it can be changed to another channel value according to your project's collision settings.

#### Code Samples

### CFrame

`CFrame`

A CFrame representing the current position and rotation of the Simulation Ball. Changing this property immediately updates the ball's position and rotation, and it is automatically updated according to `PlaybackTime` during simulation.

#### 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`

Specifies the color of the ball. This property only controls the visual representation of the ball and does not affect physical movement.

#### 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`

Controls the visibility of path markers that visually display the ball's movement trajectory. If set to `true`, the simulated path of the ball is visually displayed, which is useful for debugging or visualization.

#### Code Samples

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

-- Enable path markers
ball.EnablePathMarker = true

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

### IsPathMarkerWorldSpace

`boolean`

Specifies whether path markers use the world space coordinate system. If set to `true`, path markers are displayed fixed in world space. If set to `false`, they are displayed relative to the ball's local space.

#### Code Samples

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

-- Display path markers in world space
ball.IsPathMarkerWorldSpace = true
```

### Material

`Enum.Material`

Specifies the surface material of the ball. Visual representation and physical reactions (friction, restitution, etc.) may vary depending on the 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`

A string specifying a variant of the material. Some materials support multiple variants, and this property allows you to select a specific variant.

#### Code Samples

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

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

### PathMarkerScale

`number`

Specifies the size scale of the path markers. Larger values make the path markers appear larger. The default value is 0.2.

#### Code Samples

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

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

### Position

`Vector3`

Represents the current world position of the Simulation Ball. This value is the same as the current `CFrame.Position` and is automatically updated according to `PlaybackTime` during simulation.

#### Code Samples

### SlomoFactor

`number`

Specifies the multiplier for the simulation playback speed. 1.0 is normal speed, 0.5 is half speed, and 2.0 is double speed. It can be used to implement slow-motion effects or time-lapses.

#### Code Samples

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

-- Play at half speed
ball.SlomoFactor = 0.5

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

### TextureId

`string`

The Asset ID of the texture to apply to the ball's surface. This controls only the visual representation and does not affect physical movement. For example, you can express various styles such as soccer balls, basketballs, etc.

#### Code Samples

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

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

### Transparency

`number`

Sets the transparency of the ball. 0 is fully opaque and 1 is fully transparent.

#### Code Samples

## Methods

### ClearPathMarkers

Removes all path markers generated to visualize the simulated trajectory. Useful for resetting existing marker visuals before displaying a new path.

#### Parameters

#### Return

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

#### Code Samples

### FindNextBallBounce

Returns information about the next bounce (collision) that will occur after the current playback time (`PlaybackTime`). If there is no bounce or if it is a sliding collision, an empty `BallBounce` object may be returned.

#### Parameters

#### Return

| `BallBounce` | A `BallBounce` object containing information about the next bounce. If there is no bounce, an empty object is returned. |
| ------------ | ----------------------------------------------------------------------------------------------------------------------- |

#### 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

Returns the angular velocity (`Vector3`) of the ball when a specific time (Time) has elapsed since the simulation started. This value represents the rotation direction and speed of the ball, and can be used for the Magnus effect or rotation-based trajectory prediction.

#### Parameters

| `number` Time | Time elapsed since the simulation started (in seconds). Queries the ball's angular velocity at the specified point. |
| ------------- | ------------------------------------------------------------------------------------------------------------------- |

#### Return

| `Vector3` | The angular velocity of the ball at the specified point. Direction represents the axis of rotation, and magnitude represents the angular speed. |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |

#### 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

Returns bounce information corresponding to the specified index. The index represents the order of bounces that occurred during the simulation, starting from 0. If the index is invalid, an empty `BallBounce` object may be returned.

#### Parameters

| `number` bounceIndex | The index of the bounce to query. Starts from 0 and represents the sequence of bounces occurred during the simulation. |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------- |

#### Return

| `BallBounce` | A `BallBounce` object containing bounce information for the specified index. |
| ------------ | ---------------------------------------------------------------------------- |

#### 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
```

### GetBestDirectionToTargetAtTime

Calculates the optimal direction to launch the ball towards a target position at the specified playback time. It returns the direction with the highest probability of reaching the target through physics simulation considering spin.

#### Parameters

| `number` InPlaybackTime    | Simulation playback time. The ball is launched at this point.           |
| -------------------------- | ----------------------------------------------------------------------- |
| `Vector3` InTargetPosition | Target position.                                                        |
| `number` InSpeed           | Launch speed.                                                           |
| `Vector3` SpinAxis         | Rotation axis vector.                                                   |
| `number` InSpinSpeed       | Rotation speed.                                                         |
| `number` InStepCount       | Number of simulation steps.                                             |
| `number` InTargetRadius    | Target radius. It is considered a success if reached within this range. |
| `number` InMaxSampleCount  | Maximum number of samples.                                              |

#### Return

| `Vector3` | The optimal direction vector towards the target position. |
| --------- | --------------------------------------------------------- |

#### Code Samples

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

-- Calculate optimal direction to target at current playback time
local bestDirection = ball:GetBestDirectionToTargetAtTime(
    ball.PlaybackTime,
    targetPosition,
    2000,  -- speed
    Vector3.new(0, 1, 0),  -- spin axis
    50,  -- spin speed
    100,  -- step count
    5,  -- target radius
    100  -- max sample count
)

print("Optimal launch direction:", bestDirection)
```

### GetCFrameAtTime

Returns the ball's position and rotation (`CFrame`) at a specified time (Time) after the simulation starts. This method is useful for obtaining the exact position of the ball at a future or past point in time, and is often used by NPCs or AI to predict the ball's landing spot.

#### Parameters

| `number` Time | Time elapsed since the simulation started (in seconds). Queries the ball's CFrame at the specified point. |
| ------------- | --------------------------------------------------------------------------------------------------------- |

#### Return

| `CFrame` | The CFrame of the ball at the specified point. You can know the position and rotation values. |
| -------- | --------------------------------------------------------------------------------------------- |

#### 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 ball landing spot
local landingTime = 5.0
local landingCFrame = ball:GetCFrameAtTime(landingTime)
print("Expected landing spot:", landingCFrame.Position)
```

### GetCurrentPlaybackPosition

Returns the ball's position at the current playback time (`PlaybackTime`). This method returns the same result as `GetCFrameAtTime(ball.PlaybackTime).Position`.

#### Parameters

#### Return

| `Vector3` | The ball's position at the current playback time. |
| --------- | ------------------------------------------------- |

#### Code Samples

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

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

### GetCurrentSnapshotIndex

Returns the index of the snapshot corresponding to the current playback time (`PlaybackTime`). The snapshot index indicates the position in the snapshot array generated during the simulation.

#### Parameters

#### Return

| `Value` | The index of the snapshot corresponding to the current playback time. |
| ------- | --------------------------------------------------------------------- |

#### Code Samples

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

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

### GetLinearVelocityAtTime

Returns the linear velocity (`Vector3`) at a specified time (Time) after the simulation starts. It is used when calculating the ball's movement direction and speed, and is utilized for calculating reflection angles upon collision or visualizing the ball's trajectory.

#### Parameters

| `number` Time | Time elapsed since the simulation started (in seconds). Queries the ball's velocity at the specified point. |
| ------------- | ----------------------------------------------------------------------------------------------------------- |

#### Return

| `Vector3` | The ball's velocity at the specified point. Direction represents the movement direction, and magnitude represents the speed. |
| --------- | ---------------------------------------------------------------------------------------------------------------------------- |

#### Code Samples

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

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

### GetPlaybackTime

Returns the current playback time of the simulation. This value indicates how far the simulation has progressed along the trajectory timeline.

#### Parameters

#### Return

| `number` | The current playback time of the simulation in seconds. |
| -------- | ------------------------------------------------------- |

#### Code Samples

### GetRemainedTimeForNextBounce

Returns the time remaining from the current playback time until the next bounce. If there is no bounce or it is a sliding collision, a very large value (`FLT_MAX`) is returned.

#### Parameters

#### Return

| `number` | Time remaining until the next bounce (in seconds). If there is no bounce, a very large value is returned. |
| -------- | --------------------------------------------------------------------------------------------------------- |

#### Code Samples

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

-- Check remaining time 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
```

### GetSpeedAtTime

Returns the scalar speed at a specified time (Time) after the simulation starts. Unlike `GetLinearVelocityAtTime`, it does not have direction information and simply provides the magnitude of the velocity.

#### Parameters

| `number` Time | Time elapsed since the simulation started (in seconds). Queries the ball's speed at the specified point. |
| ------------- | -------------------------------------------------------------------------------------------------------- |

#### Return

| `number` | The ball's speed at the specified point. Unit is cm/s. |
| -------- | ------------------------------------------------------ |

#### 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, "cm/s")
```

### IsValidBounceIndex

Checks if the specified index is a valid bounce index. Verifies that the index is within the range of bounces that occurred during the simulation.

#### Parameters

| `number` bounceIndex | The bounce index to check. |
| -------------------- | -------------------------- |

#### Return

| `boolean` | Returns `true` if the index is valid, `false` otherwise. |
| --------- | -------------------------------------------------------- |

#### 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

Pauses the currently running simulation. This method can be resumed with `Play()`, and the time paused is not reflected in the simulation. Used when implementing game pauses or slow-motion effects.

#### 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

Plays simulation data to actually execute the ball's movement. It is played with the same timing and results on all clients, and it is also possible to continue playing after `Pause()`.

#### Parameters

#### 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

Resimulates including spin to head towards the target position after a specified delay time from the current playback time.

#### Parameters

| `number` InDelayTime       | Delay time from the current playback time (in seconds). |
| -------------------------- | ------------------------------------------------------- |
| `Vector3` InTargetPosition | Target position.                                        |
| `number` InSpeed           | Launch speed.                                           |
| `Vector3` InSpinAxis       | Rotation axis vector.                                   |
| `number` InSpinSpeed       | Rotation speed.                                         |
| `number` InStepCount       | Number of simulation steps.                             |

#### Return

| `boolean` | Returns `true` if resimulation starts successfully, `false` otherwise. |
| --------- | ---------------------------------------------------------------------- |

#### Code Samples

### ReSimulateToTargetWithDelay

Resimulates to head towards the target position after a specified delay time from the current playback time. This method recalculates the trajectory so that the ball heads to the target point at a specific time. Spin is automatically calculated based on the current angular velocity.

#### Parameters

| `number` InDelayTime       | Delay time from the current playback time (in seconds). |
| -------------------------- | ------------------------------------------------------- |
| `Vector3` InTargetPosition | Target position.                                        |
| `number` InSpeed           | Launch speed.                                           |
| `number` InStepCount       | Number of simulation steps.                             |

#### Return

| `boolean` | Returns `true` if resimulation starts successfully, `false` otherwise. |
| --------- | ---------------------------------------------------------------------- |

#### Code Samples

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

-- Resimulate to target after 1 second
local success = ball:ReSimulateToTargetWithDelay(
    1.0,  -- after 1 second
    targetPosition,
    2000,  -- speed
    100  -- step count
)

if success then
    print("Resimulation started")
end
```

### ReSimulateWithDelay

Resimulates with the specified direction and velocity after a specified delay time from the current playback time. This method recalculates the ball's trajectory with a new direction and velocity at a specific point in time.

#### Parameters

| `number` InDelayTime  | Delay time from the current playback time (in seconds). |
| --------------------- | ------------------------------------------------------- |
| `Vector3` InDirection | Launch direction vector.                                |
| `number` InSpeed      | Launch speed.                                           |
| `Vector3` InSpinAxis  | Rotation axis vector.                                   |
| `number` InSpinSpeed  | Rotation speed.                                         |
| `number` InStepCount  | Number of simulation steps.                             |

#### Return

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

#### Code Samples

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

-- Resimulate with 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),  -- rotation axis
    50,  -- rotation speed
    100  -- step count
)
```

### SetPlaybackTime

Changes the simulation's progress time to an arbitrary point. This allows you to rewind to a specific moment or immediately check the state of a future point for testing purposes. For example, calling `SetPlaybackTime(2.5)` sets the simulation to a state where 2.5 seconds have progressed.

#### Parameters

| `number` InPlaybackTime | Target point in time to move to within the simulation (in seconds). Specify a real number value of 0 or greater, where 0 means the simulation start point. |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### Return

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

#### Code Samples

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

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

-- Move to 2.5 second point
ball:SetPlaybackTime(2.5)

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

### Simulate

Performs physics simulation of the Simulation Ball and pre-calculates the ball's movement trajectory based on the specified parameters (`BallSimParams`). This function is used to prepare the trajectory before playing with `Play()` or to analyze simulation results separately. The result is returned as an array containing information such as position, velocity, rotation, etc., calculated for each point in time.

#### Parameters

| `BallSimParams` InBallSimParams | A physics parameter structure used for simulation. Contains physical properties such as mass, gravity, initial velocity, spin, damping, and collision properties, and trajectory results vary depending on these values. |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

#### Return

| `void` | An array containing simulation results, where each element represents the ball's state (`BallSnapshot`) sorted chronologically. |
| ------ | ------------------------------------------------------------------------------------------------------------------------------- |

#### Code Samples

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

-- Create simulation parameters
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

-- Run simulation
local snapshots = ball:Simulate(params)

print("Simulation complete. Total snapshot count:", #snapshots)

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

### Stop

Stops the currently running simulation. Unlike `Pause()`, it aborts playback, and calling `Play()` again will replay from the beginning of the simulation.

#### Parameters

#### Return

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

#### Code Samples

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

-- Play simulation
ball:Play()

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

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

## Events

### Bounded

Event called when the Simulation Ball bounces (collision reflection) with another part. Unlike the `Touched` event, it is called only when a bounce occurs, and sliding collisions are not included.

#### Parameters

| `BasePart` otherPart | The part that collided with the ball. |
| -------------------- | ------------------------------------- |

#### 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

Event called when the simulation is paused. This event occurs when the `Pause()` method is called.

#### Parameters

#### Code Samples

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

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

ball:Pause()
```

### Played

Event called when the simulation starts playing. This event occurs when the `Play()` method is called.

#### Parameters

#### Code Samples

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

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

ball:Play()
```

### Stopped

Event called when the simulation is stopped. This event occurs when the `Stop()` method is called.

#### Parameters

#### Code Samples

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

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

ball:Stop()
```

### Touched

Event called when the Simulation Ball collides with another part. You can use this event to implement collision-based logic such as goal detection, reflection handling, sound playback, etc.

#### Parameters

| `BasePart` otherPart | The part that collided with the ball. |
| -------------------- | ------------------------------------- |

#### 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

Event called when the Simulation Ball ends contact with another part. Occurs when the ball moves away after colliding with a part.

#### Parameters

| `BasePart` otherPart | The part that the ball had collided with. |
| -------------------- | ----------------------------------------- |

#### 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/H8Zx8NxQOhJ15GZAjyMW" %}
[SimulationBall](/manual/studio-manual/object/simulationball.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.overdare.com/development/api-reference/classes/simulationball.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
