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

Question Custom type available throughout project

Discussion in 'Scripting' started by XJonOneX, Jun 20, 2023.

  1. XJonOneX

    XJonOneX

    Joined:
    Dec 19, 2017
    Posts:
    69
    So I've got a class with my custom type, and I need to be able to reference it throughout my project. Currently it's in its own .cs file marked as static, and I have a using static statement in each script to reference it.

    Is this a good usage scenario for a static class, or is there a better way to do it?
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,899
    Let's just say that a static should be avoided unless there is no better way. And there is, almost always there is a better way. Typically in those scenarios users will start to use singletons, also a static.

    In Unity specifically, you will want to disable domain reload so you can enter playmode instantaneously. This starts to break when introducing static state, and requires you to carefully reset that static state (see manual). Hence it makes a whole lot of sense to avoid static state in Unity. You may not think that the 1-2s delay to enter playmode won't matter much, but it will, and it's going to take longer and longer as the project grows in size.

    Most of the times you can replace a static with a ScriptableObject instance in Unity. In other times, it's just as easy to use only static methods (no state) or create separate instances of the object with its state separated to either a ScriptableObject or Editor/PlayerPrefs or some other way to persist data (json, database).
     
    Ryiah and Bunny83 like this.
  3. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,588
    Maybe you could give us a bit more context on what's in that file and why you believe you need it globally everywhere? This approach makes your code less modular and thus usually ends up in tangled spaghetti code. Which approach, if any, would be better suited depends on the use case in the first place.
     
    Ryiah and Bunny83 like this.
  4. XJonOneX

    XJonOneX

    Joined:
    Dec 19, 2017
    Posts:
    69
    Thanks for the replies.

    @Yoreki, I'm making a Match 3 game, and I have all sorts of data stored in a class called Block. It contains necessary info to identify it's color, type, destination (for Animating purposes) among other things. It also contains a reference to the Game object, and I have a helper method to retrieve the block instance by searching thru the Game object references.

    At the moment I have three scripts that use the Block class: the BoardManager, AnimationManager and an EventManager. BoardManager handles the state of the board and also updating data of Block instances. AnimationManager handles the movement of blocks on the board. EventManager, well, has all the event system stuff in it.

    I figured it would be best to be able to pass around the Block class into methods for updating the data and moving blocks around the board. I didn't want to be constantly calling my helper method to retrieve the block instance from the Game object reference. It seemed like unnecessary overhead to me. So I (reluctantly) put it in a static class, and added a using on each script that needs the Block class.

    I used to have the Block class on each block Game object instance, but I was using Getcomponent a ton and after my project got to a certain size, I refactored it into a separate class, then as I was refactoring other code, I realized I needed the Block type to be available across my scripts.

    I'm sure there's a more elegant way... Any ideas?
     
  5. icauroboros

    icauroboros

    Joined:
    Apr 30, 2021
    Posts:
    99
    I assume your block class is a component on tiles that hold tile data and methods.
    if it is, my question is why you holding gameobject references, instead of directly referencing block components?
    Also you can access gameobject from component with no performance overhead.
     
    Bunny83 likes this.
  6. XJonOneX

    XJonOneX

    Joined:
    Dec 19, 2017
    Posts:
    69
    No, my Block class is not a component on the Game objects. Like I said, it used to be, but I was using Getcomponent a ton to reference the data, and I wanted to move away from that.
     
  7. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,588
    Im not sure i follow. If the Block is not the gameobject, why has it functionality to identify the color? The objects on the board, which you are trying to match in your game, should have the necessary scripts to provide the functionality they need. If there is some static global constant or smth, that can easily be globally referenced. Any other script which needs information about these objects should have a reference to the particular object in reference. I dont know why some static Block object would somehow be required to handle the color identification and animations of the actual gameobjects, or why they couldnt do that themselves.

    If that does not help you or you believe it does not apply to your architecture (but believe it to be good architecture), you could post your Block class and potentially other relevant parts, so we can have a closer look at it.
     
  8. XJonOneX

    XJonOneX

    Joined:
    Dec 19, 2017
    Posts:
    69
    I'm not at my dev machine atm (yay 9-5) so I can't post any code.

    My issue boils down to this: I need to store data about each block: color, type, etc that I need to retrieve in different Managers.

    I had a Block component on each Gameobject, but found I was relying heavily on the use of GetComponent() to retrieve Block data, which from what I understand is bad. It wasn't in an update loop or anything, but could be called any number of times during any given frame. It was working just fine.

    So with GetComponent() being bad in mind, I moved it all over to it's own .cs file, not attached to a game object, and have a using statement in each Manager that needs to access the Block type.

    I'm coming from a Windows application background, so maybe I'm missing something about game design/code structure in general. :oops: I think I might be stuck in the MVVM brain space.
     
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    In what way is it bad? If it was a performance problem for you as you analysed in the profiler then that's fine but if it's just something you've read then I'd say it's premature optimization i.e. a solution looking for a problem.

    Obviously anything could be bad in this respect but it's why the profiler is there.

    I'd say do a quick mock-up and run it then look at the profiler to see what the hot-path looks like. Even better, do this on the device(s) you intend it to run on.
     
    Yoreki likes this.
  10. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,588
    I agree, unless you call it many, maaaany times per frame it's unlikely to have an impact. When in doubt, use the profiler to check if it's actually anything close to a problem. If you may call it twice on the same object per frame, store the reference. If you need to iterate this component anyways, depending on the usecase, you could store and manage a full list of blocks (references through this component) in the relevant managers. Just some things you could consider.
     
    MelvMay likes this.
  11. XJonOneX

    XJonOneX

    Joined:
    Dec 19, 2017
    Posts:
    69
    Thanks for the input guys. :) I'll check out how to use the profiler. It's been on my To-Do list for a while, now's a good a time as any.
     
    MelvMay and Yoreki like this.
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    Good stuff. You may be correct but better to check your situation before believing what others have said (as fact) when it's only really correct in their specific use-case.
     
    Yoreki likes this.