Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Loading ScriptableObject via script

Discussion in 'Scripting' started by maormenashe, Feb 14, 2019.

Thread Status:
Not open for further replies.
  1. maormenashe

    maormenashe

    Joined:
    Oct 7, 2018
    Posts:
    20
    So ScriptableObject is a good way to store data, but how do i load it?

    Using AssetDatabase only works with the editor,
    Using Resources should be a last resort since it slows down the game ..
    and i don't want to reference it via the inspector, i want it to be loaded dynamically.

    I saw this thread: https://forum.unity.com/threads/loading-scriptable-objects.431583/
    Is using the Assetbundle really is the best option?
     
  2. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    Yeah, pretty much. But it doesn't mean you need to take that option. Unity sometimes does put you in a hack n slash position on clean architecture. You can either have them in resources folder, or an asset bundle, or inspector, or service locator singleton. It depends entirely on your project. I can't really give good advice without seeing what it's being applied to.

    The main options are (and their points), are:

    1. Resources folder - (Will it REALLY slow the game down that much? Publish a build and check the profiler, you might find the slow down is SOOOO small you can't even see it in the radar amongst the textures, draw calls, and other CPU/GPU usage).
    2. Asset Bundles - (You can put all of them into one bundle and keep them in your streamingassets folder). The annoying thing to this is then playtesting the game in fast increments. Each time you'll need to re-build the asset bundle when there's a change made). However they can be really powerful. Plus when there's a code change to the ScriptableObject (not inspector value change, but actual source code), you'll need to re-build the asset bundle.
    3. Service Locator Singleton - Create a MonoBehaviour singleton which holds all references to them, and has "DontDestroyOnLoad" method called on it, and have a static reference. Really this is doubling up on 2 potential anti-patterns here. The singleton and the service locator, but there's a reason why the patterns exist as well. See whether it fits your need.
    Really going to town on option 3. Instead of referencing a MonoBehaviour singleton. You could instead drag into the inspector a ScriptableObject which contains all the references to ScriptableObjects. Or create a single asset bundle which contains every ScriptableObject, and then just don't unload it till the end of play. I mean there's actually loads of options.

    That's my 2 cents at least :).
     
  3. maormenashe

    maormenashe

    Joined:
    Oct 7, 2018
    Posts:
    20
    Thanks for the detailed answer.

    I think for my situation i'll run some tests using the Resources, and if that fails i'll just go with the AssetBundle option, even thou building will be a pain ..
     
    Nigey likes this.
  4. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    I agree totally. Generally the most direct route is the fastest. Just look at the real world consequences and see what's happening with Resources and see whether it's liveable or even noticeable. For textures/models ect, resource unloading can be lengthy. Plus Unity can't compress them into the type that is most optimal for the build, and so keeps them in their original state. But a ScriptableObject is a ScriptableObject. So yeah, take a gander definitely.
     
  5. MADiFold

    MADiFold

    Joined:
    Aug 10, 2018
    Posts:
    10
    Your idea on a central so with reference is used around the globe..issue I am having with it though, is loading data from a so that you retrieve from the so...
     
  6. gaps

    gaps

    Joined:
    Jan 1, 2014
    Posts:
    12
    Sorry about the late reply, but only now I had the same issue and found this thread...
    What about having the scriptable object asset added to the preloaded assets?
    And when it loads, it registers itself in some way (I'll just go with the singleton pattern).
    Plus some editor code to automatically create the asset when the editor starts/reloads/whatever (if it doesn't exist at a specific path in the project) and add it to the preloaded assets (if it's not there already).
    I'm going to try this approach now.
     
  7. gaps

    gaps

    Joined:
    Jan 1, 2014
    Posts:
    12
    Well, I have a self contained script that could be generalized, and has ugly #if's, but it seems to work :)
    Feel free to point me any inefficiencies or things that are not completely correct or if there is a better way of doing something.

    When outside the editor it relies on an asset being in the preloaded assets, so that its OnEnable method is called, which registers its instance in the singleton.

    When in the editor, it calls a load method which creates the instance, saves the asset in the project, and adds it to the preloaded assets list. This load method is called in multiple occasions just to make sure the asset is created:
    - When assemblies are reloaded (in other words, when the editor starts and when the scripts are edited) - via the UnityEditor.InitializeOnLoadMethod attribute;
    - When the game starts - via the RuntimeInitializeOnLoadMethod (this will guarantee that it exists even if you deleted the asset meanwhile)
    - Each time the Instance is required (same as above, except that this could fail if called under certain conditions, hence the one above that should work always).

    Have fun :)

    PS: I was in Unity 2019.3 when I wrote this, but I think it should work in 2018.4 as well. Worst case scenario, it will need a minor adjustment.
     

    Attached Files:

    Last edited: Dec 20, 2019
  8. BugiGames

    BugiGames

    Joined:
    Oct 20, 2020
    Posts:
    9
    https://github.com/Eduard-Malxa/Load-Scriptable-Object-From-Script-Unity
    Here is my method you can load Scriptable Object, from script, without drag and drop the SO, in any MonoBehaviour and also you can have it in simple C# class
     
  9. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    What is your point to doing it? I just wondering because from my understanding (i am beginner) biggest benefit of SO is to reference it via inspector so then you can customize your data without touching your code.
    I create SO in code like this but i still need reference in my first script
    Code (CSharp):
    1.  
    2.   private void CreateButtons()
    3.     {
    4.         foreach (var VARIABLE in menuButtons)
    5.         {
    6.             UiButton_DisplayPanel_SO_Component.Create(transform, VARIABLE, middlePanelTransform);
    7.         }
    8.     }
    Code (CSharp):
    1.    public static UiButton_DisplayPanel_SO_Component Create(Transform buttonParent, UiButton_DisplayPanel_SO uiButtonSo,
    2.         Transform parentOfDisplayedContent)
    3.     {
    4.         Transform placedUiButton = Instantiate(uiButtonSo.uiButtonSOPrefab, buttonParent).transform;
    5.         UiButton_DisplayPanel_SO_Component uiButtonComponent =
    6.             placedUiButton.GetComponent<UiButton_DisplayPanel_SO_Component>();
    7.         uiButtonComponent.Setup(uiButtonSo, parentOfDisplayedContent);
    8.  
    9.         return uiButtonComponent;
    10.     }
     

    Attached Files:

    • asd.png
      asd.png
      File size:
      39.5 KB
      Views:
      48
    Last edited: May 8, 2023
Thread Status:
Not open for further replies.