Why Aren't The Sounds in my Sound Group not working? - lua

I was trying to make a music player for my game, however, when I was trying to get my sound to play it refused to work. The games output works before and after the sound, but I can't hear anything. I tried using both a folder and sound group (what I'm using currently) and both did not work. How would I fix this? I presume it has something to do with client-server but I am not sure.
local ss = game:WaitForChild("SoundService")
local rp = game:WaitForChild("ReplicatedStorage")
local list = ss.Music:GetChildren()
rp.SongOn.OnServerEvent:Connect(function(plr)
repeat
local num = math.random(1, #list)
print(num)
local track = list[num]
local name = track.Name
print(name)
plr.PlayerGui.Overhead.Notch.SongTitle.Text = track.Name
local song = ss.Music:WaitForChild(name)
print("played")
wait(track.TimeLength)
print("waited length")
until
rp.SongOff.OnServerEvent
end)

You never play anything. You don't actually reproduce the Sound. To run a Sound, use Sound:Play()
https://create.roblox.com/docs/reference/engine/classes/Sound
Your repeat until condition is also wrong. The music will not stop playing once that event is fired, and it will actually not matter at all - when the loop finishes running once, it will compare if literally rp.SongOff.OnServerEvent evaluates to true. OnServerEvent is the literal event itself, which will be true since it is not false or nil. So the loop will stop running when it runs once.
Instead, you likely want to make a function that plays the music, and run this function whenever:
Playing music is requested with the remote
The playing music naturally ends (https://create.roblox.com/docs/reference/engine/classes/Sound#Ended)
And then, bind to that stop music remote a function that stops the sound.
Also you should have some more shame, you didn't even try to hide you're making a nazi game

Related

My LoadCharacter() Script Isn't Working Properly

I am trying to make a LoadCharacter() script, but when it runs it makes the player load several times before they actually load.
Here is the code:
game.Players.PlayerAdded:Connect(function(player)
game.ReplicatedStorage.Remotes.LoadCharacter.OnServerEvent:Connect(function()
player:LoadCharacter()
end)
player:LoadCharacter()
end)
BTW I disabled CharacterAutoLoad.
Your issue is that your connection is inside the PlayerAdded event. It is causing the event to register callbacks every single time a player joins. So when any player fires the event, it is causing EVERYONE to reload their character.
So just move the connection outside it, and get the player object from the RemoteEvent. The first argument from OnServerEvent is always the player that called FireServer so you don't need to make any changes to your LocalScript.
game.Players.PlayerAdded:Connect(function(player)
player:LoadCharacter()
end)
game.ReplicatedStorage.Remotes.LoadCharacter.OnServerEvent:Connect(function(player)
player:LoadCharacter()
end)

Why only does idle play from my animation script?

So I'm making a custom animation script for a custom character on Roblox. The AI works fine but it will almost always only play idle animations even with humanoid events.
What should normally happen is when the monster is Idle the idle animation should play. When walking the walk animation should play. And when the AI attacks, the attack animation should play.
I've dried commenting out the idle animation part, but then no animations play at all.
Here's the code:
local myHuman = script.Parent.Humanoid
local walkAnim = myHuman:LoadAnimation(script.Parent.Walk)
local idleAnim = myHuman:LoadAnimation(script.Parent.Idle)
local jumpAnim = myHuman:LoadAnimation(script.Parent.Jump)
myHuman.Running:Connect(function(speed)
if speed > 3 then
walkAnim:Play()
else
walkAnim:Stop()
idleAnim:Play()
end
end)
myHuman.Jumping:Connect(function()
jumpAnim:Play()
end)
myHuman.Died:Connect(function()
for i,v in pairs(myHuman:GetPlayingAnimationTracks()) do
v:Stop()
end
end)
Try adding a print instead of the animation and see what happens and tell me if it prints anything.
myHuman.Running:Connect(function(speed)
if speed > 3 then
print("walk")
else
print("start idle")
end
end)
Edit: https://devforum.roblox.com/t/getplayinganimationtracks-is-deprecated/1075650 I believe that you must do
myHuman.Animator:getPlayingAnimationTracks()

Playing random audio files in sequence with AKPlayer

I am working on a sort of multiple audio playback project. First, I have 10 mp3 files in a folder. I wanted AKPlayer to play one of these audio files randomly, but in sequence - one after the other. But playing a random file after another random file seems to be tricky. Here's what I've written:
let file = try? AKAudioFile(readFileName: String(arc4random_uniform(9)+1) + ".mp3")
let player = AKPlayer(audioFile: file!)
player1.isLoopiong = true
player.buffering = .always
AudioKit.output = AKPlayer
try? AudioKit.start()
player.start(at: startTime)
This code loops the first chosen random file forever - but I simply wanted to play each random files once. Is there any way I can reload the 'file' so the player starts again when it's done playing? I've tried calling multiple AKPlayers (but calling 10 players must be wrong), if player.isPlaying = false, sequencer, etc, but couldn't exactly figure out how. Apologize for such a newbie question. Thank you so much.
AKPlayer has a completion handler
to be called when Audio is done playing. The handler won’t be called
if stop() is called while playing or when looping from a buffer.
The completion handler type is AKCallback, which is a typealias for () -> Void. If you have some good reason not to use 10 AKPlayers, you could probably use the completion handler to change the file and restart the player. But you could also create an array with 10 AKPlayers, each loaded with a different file, and have a function that selects a player at random for playback (or that cycles through a a pre-shuffled array). The completion handler for each player in the array could call this function, when appropriate. As per the doc quoted above, make sure that the AKPlayer is not looping or else the completion handler won't be called.
yes, you can use the completionHandler of the player to load a new file into the same player when playback finishes. In your completion block:
player.load(url: nextFile)
player.play()
Another approach is to use the AKClipPlayer with 10 clips of a predetermined random order and schedule them in sequence. This method will be the most seamless (if that matters).

Corona / Lua Function scope

I'm new to Corona. I'm not sure how to solve this.
In main I am creating 2 local objects, player and enemy.
Player has a function called takeDamage.
When I try to call player.takeDamage from within enemy, it can't see the function.
I presume it's because main owns both objects and they don't know about each other.
How can I have Enemy call that function so that it can deal damage to Player?
main.lua contains:
-- Create player character
local player = require("player");
player = player.new();
-- Create enemy character
local enemy = require("enemy");
enemy = enemy.new();
I think I could make player global, but from what I know, that would not be a best practice.
Any help would be greatly appreciated.
If it is safe to assume that there will be only one "player" instance, you can make it global. Otherwise, you would have to do something along these lines:
-- main.lua
local player = require 'player'.new()
local enemy = require 'enemy'.new()
enemy:setPlayer(player)
-- enemy.lua
...
function enemy:setPlayer(player)
self.player = player
end
And later use self.player in the enemy code to reference the player. Note that this will consume memory, because the player reference will be copied to every enemy instance.
One side note, I do not consider it good to call a module and an instance the same, i.e. player. It will become unclear later if you mean the module, or the instance. A safe way would be to call the modules as Player and Enemy, and the code will look like this:
Player = require 'Player'
local player = Player.new()
Ideally, you don't want the player referencing the enemy directly or the enemy referencing the player. Instead, you could poll each participant in a game loop and update the game state based on the result.
local player = make_player()
local enemy = make_enemy()
--game loop - in a real game this isn't a busy while
while true do
local move = player.move()
local result = validate_move(move)
if result.is_valid then
update_position(player, result)
end
move = enemy.move()
result = validate_move(move)
if result.is_valid then
update_position(enemy, result)
end
local attack = player.attack()
local attack_result = validate_attack(attack)
if attack_result.hit then
update_health(enemy, attack_result)
end
-- more game logic here
render(player)
render(enemy)
end
In a real game, state change would be driven by events - touch events, drawing events, etc. My busy loop (while true do) illustrates the general idea.
You'll also have to use your imagination for missing implementation.
There are many ways to model a game. I'm not suggesting this is the best. It does, however, show one way of decoupling interacting elements.

receive microphone sound without hearing it

This captures microphone sound and changes the alpha of 'foo' according to the sound level. However, I hear the microphones input. I want the visuals to work without hearing any sound. How would I do that?
m = Microphone.get();
_root.attachAudio(m);
m.setVolume(0); //i can still hear sound. does not mute mic.
onEnterFrame = function () {
foo._alpha = m.activityLevel+33;
};
EDIT: ANSWER / SOLUTION
series8217's trick with setLoopBack did not work, but that led me to the answer online:
m = Microphone.get();
var myAudio:Sound=new Sound(attachAudio(m));
myAudio.setVolume(0);
thanks for your time
EDIT: OTHER SOLUTION
my trick may interfere with sound. using this, mutes the mic but flash still receives input:
m = Microphone.get();
m.setSilenceLevel(100);
Switching the loopback mode on the microphone object should do the trick.
m.setLoopBack(false);
However, if that doesn't do it, perhaps your OS sound settings have monitor or loopback mode turned on. I'd say look into that before trying setLoopback().

Resources