Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serverside Sound System #49

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft

Serverside Sound System #49

wants to merge 10 commits into from

Conversation

Kulltero
Copy link
Contributor

@Kulltero Kulltero commented Nov 11, 2022

Adding a Server controlled Sound System

Summary
this fork adds a way to play sounds on the client & load new sounds from the web, it currently supports:

  • Loading sounds by URL to create custom Sound Definitions

    • allows making sounds loopable
    • allows setting the category of a sound, setting the volume to respect a player's setting
    • allows adjusting pitch, random pitch offset & random volume offset
    • allows setting custom curves Audio, Spatial Blend & Spread
  • Triggering Sounds via RPC call & UI Component

    • supports fadeIn & fadeOut when stopping sounds
    • trigger sounds via UI on Hover or Click, optionally stop sounds on HoverExit
    • allows playing Rust's existing SoundDefinitions
    • allows parenting sounds to entities or Placing them at a static position in the world
    • allows setting custom Max Distance & Doppler Scale
  • you can see a demo of its features here ⇒ https://streamable.com/dc8vp3

Why?

Giving devs a way to reliable & controlled way to play sound effects
the somewhat recent changes to gun sound effects & the crazy amount of people being upset over it tells us that sound & sound effects matter.

Until now, as a plugin developer, it was tedious & limiting to add sound to your mechanics.

You could play some Rust sound effects via the effect network, create a hidden NPC & send sound as voice packets, or make use of Radios & Cassettes to play sounds from the web.

However, this brought along a large amount of limitations on both the quality, timing & performance of the sound & its experience.

The Breakdown

this fork has 2 parts:

  • The Sound System
    • this system handles the RPC calls & loading sound files
  • the SoundTrigger component
    • Attaches to a UI Panel & listens to mouse events like Click & Hover

There are 3 RPC calls that a server can use with the Sound System.

RPC: AddSoundDefinition

[{
  "name":"nameOfYourDefinition",
  "url": "https://page.tld/path/to/your/file.wav", // supports some other filetypes aswell
  "loop" : false, // if true the sound will loop and wont stop until you manually do so
  "category" : "voice", // sets the volume setting to use
  "repeat" : 5, // how often to repeat the animation, optional (Default = 0), set to -1 to repeat indefinitely
  "volumeDiff" : 0.0, // the random volume offset each time the sound is played
  "pitch" : 1.0, // the pitch of the sound
  "pitchDiff" : 0.0, // the random pitch offset each time the sound is played
  "falloffCurve" : [ // sets a custom curve to use
    "0 1 0 0", // each item in the array is a string of 4 floats from which a keyframe is constructed
    "1 0 0 0" // these keyframes are turned into an AnimationCurve which controls the custom curve
  ],
  "spatialBlendCurve" : [ // curves are scaled from 0 to 1, then scaled to the maxDistance of the Audio Source
    "0 1 0 0",
    "1 0 0 0"
  ],
  "spreadCurve" : [
    "0 1 0 0",
    "1 0 0 0"
  ]
}]

To Facepunch: see the EditorTools folder, which contains a tool that lets you create test cases, this tool will produce the same json representation from the data you give it in the inspector.

RPC: PlaySound

[{
  "instanceName":"nameOfYourSoundInstance",
  "definition": "nameOfYourDefinition", // to play a Rust sound instead, give it the asset path (starting with assets/content/...)
  "fadeIn" : 0.1, // fades in volume over time
  "parent" : 61340, // the net id of the entity to parent the sound to
  "offset" : "0 0.3 3", // the position to offset your sound, if a sound isnt parented and has no offset it will act as a first person sound
  "maxDistance" : 150.0, // the max distance the sound can be heard from, custom curves in the sound definition scale by this amount
  "dopplerScale" : 1.0, // the scale of the doppler effect when moving towards or away from the sound (if not first person)
}]

Every RPC call accepts an array of json objects instead of just an object

RPC: StopSound

[{
  "instanceName":"nameOfYourSoundInstance",
  "fadeOut" : 0.1, // fades out your sound before stopping it
  "kill" : true, // decides if the sound instance should be killed, if its killed any follow-up calls to StartSound will have to recreate the sound, whereas otherwhise it would just replay the existing sound instance
}]

UI Implementation

This fork adds the SoundTrigger Component which can play multiple sounds based on mouse interactions, you can attach it to any panel & it will react to click & hover events on it or its children.

{
  "type": "SoundTrigger",
  "sounds": [
    {
      "trigger": "Hover", // trigger type, either "Hover" or "Click"
      "definitionToPlay": "assets/content/sound/sounddefinitions/entities/helicopter/helicopter-rocket-fire-single.asset", // the definition name you created or the path to the Rust asset
      "fadeIn": 0.1,
      "killOnExit" : false, // if false it will play the sound until its done, if true it will fadeOut/stop the sound when unhovering the panel
      "fadeOut": 0.2
    }
  ]
}

Note: the sound trigger requires the MouseListener from the Animation Pull Request

Issues, features I couldn't implement & a note on my test setup

I can't guarantee that this will be a flawless implementation because of the way I chose to create my test setup.

When making this feature, I didn't want to recreate what rust already has, so working with the “Sound” and "SoundDefinition" classes was the obvious way to go since it would also allow us to play Rust's sounds.

To recreate this I ended up using a mix of code from the server DLLs, current client DLLs (decompiled into stubs) and decompilable client files from back in 2018, since that was before rust changed to IL2CPP.

So while I did get it working, there were some bugs in my test setup that I couldn't confirm would appear in the final implementation:

maxDistance gets set to 500 every frame

I couldn't find anything in the code I used or online about why this happened, but it happens both when setting it via the editor or via the JSON property.

The falloff Curve stayed at logarithmic even when setting a custom falloffCurve

The falloff custom curve does get set, when manually switching it over to custom curve it will use the curve that was set, but I wasn't able to find out why this doesn't happen automatically.

On a note of features I couldn't implement, there are 2 things that may need some attention
When setting the category for a sound, I simply set the volume of the SoundDefinition, but this probably isn't how sound settings are actually used in rust, so I'd recommend changing it to match the real implementation.

A feature I would have loved to implement is the ability to prevent Rust's in game music from playing if we want to play our own.

I didn't want to alter the user's setting directly, so something like a ConVar is probably a better way to add this feature.

wrapping up

The sound system should be a solid baseline for developers to play their own sound effects & gives us access to a lot of Rust's great sounds.

There could be some hiccups though when implementing it due to my lack of knowledge on rust's sound system.

adds the methods & RPC calls to Add new SoundDefinitions, play & stop sounds
adds the ability to load a soundfile from the internet
this should allow you to test the entire Sound Feature set, also includes a few presets to recreate the test cases i had used
missed that one
it really isnt needed since we can simply check if the path starts with "assets"
removing the redundant definitionType variable, changed the FindDefinition function to also attempt loading from the file system if the path starts with "assets"
this will listen to mouse events like hovering & clicks, letting us define sounds to play when an element gets hovered
supports fadeIn & fadeOut
killOnExit defines whether the sound should be played as a oneshot or stop instantly when the player unhovers
note: this does require the MouseListener from the Animation pull request
@Kulltero Kulltero marked this pull request as draft May 17, 2023 01:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant