How to use Singletons in Unity3D without breaking everything...

Поделиться
HTML-код
  • Опубликовано: 23 дек 2024

Комментарии • 121

  • @diliupg
    @diliupg 5 лет назад +106

    Jason you must use a compressor on your microphone to keep the audio level consistent, and an equalizer to reduce some frequencies around 3000 - 5000hz.

  • @AnthelmeDumont
    @AnthelmeDumont 5 лет назад +2

    I really want to thanks you, every time I watch one of your videos I learn something new and I think it helps me to become a better developer.
    Keep the good work Jason.

  • @gregoryfenn1462
    @gregoryfenn1462 5 лет назад +89

    The audio has a bit of feedback and jumps, are you using a new microphone or sound software? Something isn't quite right!

    • @Unity3dCollege
      @Unity3dCollege  5 лет назад +27

      yea something went terribly wrong w/ the audio. It'll be fixed in the next one, sorry about that :(

  • @giggleghost3751
    @giggleghost3751 5 лет назад +30

    I love your content Jason, you are senior developer that this community needs to learn some good coding practices!
    I think it's about time you invest into a proper mic. Spend $100 - $150 on it. Get Blue Yeti or Samson G-Track Pro, both excellent USB mics. Your channel deserves good audio!

  • @nikolazagorac8634
    @nikolazagorac8634 Год назад +2

    There is a workaround for singletons, but if you are working on a team you must communicate how the system works. What you do is make your singleton base class abstract, add a protected abstract function called Initialize or OnAwake or whatever. Now also in the base Singleton class in the Awake function, after all the base class related code just call the Initialize function. So now all the child classes of the Singleton class require you to implement the Initialize function which is automatically called on the Awake function from your base class. Just make sure to never use the Awake function in your child classes. One step further would be to have a static function in your base class with the RuntimeInitializeOnLoadMethodAttribute attribute to automatically create an instance of your class when the scene loads.

  • @tarzanzabujca
    @tarzanzabujca 3 года назад

    So the main two points i got from it:
    1. Singleton makes stuff easier than:
    GameObject.FindObjectOfType() on every manager my game has, instead i have just static instance of one object, and i can event prevent duplicates :D
    2.
    static field values on MonoBehaviour are the same for ALL monobehaviours of same type, you dont have to cycle through every one to set one specific global value. hmm TIL :D
    TYVM for you hard work Jason! :D

  • @abwuds7208
    @abwuds7208 5 лет назад +4

    Great video Thank you! Please do a tutorial explaining the differences between caching components in OnEnable, Starts or Awake and the best practices around these methods... It would be so cool!

  • @clamum
    @clamum 5 лет назад +2

    Thanks for the video, Jason.
    For the AutoCleanupSingleton, on line 27, why do you call "Destroy(this.gameObject)" rather than "Destroy(_instance)"? Thanks

    • @rill3
      @rill3 3 года назад

      Saw this comment and I know it's old. But I wanna answer it anyway as someone else might have the question. He is destroying the "new" gameObject that was just created. The instance has the old gameobject that is the "true" source. So the new object is created and say "Hey, there is already someone here. Talk to this guy called instance instead and I'm gonna leave". Something like that.

  • @shannonrowe9402
    @shannonrowe9402 5 лет назад +1

    Good overview of the subject. I make quite a bit of use of singletons that involve double locking and a few other tricks to mitigate race conditions. In case it helps anyone, here's an extract that shows double lock usage and validation checks, with some comments:
    public class ManagerTemplate : MonoBehaviour where T : MonoBehaviour
    {
    private static object lockObject = new object ();
    private static volatile T instance;
    public static T Instance
    {
    get
    {
    if (instance != null)
    {
    return instance;
    }
    // Safeguard against calls after destroy has begun
    if (lockObject == null)
    {
    return null;
    }
    // Try to take out a lock
    lock (lockObject)
    {
    // Once we have the lock, do a second check to make sure another thread didn't get there first
    if (instance != null)
    {
    return instance;
    }
    // Fetch the instance of the class if already in the scene
    // Note: there should only be one copy of the singleton attached to a GameObject in the scene
    T [] instances = FindObjectsOfType ();
    // For this project we are not interested in spawning new objects to hold these if they aren't found, as if
    // it's still not already in the scene, then we have a problem of quality control anyway
    if (instances == null)
    {
    Debug.LogError ($"{typeof (T).Name} not present in scene");
    }
    else if (instances.Length != 1)
    {
    Debug.LogError ($"{instances.Length} instances of {typeof (T).Name} present in scene");
    }
    else
    {
    // Correctly found the only instance, so assign it
    instance = instances [0];
    }
    }
    // Return the existing or just identified instance
    return instance;
    }
    }
    }

  • @Xankill3r
    @Xankill3r 5 лет назад

    A good pattern to use in place of SIngletons is the Service Locator.
    1. Define an abstract class deriving from Monobehaviour that defines the public interface to your Service
    2. Create Service(s) deriving from your Abstract Base
    3. You can have premade GameObjects in scenes that have your derived Service(s) attached as components
    4. Lazy instantiation searches for the Abstract Base using FindObjectOfType
    5. That's it, you're done
    This allows you to test multiple implementations based on the same interface enabling easy testing as you can create mocks very quickly.
    Bonus:
    Mark the derived classes as Obsolete with the flag to throw compiler errors. Although VERY hacky this allows you to easily enforce good programming practices as the option for some shortcuts is removed. It should force programmers on the team to think more explicitly about the interface of their classes and to utilise proper access modifiers.

  • @broganking9830
    @broganking9830 5 лет назад +2

    Loving the use of Rider! Best IDE for Unity by a million kilometers

  • @i_am_reshad
    @i_am_reshad 3 года назад

    Here is a problem I came across when using singleton pattern on my prefab.
    I have 3 box (same prefab). each of them has one same script called changeColor (because it is prefab) ; I use singleton in this class like
    if(isntance == null) { instance = this;} else{ destroy(gameObject)} . When game stars all of other boxes ( 2 boxes of 3 ) are disapppearing. I found the problem is when Instance in not null it destroys other boxes and keep only one box.
    What should I do here.?

  • @worldeater08
    @worldeater08 5 лет назад +4

    I would love a video about data oriented design in unity

  • @mehmedcavas3069
    @mehmedcavas3069 5 лет назад +2

    Hey jason again a very nice topic and thanks a lot for the tutorials :) They help me a lot on my internship :) Want to ask u anything. What do u think about the scriptable object pattern, using them instead of singletons?

  • @justinwhite2725
    @justinwhite2725 5 лет назад +3

    For something like an audio manager you'd want to set it to dontdestroyonload. This will keep it persistent even if you change scenes.

    • @YiffyStiffyMeow
      @YiffyStiffyMeow Год назад

      I don't think this applies to static/singleton classes? You can't instantiate objects from a static class therefore there's no need to destroy anything

  • @kutanarcanakgul5533
    @kutanarcanakgul5533 5 лет назад +3

    I want to ask something. You always say you should separate your code for the future big things. Let's say i have a player and it has movement system,input system,inventory system,health system etc... I want to separate all of that but Player has a super(base) class called Character. How should i implement all of that i cannot figure that out. Is there a video out there you explain kinda stuff?

    • @trashcaster
      @trashcaster 2 года назад

      You should have separate classes for your Inventory, for an Attribute system (HP, strength, dexterity, luck, etc). Any object type that you want to be able to use that, create a class that can be used generically, and make Player and Monster/NPC/whatever implement it.
      This way you can find any kind of "entity" to modify values, without having to hardcode each type with if statements.
      Another option is to have a sort of blank-slate class that contains all the inventory, stats, etc and has a Scriptable Object that defines the type of entity. Such as making an EntityScriptableObject class with a string field set called type, and set the value to "Player", max HP set to 20, inventory size to 40, etc. Define non-dynamic properties in the scriptable object instances you make in the project, and then when you create a new Entity game object, just assign the scriptable object that corresponds to the type. This way also lets you create new types of enemies by using drag and drop + editor, and as long as you create a really generic framework to handle it, it can do anything you need it to. You can assign meshes, prefab references, numerical values, strings, lists/arrays, etc. Just remember that this approach is only for making "templates" that your game handles.

  • @paulroos8517
    @paulroos8517 5 лет назад

    It might be, that the distance to your microphone varies as the volume varies. Keep in mind, that the human ear adapts to the volume level. So, when your voice goes from loud to soft, one misses a few soft words, following the loud voice. Fortunately, there is the transcript.

  • @paulrobinson4932
    @paulrobinson4932 5 лет назад +2

    Hi Jason, any chance you can do a tutorial covering spawning enemies in a 2D game with trigger. I'm making a 2D game and have a script that lets me add enemies and spawnpoint in the inspector but struggling to get the whole thing to work, please help. Love your other tutorials :-)

  • @ThinkForward0
    @ThinkForward0 4 года назад +1

    hey Jason , you are my fav unity youtubers , you have great tutorials for beginners like me , i have a question
    am making a ball stack game where you break the stack and your score increases , when i used singleton , i was able to retain the score after the next level is loaded , but am facing a problem if i lose , it will keep the same stack , while my level spawner spawn new ones which causes Bugs , how can i limit it to the score and not to the stack

  • @toxicitzi357
    @toxicitzi357 4 года назад

    I have just one little question about the LazyInstantiatedSingleton and AutoCleanupSingleton.
    Would polimorphism work well with the lines of code that repeat there letter for letter? by which I mean the static _instance and Instance, because the only difference I see in the 2 classes is in AutoCleanupSingleton which has an Awake function. I'm guessing the reason not to use it would be to maintain single responsibility, or, keep the behaviors separated so that if we deleted either, the other one works all the same, so we don't have extra dependencies. I'm asking, because I believe that's an example of duplicate code, just wondering if I'm wrong there.

  • @DynaZor
    @DynaZor 5 лет назад

    What should be the way to hold a small database of items (just example) that would be accessible to all scripts at runtime?
    I've been using Singletons and had the exact problems you pointed out.
    I feel like you already have a video answering this but I don't know what to look for...
    Thank you for all these video!

  • @cristiancaze
    @cristiancaze 5 лет назад +1

    ohh that book of lenses.. veryy goooood :)

  • @leozhang1340
    @leozhang1340 4 года назад

    what's the VS code extension you used that gives the function arguments a label next to it? Like for example in the beginning of the video, you have Vector3.Distance(a: t.transform.position, b: point)

    • @THEspindoctor84
      @THEspindoctor84 3 года назад

      I believe he is using the JetBrains editor that is made for unity

  • @Maximetinu117
    @Maximetinu117 5 лет назад

    Hello Jason, I have a question for you:
    Don't you think that, in practice, it's better to hide the instance variable by making it private and only exposing static methods manually, that make use of the private static instance variable? In this way you disallow to performs certains operations over the component, transforms or game object, such as destroying it, moving it, adding new components, etc...

  • @Alevry13
    @Alevry13 4 года назад

    Interesting video, I recently started getting into Unity and your channel very helpful for me, thanks!
    But I got a question, I created abstract class similar to AutoCleanupSingleton with virtual awake with cleanup and I still can add something to Awake if I need to. Is there still any downsides of using it compared to establishing singleton separately in each class i want to use as singleton?

  • @rickloyd8208
    @rickloyd8208 5 лет назад

    In addition to your second implementation, I also like to add donotdestroy on a singleton object, that way I can preserve data which was calculated and loaded from internet in previous scene. As for the issue regarding awake, I solved it with virtual keyword (if I recall). The only problem which remains - no way to know the order in which singleton will be called, so there will be cases when some objects are not created yet while you are trying to access them. So I want give a try to avoid using them in next project.

    • @trashcaster
      @trashcaster 2 года назад

      You can likely call base.Awake() in any implementations too. That's how you're meant to call parent-class methods.

  • @dvdmrn
    @dvdmrn 3 года назад

    If singletons are not great for global state management, what pattern would you recommend?

  • @dand4604
    @dand4604 5 лет назад +1

    Hello sir, I'd like to ask you to please either answer me in a comment or make a video for people with the same question. How do you organize everything, how to think and avoid getting overwhelmed by tasks and information and how to stay focused. I find this to be a very important yet difficult task especially for beginner programmers.

  • @pirateskeleton7828
    @pirateskeleton7828 3 года назад

    I use a static class called Conventions to hold all of the useful functions that I tend to use throughout my different objects.

  • @gower1973
    @gower1973 5 лет назад

    I just finished my first game with Unity, but had to use alot of static variables in order to access them from other scripts, but I realize it promotes them to global scope which goes against the whole point of OO design. How do I access variables and functions sitting on another script on another object because even when you make them public Unity just wont compile the script because it says you cant access them. Could you do a tutorial on it?

  • @niravsenjaliya1206
    @niravsenjaliya1206 5 лет назад

    u r awesome.plz keep sharing this kind of advance things.
    have a good day!!!

  • @kerolesmonsef4179
    @kerolesmonsef4179 5 лет назад

    Hi Jason i watched all of your pattern design game videos
    and i still think that i am not good at OOP
    do you have any suggestion book , videos , ...... tutorials for game development OOP
    i wonder how did you know all of that and how and from where ?
    please answer

  • @SlayPlenty
    @SlayPlenty 3 года назад

    A video on object oriented vs process oriented programming? A GDC talk by the dude that built Thumper argued for it but I cant get my head around the differences. I don't think I've ever built anything purely on functions without classes or objects

  • @morneerasmus1789
    @morneerasmus1789 5 лет назад

    I've been using Scriptable Objects kind of like a singleton, would you propose using singletons instead of scriptable objects?
    e.g. I have a playerData SO and other scripts call that SO's functions.

    • @justinwhite2725
      @justinwhite2725 5 лет назад

      Isn't using scriptavle objects this way nearly exactly the same? You'd still have to stick it on a static variable and initialize it on game startup.

    • @morneerasmus1789
      @morneerasmus1789 5 лет назад

      ​@@justinwhite2725 Yeah I think you're spot on with that, I've just not been using the static variable, been referencing the SO directly from all the other scripts.
      I'll give that a shot thanks!

    • @justinwhite2725
      @justinwhite2725 5 лет назад

      @Khalreon so how dl you reference it if it's not static? Do you link it into all your monobehaviours? That seens fragile.

    • @justinwhite2725
      @justinwhite2725 5 лет назад

      @Khalreon not really, because you can't search links like that the way you can in a script editor.

    • @justinwhite2725
      @justinwhite2725 5 лет назад

      @Khalreon don't get me wrong - I love scriptavle objects and use them for a lot. I don't use enums or anything. I use scriptavle objects for most data types and even some calculations. I just don't see them replacing singletons. Or maybe I'm just not understandinf what you are doing which is why I'm asking the questions I am.

  • @macleodgordon
    @macleodgordon 4 года назад +1

    All I wanted to know was how to use Singletons to create a class which contains global variables. I thought this would address this. Alas, this was such a confusing tutorial and introduced so much stuff which has nothing to do specifically with singletons. While I have enjoyed and learned a lot from your tutorials Jason, this one floors me! :(

  • @user-lv6qm3fj2z
    @user-lv6qm3fj2z 5 лет назад

    One useful addition. Avoid at any cost using singletons when you apply for the job in the company and do the test task for them. There are a lot of really weird people out there, who will reject you just by seeing this pattern in your code. Happened to me a lot of times.

    • @nowayjosedaniel
      @nowayjosedaniel 4 года назад

      This actually makes a lot of sense. Many bad programmers (and even some good ones) fear valid tools because they abide by weird religious dogma.
      As strange as it is, your advice is good. It's the same advice as avoiding talking about literal religion or politics in an interview or at all in most cases. You never know what team they mindlessly follow or will find offense with.
      Tribalism sucks but it's too real to just ignore, and for some weird reason some people just have to worship some idealogy no matter what the context.

  • @frostden
    @frostden 5 лет назад

    What would you do if your Singleton needed to have Prefab references in it?
    I have a 'Spawner' script which provides a static 'Instance' reference to itself. It is on a prefab, and contains references to any Prefab I might want to spawn. It's useful, because if any entity wants to spawn a bullet, fireball, character, etc, they can call the Spawner. It means I don't have to add an 'Explosion' prefab to every Projectile, Spell, and Death animation that might need it, for example.
    The problem is that the Spawner Prefab contains references to every Prefab that I might want to spawn. I did this to avoid using Resources.Load(). I don't want to use Resources.Load() because 1. I don't want to access prefabs by path, and 2. I don't want to to arrange my project by how a prefab is instantiated, instead of what it does/is.
    It looks like LoadResource() might be unavoidable in this case. On the bright side, I would only be using it to load the Spawner prefab itself...

    • @YiffyStiffyMeow
      @YiffyStiffyMeow Год назад

      I don't understand. How do you have a prefab instantiated to use the Spawner script if the prefab was never loaded with Resources.Load to begin with? Isn't this a necessary first step to utilising a prefab?

    • @frostden
      @frostden Год назад +1

      @@YiffyStiffyMeow My comment was made three years ago. "Globals/Singletons/Utilities" in unity were a mess then. I was struggling with them at the time, and built all sorts of horrible workarounds.
      Hopefully they're less of a mess now. I don't know. I don't work with Unity any more.

    • @YiffyStiffyMeow
      @YiffyStiffyMeow Год назад

      @@frostden No worries, I'm still learning so I can't vouch for if they're fixed or not haha

  • @Shurid16
    @Shurid16 5 лет назад +4

    Can u fix the audio please? The pitch is so high.. Hurts my ears

  • @DynaZor
    @DynaZor 5 лет назад +1

    Thank You!!!

  • @IAmSlex
    @IAmSlex 3 года назад

    Need a re-recording of this one day. The audio triggers my condition and I can't seem to make it sit right no matter what I do 😭

  • @sagiziv927
    @sagiziv927 5 лет назад +1

    Great tutorial, love your vids, but I have to disagree about this one.
    I have tried to use Singletons in my last project, but it caused a lot of issues and the code broke pretty often.
    Usually I had to play with the execution order to make sure the singleton are created before calling them.
    Nowadays I am using ScriptableObjects and it is much easier and more reliable and flexible.
    Also I can usually see the current values in the Inspector, unlike with static list/instance so I can debug it a bit quicker

    • @MrKyokure
      @MrKyokure 5 лет назад

      How do you refer your SOs without linking them to singleton class?

    • @sagiziv927
      @sagiziv927 5 лет назад

      @@MrKyokure I just add reference to them in the script. If there was a good dependency injection options for unity it could be way simpler.
      The advantage of ScriptableObject vs MonoBehaviour is that the ScriptableObject is related to the project and no the scene, so it will always exist

    • @MrKyokure
      @MrKyokure 5 лет назад

      @@sagiziv927 Hmm okay so you add serialized field to hold the SO in every script that needs it? Isn't that too complicated if lets say we have 20 classes that want the reference. Not to mention if we refactor the SO class name, those references will break and we need to re-reference it all.

    • @sagiziv927
      @sagiziv927 5 лет назад +1

      @@MrKyokure Renaming the class name will not break the connection as long as you also rename the file name.
      About referencing the SO, after you added the variable to the class,
      If you select class file (in the project view) there is a default values you can assign. so basically I assign it from the beginning and don't need to butter when attaching the class to an object.
      And as I said, if there was good dependency injection framework in Unity life would be simpler

  • @zekiozdemir420
    @zekiozdemir420 2 года назад

    thank you

  • @ElegantWaster
    @ElegantWaster 5 лет назад +11

    The audio issues make the video difficult to listen to

  • @NiclasGleesborg0
    @NiclasGleesborg0 5 лет назад +1

    21:00 Been there.. It's a hard balance :P

  • @9paradox
    @9paradox 5 лет назад

    One more.. Thread safe Singleton, with help of volatile and synchronisation

  • @N0biKn0bi
    @N0biKn0bi 4 года назад

    Line 11, never forget.

  • @ozanunay9257
    @ozanunay9257 5 лет назад +2

    You don't, that is how.

  • @pimpace
    @pimpace 5 лет назад

    Sorry, but what is the purpose of this local _audioSource in AudioManager? There is no AudioSource on this object.... GetComponent is irrelevant here. It is not?

  • @sinistermephisto65
    @sinistermephisto65 5 лет назад

    Tupac Approves this video

  • @denispahunov6415
    @denispahunov6415 5 лет назад +1

    Why make half an hour video when it all could be represented as a couple pages of text with code samples and all that useful stuff?

  • @HunTMovie
    @HunTMovie 5 лет назад

    Sorry for question but... Are You Negan from The Walking Dead?

  • @gaming4fun419
    @gaming4fun419 5 лет назад

    I'd love to have a new video on this subject. I simply can't listen to it =( Don't know if it's my ADHD or what it is but I can't focus at all, and this is something I would love to learn more about.

  • @chloe_the_cat2831
    @chloe_the_cat2831 2 года назад

    I really want to watch this video, but the changing volume makes it hard for me to listen and understand. I don't know, maybe it's easier for native English speakers. 🤔

  • @lemetamax
    @lemetamax 5 лет назад +1

    I didn't actually complete the video cause the audio was driving me crazy...no offence.

  • @eduoki8498
    @eduoki8498 5 лет назад

    while(true) => LikeButton();

  • @arnovveiss
    @arnovveiss 5 лет назад

    You are using too much noise reduction for your audio.

  • @gregridd
    @gregridd 4 года назад

    most of my scripts are singletons :S

  • @KhrisKruel
    @KhrisKruel 4 года назад

    So this is nice, but this really doesn't explain why use singletons over static, or vice versa

    • @gazoonman
      @gazoonman 4 года назад

      Yes, I thought it too, the thumbnail was supposed to explain it too

  • @dankodev
    @dankodev Год назад

    Singletons are mid and Scriptable Objects are based

  • @_CloudyBunny
    @_CloudyBunny 3 года назад +1

    English is not my first language. Your voice is unclear and loudness is not constant so I really had a hard time understanding your content!

  • @The28studio
    @The28studio 5 лет назад +1

    I never use Singleton , and I had a fight with coworkers abt it.

  • @yudanaim6849
    @yudanaim6849 5 лет назад

    Please replace your cranky microphone you heart my ears. Put a poofer and make it a little less hi mid add more bass and cut the hi ends . It happened during manny of your tutorials and when it happened i just stopped and move on. Man do something about it.

    • @Unity3dCollege
      @Unity3dCollege  5 лет назад +1

      It should be much better in the newest videos :)

  • @sam_cavalheiro
    @sam_cavalheiro Год назад

    Please, fix this microphone

  • @thygrrr
    @thygrrr 3 года назад

    You should retract this video, it's poor software engineering and you don't "new a property".

  • @andremilanimartin3338
    @andremilanimartin3338 4 года назад

    pls set up yiut mic properly. my ears are hurting

    • @Unity3dCollege
      @Unity3dCollege  4 года назад

      It's better now... totally new setup :) I'll have to re-record some of these soon.