Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Best way to reference asset files in code

Discussion in 'Editor & General Support' started by ShiroAisu, Jul 27, 2017.

  1. ShiroAisu

    ShiroAisu

    Joined:
    Jun 21, 2017
    Posts:
    3
    So, I feel a bit of context is important for you guys to understand what I'm trying to do:

    In my game, I have a bunch of characters which have to refer to sprites. said characters are all tied to an interface with the different methods and behaviours they are to implement; something of this sort:

    Code (CSharp):
    1. public class NPCJonas : NPC
    2. {
    3.     Sprite spr_frightened;
    4.     Sprite spr_happy;
    5.  
    6.     // Interface's methods go here...
    7.     // Original methods go here...
    8.     // And so on...
    9. }
    This works really well when paired with a manager class, since then I don't need to have game objects for each of my NPCs polluting my scene, and I can just refer to them by an arbitrary id. Organized and effective, except for one detail: those sprites there will, of course, never show up in the inspector.

    Before I go any further, let me say that I already thought about scriptable objects; in fact, my very first implementation of the NPCs was done using scriptable objects, although the NPCs were much more uniform, and I didn't have to use any inheritance; when inheritance is needed in order to provide radically different behaviour between NPCs, however, scriptable objects just didn't seem to be adequate to handle the problem (unless I'm missing something, of course), since I'd basically have to have double the files for each NPC (one for the script itself, and one for the actual scriptable object), and that just seemed silly to me.

    Now, the original idea I had, was to simply get the assets in that NPCs constructor as the game was initializing, but I just don't know how to go about it. I've tried Resources.Load(), but it always gave me null, even with my resources in the resources folder.

    My current solution is to have another Image Manager game object which would have all the sprites in the game contained in an array, and from which I could get a sprite specifying an id. This works perfectly, but I can't help but wonder if it's the best way to do things; if I was programming an engine from scratch in C, this is definitely how I'd do it, but it just doesn't feel very "Unity-y", you know?

    Anyway, any help and opinions on my current approach would be appreciated.
    Thank you in advance.
     
  2. guillermoi

    guillermoi

    Joined:
    Sep 20, 2012
    Posts:
    27
    Hey.

    I guess the final answer will use ScriptableObjects, but lets start from the beginning:

    What is this manager class doing?
    How are you managing to not need game objects for the NPCs?
     
  3. ShiroAisu

    ShiroAisu

    Joined:
    Jun 21, 2017
    Posts:
    3
    The manager class is just an interface with the inspector so I can drop images through there and refer to them by ids at runtime. It's quite a simple class:

    Code (CSharp):
    1. public class ImageManager : MonoBehaviour {
    2.  
    3.     public static ImageManager imageManager;
    4.  
    5.     public Sprite[] sprites;
    6.  
    7.     void Start()
    8.     {
    9.         imageManager = this;
    10.     }
    11.  
    12.     Sprite GetSprite(int i)
    13.     {
    14.         return sprites [i];
    15.     }
    16. }
    As for the NPCs, game objects are not only needed, but are even troublesome, since there can only be one NPC "active" at all times whose graphics display on the screen. This NPC has to be referenced by the game controller, and if I had the NPCs as game objects I'd have to go around dealing with components (is requesting an interface component even a viable thing to do?), and this way I don't need to. I probably should've mentioned my game is a kind of text based sort of thing.
     
  4. guillermoi

    guillermoi

    Joined:
    Sep 20, 2012
    Posts:
    27
    Alright.

    You tried two ScriptableObjects. One for the actual NPC (this one maybe with NPC settings and the actual NPC code) and one for the NPC assets (sprites, audio clips,etc)??.

    You kind of liked this but you had two files for one NPC and this you didn't like. I think its actually not bad because you separate a bit the logic from the data and you could specify:
    • Two NPCs that behave differently (let's say one pure NPC and another SellerNPC : NPC) but they look the same (or at least they do at the initial stage of the development). So you create two ScriptableObjects for each NPC type but assign the same NPCData (same looks,audio) to them. You only had to drag and drop the sprites, AudioClips once into one NPCData.

    The more Unity way would be:
    • Open a new scene
    • Start adding GameObjects and components to design your NPC
    • Add your NPC component to the root GameObject
    • You create in the Project window your ScriptableObject with the data of the NPC (here we only have one ScriptableObject, the one for the NPC data, the NPC itself its not a SC)
    • You drag it into your NPC behaviour
    • Create a prefab out of this NPC you designed.
    • You add this new NPC to your Game/level/scene manager in the list of NPCs in that level or whatever.

    In this way the NPC is a component, which you want avoid. But you could separate the actual NPC code from the behaviour, and do your thing with the NPC as you want but when the time arrives to show/interact-with the NPC then you instantiate its "real body" (its prefab) and you pass the NPC class instance to the root NPCBehaviour : MonoBehaviour. Like putting a PowerRanger inside a Zord.