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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Differentiating between objects which use same script

Discussion in 'Scripting' started by beerinbox, May 20, 2020.

  1. beerinbox

    beerinbox

    Joined:
    Feb 29, 2016
    Posts:
    26
    Hello.
    So here is my problem, I have 15 different shops. The shops automatically produce a product (same product for now). The shops store the product in their respective storage boxes. I manually sell them at the market. I also intend to upgrade/change things in the shops like the worker limit or storage size.

    This means that I need a way of telling which of these 15 shops I am manipulating. For instance, when I am selling the product, how do I know which storage box I am getting the product from?

    I know I should try something but anything I think of just doesn't seem to work in my head, so I cannot see ahead to give it a go.

    For example, I could use enum and give 15 shops unique IDs. But then I'll have long if/else or switch statements.
    I could give different names to each shop and then try calling them by their names (which I actually laid the groundwork, I think). But this again just another way of using enums.
    I thought of using tags as well, giving every shop their own tags. I think this is also similar to enums.
    I could make a shop prefab, but that doesn't seem to change much as I'll still need to know which one I have to deal.

    Basically, every single way I could think of leads to me writing long if/else statements. More importantly, hard-coding name or tag or something similar which will probably come back to haunt me later in the project. I can probably write the code, add dropdowns and/or toggles but I feel like there is something else to this.

    For now, I disabled any upgrades and since they are producing the same product right now, I created a "common basket" where the shops empty their stock to, and then I do the selling part.
    But there will be a time where I press "Increase Worker Limit" button and the button would look at 15 shops and probably go "Ugh... Let's... Let's just increase ALL of them". Also market would take same amount of product from every storage box it can lay its hand on, but will pay me only for one of those. Sneaky market...

    Code (CSharp):
    1.     void GetShops()
    2.     {
    3.         Shop[] tempShops = transform.Find("ShopContainer").GetComponentsInChildren<Shop>();
    4.         for (int i = 0; i < tempShops.Length; i++)
    5.         {
    6.             allShops.Add(tempShops[i].name, tempShops[i]);
    7.         }
    8.  
    9.         foreach (var shop in allShops)
    10.         {
    11.             Debug.Log("Key: " + shop.Key + " and value: " + shop.Value);
    12.         }
    13.     }
    Here I added all of the shops into a dictionary but I am not sure how to go ahead from here. [EDIT: I don't have to go this route, any new approaches are welcome, of course]

    I don't know if this is true because I haven't gone through all the way with anything, but the solutions above feels like the player and the compiled game would need me to be there holding their hands to navigate through the game :) Not ideal, is it?

    Any help or thought would be appreciated.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    You should probably reach for ScriptableObjects. They are basically bags of data. You define a script that is a ScriptableObject, then make instances of it. Each instance is a file on disk that you load.

    The two most obvious levels I see for your case is a "a thing I can buy" and then each shop would have a "collection of things I am currently offering."

    You can extend this entire system into an inventory system too for the player, as you will likely need.

    Check out some tutorials on ScriptableObjects and inventories. You can make them as fancy or as simple as you like. I highly recommend starting simple since you're going to probably realize your needs change as your game develops, but luckily this is software, so it is soft and can be changed!
     
  3. RLord321

    RLord321

    Joined:
    Feb 25, 2017
    Posts:
    28
    A dictionary could work - since you have a key, which is the name, you will have direct access to the 15 shops without looping through all the shops. Also, I'm not sure why you are saying you would have long if/else or switch statements. Instead you would have ONE loop with ONE if statement.

    However, with only 15 shops, a dictionary is not required. Especially, if you want to configure the shop in the editor in design time. If I was to doing this, I would create a Shop prefab and create a List or Array to store them in my main script. This way you can configure the shops directly in the editor.
     
  4. beerinbox

    beerinbox

    Joined:
    Feb 29, 2016
    Posts:
    26
    @Kurt-Dekker
    Thanks for the answer. I'll look into them. Unity manual specifies two use cases, and I did not think that my case would be one of those. That's why I ruled them out. But I'll check them out.
    Meanwhile, how would that solve my problem of telling which class' data (shop's product) I am manipulating? Am I to set a different set of data for every shop? 1st shop's product is apple, 2nd shop's is apricot etc?

    @RLord321
    Thanks for the answer. I am not sure how I would go with one if statement. Because there are 15 shops, probably going to produce 15 products. The products will have to have different price. Also, if I am to upgrade storage limit of the nth shop, I'll need to check if it is nth shop's storage I am bumping, won't I? Can you provide a pseudocode?

    I feel a little bit lost and unable to think as I spent too much time thinking about this problem. So, I apologize if any of my questions seem too obvious.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    Yes, generally this is how you "data drive" a solution that varies throughout your game's context.

    If each store only sells one thing, then just slot that one thing in. If a store has to sell a range of things, you need an extra level of indirection, which would be the menu of things a particular store sells... which of course could be just one thing.

    The script for buy/sell would remain identical across all stores, but it would be configured with different datasets, and in Unity the easiest way to configure such a thing is with ScriptableObjects, since they are so easily editable in the Unity Editor.
     
  6. beerinbox

    beerinbox

    Joined:
    Feb 29, 2016
    Posts:
    26
    Thank you again, @Kurt-Dekker.
    I realized it's impossible to escape from creating some sort of menu or a list to choose from.
    What I am doing right now is, I am sending a reference of the object to a singleton class and assign it to "activeShop" variable. And any class that needs to manipulate data from one of the shops get the activeShop from that singleton class and lets the user know that they are dealing with "activeShop.name" shop. So when I click a "Toy Shop", it is set as the "activeShop" and every other screen, class or object knows that the activeShop is a Toy Shop and they are selling the toy, upgrading toy quality or toy-worker limit and so on.

    Again, because I haven't implemented yet I am not sure but this gives me some flexibility. I can store product name in the class or in a different class with its price and requirements etc. An enum for productType maybe...
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    I would just make a store scene and a single GameObject that runs a script that looks into your GameManager and decides what to offer at that store. Scenes are an awesome way to organize your game in Unity because you can get "nice clean slate" transitions if you set things up nicely, with only the few needed persistent objects in the GameManager.

    ALSO, you can additively load scenes, so you could overlay your play screen with a store, pause all player actions in the play scene, and resume them when you leave the store, at which point you async unload the store scene. Organising your game "chunks" via scene is a HUGE win with Unity.