Using Array of scripts to call methods in each script.

Hi, [Having solved my previous issue of converting bools and ints I’ve created this one]

I’m using an Array to hold my scripts, and within each script I have a function I want to call. I want each script to generate a random cost for the item it is attached to.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class BuyCheapHouse : MonoBehaviour
{

    public int cost, houseIncome;
    public Money money;
    public buy buy;
    public int BuyValue;
    private int incomeTime = 1;
    /* public int houses; */
    public int estate;
    public buy[] buyScripts;

 

   

    void Start()
    {
        cost = Random.Range(2000, 4000);
       
    }
   

    void Update()
    {
        if (estate >= 1)
        {
            foreach (buy in buyScripts); //for every buy script in buyScript array GenerateCost
            {
                buy.GenerateCost();
            }
        }
    }

    public void PurchaseHouse()
    {
          if (money.money >= cost)
                {
                money.money -= cost;
                money.money += houseIncome;
                estate += 1;
                BuyValue = cost;
               
        }
    }

   

    IEnumerator Wait()
    {
        yield return new WaitForSeconds(1);

    }



    public void Sell()
        {
            money.money += BuyValue;
            estate -= 1;
           
        }

   


}

I’m getting an unexpected symbol “in” for that script line 35 and also an error on line 38 “)”

You need a type for the enumerator variable and a name that doesn’t conflict with that type. You can use var to let the compiler determine the type for you.

foreach (var b in buyScripts)
{
    b.GenerateCost();
}

What is the name of the script which you’re using? If it’s “buy” (as in, “public class buy : MonoBehaviour”), then… well change that, because it’s confusing. The common naming convention is for classes to be UpperCase and variables to (often) be camelCase - that way you (and everyone collaborating with you, or helping you on the forums) can tell at a glance what’s a class name and what’s a variable name.

In addition to what @KelsoMRK said, note that his sample code does NOT have a semicolon after the foreach statement.

1 Like

Didn’t even see that :slight_smile:

I tried adding the script in but Unity is giving me an error saying that the variable I have assigned does not exist in the current context.

And buy is the name of the script so I’m doing public buy buy; and public BuyCheapBuilding byCheapBuilding. It’s only me coding this, and it’s my way of making it easier to know what is what. :confused:

Yeah don’t do that. That’s going to cause all sorts of troubles. You can’t have a variable name be the same as the class. This is part of the reason for the aforementioned naming convention. Class name capital, variable name lowercase.

Rename your “buy” script to “Buy” (including the script filename and the name in “public class Buy : MonoBehaviour”).

In the other script, you can use public Buy buy;

Okay - but that doesn’t help with my problem. Once the problem is fixed I can go through the scripts and do the renaming.

I changed the variable name - but I still need to have buy.GenerateCost after the variable as the GenerateCost is within the other Buy script.

After giving a new variable, it says “the name b does not exist in this context”

I promise you that you have to fix this before you’ll be able to get this to compile. “public buy buy;” might compile, but every time you try to use it you’re going to get ambiguous reference problems - the compiler will never know whether you’re referring to the class or your local variable.

So to make some “stub” code here, this is roughly where you should be at after the advice:

//in Buy.cs
public class Buy : MonoBehaviour {
public void GenerateCost() {
Debug.Log("Blah blah");
}
}

