Sorry for not responding sooner, my idea became a bit more involved than I would have liked and I’ve done my best to explain it below.
Note that I’m not great at making things work well performance wise, however, the below code I believe works for your use case/issues.
Step 1: Create a SoundCue in the content browser.
a. In the SoundCue add a CrossFade by Param node and plug into this your ambient sound (pin 1) and your battle sound (pin 2).
I followed this post to figure out how CrossFade works and came up with the following settings. Note that I called the CrossFade param name ‘Duration’:
Step 2:
Create an actor Blueprint that will handle your Sound logic. I’ve called mine MasterSound_BP and drag this into your level somewhere.
Back in your MasterSound_BP class set the BeginPlay event like so:
Click on Add Audio Component and set the sound to the SoundCue created above.
If you run your game you should then find that the ambient music (whatever is in pin1 of the CrossFade) is playing automatically.
Step 3:
If you’ve not setup a Blackboard for your AI you can create one in the content browser by Right Clicking->AI->Blackboard.
In your Blackboard create a new Key with the following settings:
The Base Class is whatever you called the class created in step 2.
Step 4.
Replicate the following in your AI Controller class.
Here we set the Blackboard to use (Blackboard Asset is whatever you called it in Step 3).
We then do a check for if the Blackboard Key MasterSound is already set.
If True: Do Nothing
If False: Find the MasterSound_BP we added to the level and set this as the value of the key.
Because Instance Synced is set to true in the Blackboard key, the logic above results in us only having to run Get All Actors of Class once.
Step 5.
Back in the MasterSound_BP class create the following custom events:
Here we’re creating a timeline between 0 and 1 and interp between 0 and 1 at an interp speed of 0.001. (Note that someone with more experience in timelines would probably cringe at the above description and implementation as I’ve probably not explained it or implemented it right, but it does work).
This value is then fed into the SoundCue CrossFade parameter ‘Duration’ to crossfade between the ambient and battle music.
The check for the number of AI that found the player is done to stop the AI keep calling the function and the timeline keep being restarted. I.e. if one AI saw the player and then 0.1 seconds later another AI saw the player, without this check in place the timeline would run twice from PawnSeen.
There may be a better way of handling this but I couldn’t come up with a different solution.
You may also encounter a bug if PawnUnSeen is called and the count is set to 0 but a split second later PawnSeen is called (and vice versa), it will cause what will sound like a skip in the fade. This is only theory as I couldn’t test this. You’d need to come up with some additional logic to only start the TimeLine again once the previous TimeLine has finished.
The FadeInBattleTrack is just a timeline (Right Click → Search for TimeLine->Add TimeLine).
- You need to press the f+ button to create a new float track
- Change NewTrack_0 to a more meaningful name
- Make the Length 1.00
- Right Click in the float track and select Add Key to CurveFloat_(some number)
- Set the time to 0 and the value to 0
- Add another key and set the time to 1 and the value to 1
Step 6.
Back in your AIController class create a flow that’s similar to the following:
Let me know if there’s any questions on what the logic is doing here.
You may find that a retriggerable delay of 1.0 seconds is too short, so I’d suggest changing this value.