fmod-gdextension icon indicating copy to clipboard operation
fmod-gdextension copied to clipboard

Plans for Godot 4.0 and forward.

Open CedNaru opened this issue 1 year ago • 4 comments

Godot 4.0 and its new extension system is an opportunity to improve how this plugin is structurally made. In the current Godot 3.x era, the way to go is relatively straightforward: There is one FMOD singleton and every operation is done through it. We all interact with the entirety of FMOD with that singleton, either referencing entities only by their string identifier or some integer returned by a few of the functions (the case for event instances) which in reality is literally the memory address of the instance. On top of that, we have plans to have Nodes for ease of use (with one already implemented by @bitbrain)

The goal is to split the plugin into 2 layers with a more object-oriented mindset :

  • A "low-level" layer implementing every FMOD entity as its own Godot extension of either Object or Refcounted. EventInstance, banks, sounds, event descriptions, buses, and more... They are all going to be actual classes. More global functions/settings will remain in the FMOD singleton. Everything related to the native FMOD API should be done in those classes. Put another way, it's just a set of wrappers to expose the FMOD library to Godot.
  • A "user-friendly" layer using the low-level one to implement Nodes that can directly be used in Godot Scenes. They will be heavily inspired by the Unity implementation of FMOD. EventEmitters, Listeners, Bank loaders are the obvious candidate to implement.

Most people should be able to do what they wish using Nodes only but the low-level layer would still be available for the ones wanting a more custom behavior.

Discussions are open of course, and the future implementation of it should start after #https://github.com/utopia-rise/fmod-gdnative/pull/123 is merged so we keep its size relatively small. That first step should be to make the plugin run in Godot 4.0 using the "old" model.

I can also foresee ambiguity between what should be put in the low-level or user layers. One example just to boot the discussion but not the only one of course: EventInstances can be used as OneShot, which currently are handled a bit differently in the code (automatically released). In those cases, there are 3 "main" implementations. -Memory management in the low-level layer with EventInstance simply having an isOneShot property -Memory management in the low-level layer with 2 different classes inheriting the same abstract class for the regular events and one-shot events. -Memory management only in the user Nodes, everything is manually handled inside the low-level layer.

Might seem trivial but the idea of "low level" is not really the same between a C++ library and an editor plugin with scripts. So it's better to clearly define it.

CedNaru avatar Oct 01 '22 11:10 CedNaru

As discussed an FmodAudioServer that can be accessed via getSingleton() might be a great foundation. This server then could be used to implement all other nodes accordingly. The main difference to the 3.x approach would be that we do not require an autoload singleton at all. Instead, we'd have some sort of thread that runs the server and we could use signals to sync with the Godot main threads.

bitbrain avatar Oct 08 '22 10:10 bitbrain

I don't think it's necessary to have a FmodAudioServer running on its own thread. Fmod is already running on its own set of threads so in a sense it's already its own server. The FMOD API exposed by its libs is just a way to send commands to those threads. There is no real benefit in adding one extra layer of thread, it would just add more latency and a need for synchronization.

CedNaru avatar Oct 08 '22 17:10 CedNaru

@CedNaru this means however that we will have to rely on an autoload singleton still - unless there is another way to somehow connect to the Godot process thread to update the callbacks.

bitbrain avatar Oct 08 '22 19:10 bitbrain

I think it will be something like FmodManager becoming a regular node, not an autoload. You would add a single instance of that node in your scene tree and with the new extension system users will even be able to give it a custom behavior by adding a script on top of it. It's useful, not only for callbacks like process but for other kinds of events like handling unfocusing the windows, taping home in android, and pausing the game.

You can also just make the FmodAudioServer connect to the SceneTree.process_frame signal so you can still have a default update loop.

You can see that like something similar to nodes like Viewport, Camera, and WorldEnvironnement. You always have one basic default one in Godot even if you add nothing to the scene tree yourself. Their behavior is then immediately replaced by the first node of those types added to the tree.

CedNaru avatar Oct 08 '22 19:10 CedNaru