//in BuyCheapHouse.cs
public class BuyCheapHouse : MonoBehaviour {
public Buy buy;
public Buy[] buyScripts;

void Update() {
if (estate >= 1) {
foreach (Buy thisBuy in buyScripts) {
thisBuy.GenerateCost();
}
}
}

Did you remove the semicolon at the end of the foreach line, as was already mentioned? Because if that’s still there, it’s going to immediately terminate the scope within which b is defined, and give you the error you described.

After renaming my scripts and altering the code, and removing the semicolon, I now get the error "BuyCheapHouse.buy is a ‘field’ but a ‘type’ was expected.

Show us the code and paste in the actual error message (including line numbers)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class BuyCheapHouse : MonoBehaviour
{

    public int cost, houseIncome;
    public Money money;
    public Buy buySell;
    public int BuyValue;
    private int incomeTime = 1;
    /* public int houses; */
    public int estate;
    public Buy[] buyScripts;
  

 

  

    void Start()
    {
        cost = Random.Range(2000, 4000);
      
    }
  

    void Update()
    {
        if (estate >= 1)
        {
            foreach (buySell costGenerator in buyScripts) //for every buy script in buyScript array GenerateCost
            {
                costGenerator.GenerateCost();
              
            }
        }
    }

    public void PurchaseHouse()
    {
          if (money.money >= cost)
                {
                money.money -= cost;
                money.money += houseIncome;
                estate += 1;
                BuyValue = cost;
              
        }
    }

  

    IEnumerator Wait()
    {
        yield return new WaitForSeconds(1);

    }

Assets/Scripts/BuyCheapHouse.cs(36,22): error CS0118: `BuyCheapHouse.buySell' is a `field' but a `type' was expected



    public void Sell()
        {
            money.money += BuyValue;
            estate -= 1;
         
        }

  


}

Assets/Scripts/BuyCheapHouse.cs(36,22): error CS0118: BuyCheapHouse.buySell' is a field’ but a `type’ was expected

Change this:

foreach (buySell costGenerator in buyScripts)

To this:

foreach (Buy costGenerator in buyScripts)

The foreach loop is iterating (going over 1 by 1) each Buy script in your buyScripts array… costGenerator is a generic variable its assigning each buyScript to. so the first time through the loop, the compiler behind the scenes is doing this:
costGenerator = buyScripts[0]. Then the next time through the loop costGenerator = buyScripts[1]. And so on. So it needs to know what kind of variable costGenerator will be. Since buyScripts is a Buy[ ] array… costGenerator needs to be a Buy variable. buySell was just the name of one instance of Buy class. It doesn’t make sense to put it there. It would be like doing this:

int someInt;

someInt x = 5;

Just because someInt is an int. I can’t use it like the int keyword.

1 Like

I’ve implemented all of the changes and attached all the necessary scripts in the inspector, but they’re still all generating the same value not different ones.

I’m not getting any more errors.

What does GenerateCost actually do?

Generates a random number and assigns that as the cost of an item.

Post code :slight_smile:

I have managed to solve the random number generation issue, but have no managed to get a new issue "Null reference except: Object not set to an instance of an object.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Buy : MonoBehaviour {

    public BuyCheapHouse buyCheapHouse;
    public Text costDisplay;
    public bool owned;
    private float currentTime;
    private int costTime = 1;
    public int cost;
    public Money money;
    public int BuyValue;
    private int incomeTime = 1;
    /* public int houses; */
    public int estate;
    public int houseIncome;
   

    void Start()
    {
        owned = false;
        cost = Random.Range(2000, 4000);
        BuyValue = cost;
        estate = 0;
       
    }

    void Update()
    {
        if (owned == true)
        {
            costDisplay.text = BuyValue.ToString();
        }
        else
            {
            costDisplay.text = " " + cost;
        }

       
    }

    public void OnClickBuy()
    {
        if (owned == false)
        {
            if (money.money >= cost)
            {

                PurchaseHouse();
               
            }
        }
        else if (owned == true)
        {
            Sell();
            owned = false;
        }
    }

    public void GenerateCost()
    {

       
            if (currentTime < costTime)
            {
                currentTime += Time.deltaTime;
            }
            else
            {
                cost = Random.Range(5000, 100000 + 1);
                currentTime = 0;
            }

       

    }

    public void PurchaseHouse()
    {
            money.money -= cost;
            money.money += houseIncome;
          
       
        owned = true;
       
            estate += 1;
       
       
    }

    public void Sell()
    {
        GiveMoney();
       
        estate -= 1;
        Debug.Log("Assign money for sale: " + BuyValue);

    }

    public void GiveMoney()
    {
        money.money += BuyValue;
    }

   

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class BuyCheapHouse : MonoBehaviour
{


    public Money money;
    private int incomeTime = 1;
    /* public int houses; */
    private Buy buy;
    public Buy[] buyScripts;





    void Start()
    {
       

    }


    void Update()
    {

        if (buy.estate >= 1)
        {
            foreach (Buy costGenerator in buyScripts) //for every buy script in buyScript array GenerateCost
            {
                costGenerator.GenerateCost();

            }
        }
        else
        {
            return;
        }
        }
    }

The line is referencing the second script line 31 buy.estate >=1

It is an int, and it is set to 0 at the start.

buy is null - meaning it hasn’t been assigned to anything or the thing it was assigned to has been destroyed.

Frankly, it sounds like maybe you should take a step back and do some higher level programming tutorials/reading about OOP and C#

Buy is a script which has been assigned to 5 objects, all of which are active when the game initisalises.