Search Unity

Calling method in prefab that is not instantiated

Discussion in 'Scripting' started by muffin1, Sep 27, 2017.

  1. muffin1

    muffin1

    Joined:
    Sep 25, 2016
    Posts:
    8
    Hi,

    I've been working on a weapon/inventory system for a few days trying to find a good solution for my project.

    One of the experiments involved using a prefab as a weapon (let's say the prefab is just called "Gun").

    I don't know how best to describe this so here it goes:

    Player.cs is a Monobehaviour which has two public fields;

    public Gameobject m_gunPrefab;
    public Gun m_gun;

    And the Gun prefab just has a Gun.cs Monobehaviour attached with a public method "Shoot()".

    So I've dragged the Gun prefab into the Player's inspector in both public fields. The prefab is never instantiated inside of the Player class, just dragged on to these public fields.

    In the Player class I have a method called "UseWeapon()" which takes the "Gun" reference and calls it's "Shoot()" method. When I call this method it actually executes the Shoot() method, but I have not instantiated the prefab. This is what confuses me. How could it run that method if the object it is calling has not yet been created?

    I'm on my phone at the moment so if it would help to get my actual source code up I'll get on my computer and post it up.

    Thanks for any help

    Muffin
     
  2. MaxGuernseyIII

    MaxGuernseyIII

    Joined:
    Aug 23, 2015
    Posts:
    315
    I think I understand your question. You want to know why the method call worked when you hadn't instantiated gun, yet, right?

    Instantiation of prefabs is an expression of the Prototype pattern. As such, it uses a real object as the basis for instantiation. So, when you instantiate something, you aren't going from zero to one, like you would when using the new operator. You are taking one thing and making a copy of it, then tweaking a few of its properties.

    When you call a method on a prefab, you are calling that method on the prototype. Its purpose is different from other game objects - it's meant to be used to create new game objects rather than to participate directly in the game - but it is a valid game object nevertheless.
     
    muffin1 likes this.
  3. muffin1

    muffin1

    Joined:
    Sep 25, 2016
    Posts:
    8
    Ahh that would explain it, I've been scratching my head over this for nearly 2 days now. So the the prefab that I have referenced to the Player through the inspector is actually already "instantiated" in some form, and any actual instantiation of this prefab will just make a clone of it.

    Thanks for the quick reply Max *thumb*

    Something else that seemed strange is that I was only able to execute the "Shoot()" method once and after that it would no longer run. The Shoot method first Debug.Log's a string to the console and then plays a sound and finally spawns a projectile. The sound is played by my Soundmanager that is injected using Zenject and also the projectile is spawned using. Zenject memory pool. Both of these injects were not actually accessible, and when attempted to play a sound it would return a null exception, same with the projectile spawning if I commented out the sound call. Do you have any insight in to this? Just for curiosity reasons.

    Thanks again Max.
     
  4. MaxGuernseyIII

    MaxGuernseyIII

    Joined:
    Aug 23, 2015
    Posts:
    315
    I'd need to look at the code but as soon as someone says "Something's weird when I do this thing with a dependency injection framework" my prejudice against such frameworks manifests and I can't be helpful. I'm fairly Napoleonic when it comes to DI frameworks. Once it's proven innocent, I can move on, though. :)
     
    phobos2077 likes this.
  5. muffin1

    muffin1

    Joined:
    Sep 25, 2016
    Posts:
    8
    I love the idea of DI it seems to make great sense to me, but this is all experimentation (been in the "experimenting" stage for about 20 years now, I'll move on to "full project" stage when I'm 90).

    I'm at work at the moment but I'll get the code posted in an hour or so. Off the top of my head the setup is like this:

    Gun.cs has two injects:

    SoundManager
    Projectile.Pool

    The SoundManager is just a basic Monobehaviour with a few public methods for playing audio clips. It is attached to a gameobject with two audio sources and boxed up in to a prefab.

    The Projectile.Pool is a memory pool for spawning Projectiles. This is extended from a Zenject class for handling/creating memory pools.

    Injects all work fine if the prefab is instantiated at some point, but doing the above (calling a method on an uninstantiated prefab) it seems as thought it doesn't grab the references/have its references injected. I wish I understood the inner workings more, if the prefab is already in memory (as to the Prototype pattern mentioned before) I don't see how these references aren't accessible until instantiation.

    I guess from this point on my main question has already been answered but these points are interesting, it'd be nice to have a better understanding.

    Thanks for the replies!
     
    phobos2077 likes this.