Search Unity

Question How do I make a game object have it's own variable with the same script as others?

Discussion in 'Scripting' started by ILikeMakingFreeGames, Nov 28, 2022.

  1. ILikeMakingFreeGames

    ILikeMakingFreeGames

    Joined:
    Nov 26, 2022
    Posts:
    4
    So, I've been trying to make a factory spawn offscreen to set the level of the factory, then when I left-click, it sets the position of the factory to the mouse It will also spend tac(the in-game currency).

    Everything works just fine until I try to add multiple factories. If I try to increase the level of the factory, all other factories that already exist will have their level be increased, and the tac spent will be the same if I try to individually place all of them. If I left click to bring the factory into the screen by left clicking, all of the other factory's position will be set to the same spot.

    I've been trying to use a variable (alreadyPlaced) which detects if the factory has already been placed, but as far as I can tell, it doesn't work because it applies to all factories, so it doesn't change anything.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class factoryScript : MonoBehaviour
    6. {
    7.  
    8.     int level = 1;
    9.     bool alreadyPlaced = false;
    10.  
    11.     void Update()
    12.     {
    13.         if(alreadyPlaced == false)
    14.         {
    15.             if(Spawn.isSelecting == true)
    16.             {
    17.                 if (Input.GetKeyDown(KeyCode.Alpha1))
    18.                 {
    19.                     if (variables.tac > level) { level++; Debug.Log("level is now" + level); }
    20.                     else if (variables.tac == level) { Debug.Log("Can't Upgrade anymore with current tac"); }
    21.                 }
    22.  
    23.                 if (Input.GetKeyDown(KeyCode.Mouse0))
    24.                 {
    25.                     alreadyPlaced = true;
    26.                     Spawn.isSelecting = false;
    27.                     Vector3 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition, Camera.MonoOrStereoscopicEye.Mono);
    28.                     Vector3 trueMousePos = new Vector3(worldPoint.x, worldPoint.y, transform.position.z);
    29.                     transform.position = trueMousePos;
    30.                     variables.tac = variables.tac - level;
    31.                     variables.buildingAmount++;
    32.                 }
    33.             }
    34.  
    35.         }
    36.         if (alreadyPlaced = true && Input.GetKeyDown(KeyCode.Return)) { variables.tac = variables.tac + level; Debug.Log("+" + level + ", result = " + variables.tac); }
    37.         else if (alreadyPlaced = false && Input.GetKeyDown(KeyCode.Return)){ Debug.Log("Not Placed"); }
    38.     }
    39. }
     
  2. Amon

    Amon

    Joined:
    Oct 18, 2009
    Posts:
    1,384
    Well, this script is on every factory object so it is going to do what you said it does to every factory. Your best bet would be reading up on classes, 'new' the data of the class for each instance which gives each instance it's own properties and then learn to pass that data to each individual GameObject you click on. You could have an id for each factory that is different and when you click on the object have your script only work on that specific object.
     
  3. Oddness

    Oddness

    Joined:
    Jul 12, 2019
    Posts:
    5
    Code (CSharp):
    1. if (variables.tac > level) { level++; Debug.Log("level is now" + level); }
    The issue is in the above line. I'd suggest taking everything which has to do with increasing levels out of the main factory script all together, moving it to its own method (With appropriate access), and then calling that method when you need to increase the level of a given factory. No need for an ID variable, unless you want one. You can just pass the GameObject (Or, better, Building) as a parameter. If I was going to write this, here's how I'd do it:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Building : MonoBehaviour // Here, we are declaring a base class with a level member.
    6. {
    7.     public int level = 1; // Or we can do a {get; set;} to control access. Up to you.
    8.  
    9. }
    10.  
    11. public class Factory : Building // Here, we are inheriting the 'Factory' from the 'Building' base class.
    12. {
    13.     void Update()
    14.     {
    15.         if(Input.GetKeyDown(KeyCode.Mouse0))
    16.         {
    17.             // I don't know what all of this does, or I'd change the code here, but
    18.             // if you can standardize this across all buildings, then it will save you
    19.             // time writing each of your building classes. Look up how inheritance works.
    20.             // and see if it is applicable to your use-case.
    21.        
    22.             Spawn.isSelecting = false;
    23.             Vector3 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition, Camera.MonoOrStereoscopicEye.Mono);
    24.             Vector3 trueMousePos = new Vector3(worldPoint.x, worldPoint.y, transform.position.z);
    25.             transform.position = trueMousePos;
    26.             variables.tac = variables.tac - level;
    27.             variables.buildingAmount++;
    28.         }
    29.  
    30.         // In this scenario, this is the syntax for increasing the level of a building.
    31.         // The reason that it is affecting them all right now is that they all meet the conditions to have
    32.         // their level increased. If you fix that, then all of their levels will not be
    33.         // increased. If you want the opposite behavior, then you would make their level static (Just for future reference)
    34.    
    35.         //if(*/Some condition*/ true)
    36.         //{
    37.         //    this.SetBuildingLevel(this, level + 1);
    38.         //}
    39.     }
    40. }
    41.  
    42. public static class BuildingTools
    43. {
    44.     // As your game and code become more sophisticated, and depending on what you're doing, I would actually suggest
    45.     // placing this building, along with others, into a base class of Building. If each Building is going to have a level,
    46.     // just have them extend from the Building class, then you can make the below static method to affect ANY building,
    47.     // instead of only affecting Factories, and having one specific method for changing the level of each.
    48.  
    49.     // Note:
    50.     // Again, this depends on what you're doing. If each of your buildings isn't going to have similar parameters,
    51.     // then disregard this part. This is a design decision that I'm suggesting, based on what you appear to be
    52.     // trying to do.
    53.  
    54.     public static void SetBuildingLevel(this Building building, int level)
    55.     {
    56.         building.level = level;
    57.     }
    58. }
    Edit:
    In any case. Your problem is a conceptual one. You need something which is external to buildings to affect that building. No matter how you slice it, you are going to need another class here -- A 'building (Or factory) "manager"'. Factories don't differentiate themselves. The manager differentiates them based on a set a of conditions. If you put the conditions in the Factory itself, and those conditions are true for each factory, then they will all react the same way.

    If, on the other hand, you change the conditions which are applicable to that Building externally, they will still all react the same way, but one will have different circumstances acting on it, so it will behave differently based on its own local conditions..

    Think of it like this --

    Lets say that each of your buildings has a method in it called Collapse(). Now, you can call that method on each of your buildings internally, and they will all collapse. If that is the desired behavior, then that's fine. However, if you want some out-side force to MAKE the building collapse (Let's call this outside force a Hurricane), then what you need to do is to make the "Hurricane" affect specific buildings in a specific scope (City) call that method, and then only those specific buildings will Collapse().

    What you're doing right now is building a design flaw into every single building you create, to make it Collapse(). What you need is a Hurricane.

    I hope that makes sense.
     
    Last edited: Nov 28, 2022