3D to 2D Sound Bug

Problem:

  • When a Sound is parented to an Instance with Positional data then parented to an Instance with no Positional data it plays as a 3D sound NOT 2D sound

Expected behavior:

  • When a Sound is parented to an Instance with no Positional data it’s suppose to play as a 2D sound NOT 3D sound

image

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

local function play3D()
	print("play3D")
	Sound.Parent = Attachment
	Sound:Play()
end

local function play2D()
	print("play2D")
	Sound.Parent = script
	-- this erroneously plays in 3D if the Sound was in the Attachment beforehand
	Sound:Play()
end

play3D()
wait(5)
play2D()

Just press play a zoom the camera in and out to reproduce


repro file.rbxl (19.3 KB)

https://developer.roblox.com/en-us/api-reference/class/Sound

A sound placed in a BasePart or an Attachment will emit its sound from that part’s BasePart.Position or the attachment’s Attachment.WorldPosition

A sound is considered “global” if it is not parented to a BasePart or an Attachment . In this case, the sound will play at the same volume throughout the entire place.

5 Likes

Additionally this can be fixed by doing
Sound.Parent = nil then Sound.Parent = Instance
but this is annoying to do, inconsistent with the documentation, unexpected, etc

Furthermore this should be either fixed or mentioned in the DevHub so others do not have to go through a frustrating experience while wondering why it’s not working as expected.

1 Like

Documentation is on-point here, the Sound is in an Attachment so it should play in 3D. It doesn’t say anything about ancestors. There is no bug here.

This use case seems really quirky / bad practice, you might want to file a feature request instead and explain more clearly why you are trying to do whatever you are doing this way.

1 Like

Did you tested the repro file or looked at my Code?

local function play2D() 
	print("play2D")
	Sound.Parent = script
	Sound:Play()
end

you must have missed something :upside_down_face:

1 Like

Ah, your code sample is confusing because there are no comments. I interpreted this as “play2D – this plays in 2D and that is wrong”.

If you add a Heartbeat:Wait() between the parent and play call, does it play as intended? It might be processing the Play call before it sees the updated ancestry.

I think the function names are descriptive enough,
play3D and play2D is pretty straight forward, please let me know how I can improve it or you can go ahead and do that, irrc Community Sage has access to do that. :grinning:

I tried that it doesn’t work.

1 Like

I’ve experienced this issue for myself long before this post was made. The issue here is that the sound simply doesn’t update to a “2D” (or global) state whenever the Parent is updated to not be in an instance that has positional data (and maybe vice-versa, but I didn’t verify that). Fixing this is really just one line of Sound:Pause() Sound:Resume() or otherwise stopping the audio, which would then properly update the Sound.

2 Likes

Thank you for your insight, this is good to know!

No, it only becomes a problem when doing 3D to 2D

While that may work it causes other problems like firing .Paused / .Resumed / .Stopped for no reason

so this should be fixed regardless,

and doing Sound.Playing = false before Sound.Play doesn’t fix it

while performing

works but it causes problems while using CollectionService

1 Like