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

C# Trying to create an instance of a class in another class

Discussion in 'Scripting' started by victorML, Jul 5, 2018.

  1. victorML

    victorML

    Joined:
    Jul 5, 2017
    Posts:
    38
    Hi, my name is Víctor and I'm trying to learn a little bit more about classes in Unity.

    I'm making a 'Snake Game' and I want to pull apart the Food code from the Snake Code... For this reason I have created an SnakeScript and a Food Script but when I try to call some methods from the food script to the snake script, the game gets stuck.

    Any idea ?
    This is the Start method from Snake Script and It gets stucks from 'food.instantiateFood()'
    Code (CSharp):
    1.     // Use this for initialization
    2.     void Start () {
    3.         //Start with the initial framerate and step large
    4.         //Coordinates to re-allocate food
    5.         horizontalRange.x = leftWall.transform.position.x + 270f;
    6.         horizontalRange.y = rightWall.transform.position.x - 270f;
    7.  
    8.         verticalRange.x = topWall.transform.position.y - 260f;
    9.         verticalRange.y = bottomWall.transform.position.y + 260f;
    10.  
    11.         food = gameObject.AddComponent<FoodScript>();
    12.         food.instantiateFood();
    13.  
    14.         // FoodList.Add(Instantiate(foodPrefab));
    15.         //FoodList[0].transform.position = new Vector2(Random.Range(horizontalRange.x, horizontalRange.y), Random.Range(verticalRange.x, verticalRange.y)); //Teleport food to a new position
    16.         StartCoroutine(Move());
    17.     }
    This is Food Script
    Code (CSharp):
    1. public class FoodScript : MonoBehaviour
    2. {
    3.     private int foodType;
    4.     public GameObject bronzeFood;
    5.     public  GameObject silverFood;
    6.     public  GameObject goldFood;
    7.     public  GameObject diamondFood;
    8.  
    9.         public void instantiateFood()
    10.         {
    11.             foodType = randomFood();
    12.             print(foodType);
    13.             if (foodType == 1)
    14.             {
    15.                 Instantiate(bronzeFood);
    16.             }
    17.             else if (foodType == 2)
    18.             {
    19.                 Instantiate(silverFood);
    20.             }
    21.             else if (foodType == 3)
    22.             {
    23.                 Instantiate(goldFood);
    24.             }
    25.             else
    26.             {
    27.                 Instantiate(diamondFood);
    28.             }
    29.  
    30.     }
    31.     public int getFoodType
    32.         {
    33.             get { return foodType; }
    34.         }
    35.         //Function to get a random type of Food;
    36.         public int randomFood()
    37.         {
    38.  
    39.             float random = Random.Range(0.0f, 10.0f);
    40.             if (random <= 9.0)
    41.             {
    42.                 return 1; //Bronze
    43.             }
    44.             else if (random > 9.0 && random <= 9.8)
    45.             {
    46.                 return 2; //Silver
    47.             }
    48.             else if (random > 9.8 && random <= 9.95)
    49.             {
    50.                 return 3; //Gold
    51.             }
    52.             else
    53.             {
    54.                 return 4; //Diamond
    55.             }
    56.  
    57.         }
    58.  
    59.  
    60. }
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,144
    My guess, since you didn't post any errors, is that all your public food variables have no values. When you addComponent to add the FoodScript, your food values are null, thus it can't instantiate anything.

    You should always post your errors along with your code. But you should be able to check this for yourself in the inspector within the editor.
     
    victorML likes this.
  3. victorML

    victorML

    Joined:
    Jul 5, 2017
    Posts:
    38
    Hi i'm pretty sure that the prefabs are assigned to the public variables... And the inspector doesn't tell any error nor warnings... Anyway thanks for the suggestion.
    Any other idea plis ? :(

    https://gyazo.com/6f27bef64c516f2cac932067b5dbe5ef
     
  4. FernandoHC

    FernandoHC

    Joined:
    Feb 6, 2018
    Posts:
    333
    Like @Brathnann said, Adding a component via code will always have its non-instantiated values empty;
    What you're probably looking for is to instantiate the a prefab of an object with the Food class component on it, with it's values assigned in the inspector.

    You should check the values in the inspector in real time to confirm that.

    Also, what do you mean by "the game gets stuck" ? Does it crash unity? Does it keep running but nothing happens?

    Also, you should look for errors in the console, not the inspector.
     
    victorML likes this.
  5. victorML

    victorML

    Joined:
    Jul 5, 2017
    Posts:
    38
    When I said that Unity gots stuck is that, from the instatiation of the food, code doesnt continues the execution.
    Finally I understood what you are telling about the .AddComponent() but I didnt solved the problem by this way.

    What I've done is changing the private FoodScript to public and attach a gameObject with the script. To me it seems a little bit dirty but it works...
    What should I do to assign the prefabs to a Script added via code ?
     
  6. FernandoHC

    FernandoHC

    Joined:
    Feb 6, 2018
    Posts:
    333
    Not sure I understood it completely, but if you want to access a foreign object's script you'd need to get the component of their instantiated script. Like so:
    1. You declare your public prefab reference and attach it in unity inspector, like you did " public GameObject diamondFood;"
    2. Then, whenever, in your code you instantiate that prefab almost like you did "Instantiate(diamondFood);", but get the return of Instantiate which will be a GameObject type. Like so: "GameObject newObj = Instantiate(diamondFood);"
    3. Once you have a reference for your instantiated object, you can fetch their instance of the script like so: "ScriptClassName instantiatedClass = newObj.Getcomponent<ScriptClassName>();".
    From then on you can use instantiatedClass to access all ScriptClassName public definitions.
    It would be recommended to keep a definition of your instantiated classes if you're going to interact with them in the future (so you never have to do things like Gameojbect.Find, or go through slow processes to find objects).

    Hope that's what you've been looking for.
     
    tubelightboy and victorML like this.
  7. tubelightboy

    tubelightboy

    Joined:
    May 12, 2020
    Posts:
    9
    I have read in multiple places that GetComponent and FindGameObject are process heavy code and that one should avoid these as much as possible. I create a static instance of a class from which I want to access a function and then I use this instance to access those methods. In this way, you can avoid those GetComponent method.

    1. 1. public static ClassA instance; //this is the class from which you might want to access the method.
    2. 2. ClassA.instance.ReturnFoodPoints(parameters); //use this in the class where you want to access ClassA methods.