Search Unity

Question Best practice to allow managing complex arguments for script nodes in the editor UI

Discussion in 'Visual Scripting' started by alexpaulr, Feb 3, 2022.

  1. alexpaulr

    alexpaulr

    Joined:
    Jan 10, 2022
    Posts:
    4
    Hello community,

    I've been struggling to come up with a good solution for my problem, especially with regard to UX for logic flow designers.

    In my current project, I want to model logic flows that control the state of multiple audio samples in an auditive scene. Depending on certain conditions that I model mainly with script graphs eventually I want to make a call to a static function SetSampleState (represented by a script node in my graph) that receives a list of objects, each item containing a reference to an audio item and a set of key-value pairs, describing the desired state for each audio item in the list (e.g. volume, pitch, sequencing information). A call to SetSampleSet would then smoothly transition the states of the listed audio samples from their old to their new state.

    My problem is that I have this potentially big object that describes the desired that I want to pass as argument to the SetSampleState node - and I want to be able to edit this object in a good way using the editor. The reason for me wanting to have one single state object with a list of samples and their audio parameter settings instead of using one script node for each sample and each of its audio parameters that I want to set is mostly UX and readability of my visual code. It just feels unintuitive and unclear to someone maintaining these settings to have something so cohesive as a state description for single event being spread out across so many nodes on the script graph.

    I tried using the Inspectable attribute for my state argument, so I can edit the data on the Graph Inspector (which would be acceptable), but the Editor UI also renders on the node itself and I cannot see myself fixing this mess even with a custom property drawers, mainly because of the limited width of the script nodes. Would it be possible to disable or alter rendering for the Editor UI depending on whether it is being rendered in the Graph Inspector or inside of a node on the node canvas to mitigate this?

    upload_2022-2-3_15-39-51.png

    Ideally though, I would like to be able to just click on my SetSampleState node and then edit the state argument in my regular Inspector (the one that sits outside of my Visual Scripting Graph). I followed a different approach and made SetSampleState accept a ScriptableObject instead of an inspectable class. ScriptableObjects open in my inspector and I generally like the approach, but I don't want to create a ScriptableObject asset in my project file directory for every single request to change the audio state (as there will be many). So basically I want to embed the ScriptableObject into the script node where it is used. I tried instantiating a new ScriptableObject in the custom unit's Definition method, but I get errors ranging from "You cannot instantiate a ScriptableObject on this thread" to "You cannot do it in the Definition method because it f***s with serialization". So would it be possible to instantiate a ScriptableObject together with a custom unit (and if yes, where in the units lifecycle using which instantiation method) and will I be able to serialize the SO together with the Script Graph?

    upload_2022-2-3_15-50-22.png

    Something like this I want to achieve, without having to save every ScriptableObject as asset, but rather instantiating and serializing them together with the SetSampleState node instances.

    I'm rather new to Visual Scripting, but also fairly unexperienced with Unity (and especially with advanced topics like component lifecycle and serialization), so I would highly appreciate every bit of information or best practice advice that gets me closer to a well working solution.

    Thank you so much!
    Cheers,
    Alex
     

    Attached Files:

    Last edited: Feb 3, 2022
  2. Trindenberg

    Trindenberg

    Joined:
    Dec 3, 2017
    Posts:
    398
    So you want your node to contain an array of AudioClip each with an array of possible AudioSource settings? As in, entering the state, goes through the list and changes the params on the AudioSource (for which you would need a target)?
     
    alexpaulr likes this.
  3. alexpaulr

    alexpaulr

    Joined:
    Jan 10, 2022
    Posts:
    4
    Hey Trindenberg,

    thank you for your response.

    To be honest, I'm not so much concerned about how my application data model is made up (which in my case are audio parameter settings), but I rather stated it as context and as explanation for why I want to be able to configure a non-trivial, nested data object from within a visual scripting graph.

    As can be seen in my first screenshot the UI glitches as the list of objects (that potentially could have nested children further down development) is being rendered inside of the unit body. I thought that one possible approach would be to
    a) change the width of the unit body or
    b) prevent rendering the editor GUI inside of the unit body to rely on using the editor GUI in the graph inspector side bar.

    The second approach I tried to go for was making the audio settings class inherit from ScriptableObject, which would result in a drop field on the unit body inside the graph editor and the scriptable object being editable in the global inspector tab. However, for this approach to work I would have to either
    a) manually create a ScriptableObject asset in my project directory (which I don't want to, because it could be thousands of individual sample states) or
    b) instantiate and serialize a data structure (e.g. a SO instance as default value for my node's input) together with its respective node/unit on the script graph (for which I don't know the correct lifecycle methods of the Unit class and the general approach of how to (de-)serialize this data together with the script graph.

    I hope I could further elaborate on which problem I want to solve.

    Thanks!