search/
Start typing to search packages!
package_2
dispense-prop
By @khanpython
Roblox
MirroredProp Dispenser
System for physically dispensing and attracting in-game props towards a target.
[image: Prop Dispenser Demo]Features:
- Customizable Prop Spawning: Spawn a specified number of props from a given origin with configurable settings.
- Automatic Prop Removal: Optionally remove props automatically after a configurable duration.
- Sigmoid Attraction: Props are attracted towards a target using a smooth sigmoid easing curve over a configurable duration.
- Dynamic Timing:
AttractDelayandAttractDurationaccept a fixed number, aVector2range for per-prop randomization, or a custom function. - Batch Movement: All attracted props are moved in a single
workspace:BulkMoveTocall each frame for minimal overhead. - SoA Data Layout: Internal state uses flat, cache-friendly Structure of Arrays instead of nested dictionaries.
- Event Callbacks: Attach custom logic to prop spawn, removal, and group completion events.
Installation via Wally:
- Ensure you have the Wally package manager installed on your system.
- Add the following line to your
wally.tomlfile under the[dependencies]section:dispense-prop = "khanpython/dispense-prop@5.1.0" - Run the Wally install command to download and integrate the package:
wally install - The package will be placed in your Packages folder. Use the following code snippet to require it in your project:
local PropManager = require(path-to-package)
Parameters:
PropManager:Start(amount, originCFrame, propTemplate, targetInstance, settings)
| Parameter | Type | Description |
|---|---|---|
amount | number | The number of props to spawn. Must be an integer >= 1. |
originCFrame | CFrame | The starting position for the props. |
propTemplate | Model or BasePart | A template instance to clone for each prop. |
targetInstance | Model or BasePart | The target instance towards which props may be attracted. |
settings | table | A table of configuration options for the props. See details below. |
settings Table
DynamicNumber = number | Vector2 | (propIndex: number) -> number
| Key | Type | Default | Description |
|---|---|---|---|
RemoveMagnitude | number? | 1 | The distance within which a prop is removed (claimed). |
AttractMagnitude | number? | nil | The range within which props begin attraction. nil means attract from any distance. |
AttractDuration | DynamicNumber? | 1.5 | How long (seconds) the sigmoid attraction takes to complete. |
AttractDelay | DynamicNumber? | 3 | Time delay before a prop becomes live and can be attracted/claimed. |
AutoRemoveTime | number? | nil | Time in seconds before props are automatically removed. |
CollisionGroup | string? | Props | The collision group assigned to props. |
OnSpawn | function | required | A function executed when a prop is spawned. |
OnRemoved | function? | nil | A function executed when a prop is removed. Receives true if forced (auto-remove/external destroy). |
OnAllRemoved | function? | nil | A function executed when all props in a group are removed. |
DynamicNumber
AttractDelay and AttractDuration accept a DynamicNumber, which resolves per-prop at spawn time. This lets you stagger or randomize timing across a group.
| Form | Behavior | Example |
|---|---|---|
number | Same value for every prop | AttractDelay = 2 |
Vector2 | Random value in [min, max] (order doesn't matter) | AttractDuration = Vector2.new(1, 3) |
function | Called with the prop's 1-based index in the group | AttractDelay = function(i) return i * 0.15 end |
-- Fixed: all props attract after 2 seconds
AttractDelay = 2
-- Random: each prop gets a random delay between 1 and 4 seconds
AttractDelay = Vector2.new(1, 4)
-- Staggered: prop 1 waits 0.15s, prop 2 waits 0.3s, etc.
AttractDelay = function(propIndex)
return propIndex * 0.15
end
Example Usage:
local PropDispenser = require(path-to-package)
local settings = {
RemoveMagnitude = 2,
AttractMagnitude = 20,
AttractDuration = Vector2.new(1, 2), -- random 1-2s per prop
AttractDelay = 3,
AutoRemoveTime = 30,
CollisionGroup = "Props",
--! Important: Avoid yielding any of the callbacks. `OnSpawn` could be an exception, though it may lead to unexpected results.
OnSpawn = function(prop)
print("Spawned prop:", prop)
-- You must manually parent the prop
prop.Parent = workspace
local randomX = math.random(-10, 10)
local randomY = math.random(5, 10)
local randomZ = math.random(-10, 10)
-- Your `spill` logic
task.defer(function()
prop.PrimaryPart:ApplyImpulse(
Vector3.new(randomX, randomY, randomZ)
)
end)
end,
OnRemoved = function(wasForced)
print("Prop removed.")
--[[
* Triggered whenever a single prop is removed.
* `wasForced` is `true` if the removal was due to auto-remove, external destruction,
or the target leaving. It is `nil`/falsy when the prop was claimed normally.
]]
end,
OnAllRemoved = function()
print("All props removed.")
--[[
* Triggered when every prop in the group has been removed,
regardless of how each individual removal occurred.
]]
end,
}
PropDispenser:Start(
10, -- Number of props
CFrame.new(0, 10, 0), -- Origin position
workspace.PropTemplate, -- Template prop instance
workspace.Target, -- Target instance
settings -- Settings table
)
Package Details
Install command (Click to copy)
Version
5.1.0
License
MIT
Safe for commercial use
Automated license review — not legal advice.
