Add function to play sound at position

Currently to play a 3D sound it needs to be parented to a BasePart or Attachment. This means if you have coins that you can pickup in your game, each coin needs its own Sound instance, wasting memory and complicating the entire process

SoundService already has a method for playing sound instances. Adding a method similar to :PlayLocalSound(), eg :PlayWorldSound() that will accept a sound instance and a Vector3 position which is where it will play the sound at would save memory and make it easier to use sfx in games

local CoinPickupSound = SoundService.SFX.CoinPickup

    SoundService:PlayWorldSound(CoinPickupSound, Coin.Position)

In the mean-time, you can use an attachment as a stand-in and then use PlayLocalSound:

local CoinPickupSound = SoundService.SFX.CoinPickup:Clone()
local Attachment ="Attachment", workspace.Terrain)
CoinPickupSound.Parent = Attachment

    Attachment.Position = Coin.Position

Would have to be on the client but I’m assuming since this is a special effect, you are running it on the client anyway.


I agree with this feature request.

That should only be used for Plugins iirc

  • It doesn’t fire .Played
  • and .IsPlaying is false
  • and .Playing is false
  • and .TimePosition doesn’t move

when PlayLocalSound is called

I don’t think it should be used at all, it’s very unreliable

@gillern, I might open source my Sound System module, would you be interested?

Nope, neither documentation or the security level of the API member agrees with that. It’s not listed as PluginSecurity, regular game (local)scripts can call it.

Yes, PlayLocalSound plays a sound once, it doesn’t manipulate the Sound object. This is fine if you don’t have to stop the sound or otherwise read out these values, e.g. for quick sound effects.

It’s not unreliable at all – no offence but you really don’t seem to know what you are talking about. Throwing random statements out there that aren’t actually based on technical knowledge or experience is harmful to technical discussion.


Yes, it is true that any script can call this function however the DevHub states

and in this sample code

(which sadly doesn’t work Sound.Ended will never fire)

While you can use PlayLocalSound with Positional data, it will not update and it can not be stopped.

  • The playback will always be at the start position regardless of the current Parent’s Position
  • Destroying the Sound Instance will not stop the Sound from Playing

which isn’t ideal in cases where Sound.Position has to be updated.

While PlayLocalSound can be used for in-game purposes it is very limited compared to Sound:Play, it could be used but I’d strongly advise against it, therefore it is mostly useful for Plugins.

What @buildthomas has suggested is valid for the OP’s use case but in many other use cases PlayLocalSound couldn’t be used and therefore PlayLocalSound being unreliable, not what he suggested.

These behaviors that I mentioned aren’t documented which is why I wanted to make sure people are aware.

I provided a test place to backup my findings

PlayLocalSound.rbxl (22.3 KB)

Source Code

local module = {}

local SoundService = game:GetService("SoundService")
local TweenService = game:GetService("TweenService")

local Part = script.Part
	local Sound = Part.Attachment.Sound

local Events = {

for _, v in ipairs(Events) do



local tweeninfo =, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, -1, true, 0)

TweenService:Create(Part, tweeninfo, {["CFrame"] =,5,0)}):Play()

return module
1 Like

That’s not unreliable. That’s a facet of the API that you can accept if it is fine for your use case.

I use this API in live games and I’m fully aware that you cannot read certain properties/events on the playing sounds. If your use case doesn’t need it, you can use this API just fine. The use case in OP doesn’t seem to need it.

Unreliability means that the API only works in certain edge cases or only a % of the time. This API works 100% reliable within the given constraints.