Unity (C#) - public variable won't work in one specific function - c#

Ok so I have a variable called info which is of my own class called Kingdom Perk. It holds info about each different upgrade you can add to your kingdom and it gets passed to a script through a setup function, and in that function the public variable "info" gets assigned to whats passed in.
In an update function, if I write:
Debug.Log("Perk Name: " + info.Name);
It tells me "Cannon" or "Walls" e.t.c
But if I try to access it in a function that is run when a button is pressed, it tells me that "info" is null.
The setup function is always run before the button pressed function, and the same global variable works in the update function as it always tells me the correct thing, its only broken in this function.
Any help appreciated, ask if you need more detail
Thanks
EDIT: A different global variable also shows as null in this function only.
EDIT 2:
private KingdomPerk info;
public void Setup(KingdomPerk data)
{
info = data;
perkName.text = data.Name;
perkType.text = "Type: " + data.Type.ToString();
perkHealth.text = "Health: " + data.Health.ToString() + "HP";
perkUpgradeCost.text = "Upgrade Cost: " + data.UpgradeCost.ToString();
perkImage.sprite = data.Sprite;
}
public void UpgradeButtonPressed()
{
float money = FindObjectOfType<MapGenerator>().worldInfo.money;
if (money >= info.UpgradeCost && info.Level != info.MaxUpgradeLevel)
{
Debug.Log("We've got enough!");
money -= info.UpgradeCost;
info.DamagePerShot *= info.DamageMultiplier;
info.Health *= info.HealthMultiplier;
info.Level++;
info.UpgradeCost *= info.CostMultiplier;
info.FireRate *= info.FireRateMultiplier;
RefreshInfo();
}
else if (money < info.UpgradeCost)
Debug.Log("Get more money!");
else if (info.Level == info.MaxUpgradeLevel)
Debug.Log("Already max level!");
}
Setup is called here, in a different script:
void RefreshListItems()
{
ClearListItems();
for (var i = 0; i < perks.Count; i++)
{
if (perks[i].UnlockLevel <= FindObjectOfType<MapGenerator>().worldInfo.playerLevel)
{
GameObject perkObject = Instantiate(itemPrefab);
perkObject.transform.SetParent(scrollViewTransform);
PerkListItem perkItem = perkObject.GetComponent<PerkListItem>();
perkItem.Setup(perks[i]);
upgradeGOList.Add(perkObject);
}
}
}

Fixed - The onclick event was referencing the script on the prefab rather than the instantiated copies of that.

Related

Finding the right Button on click in Unity

So the answer might be simple but my brain doesn't want to work correct lol. My code generates button clones out of an JSON array, which works fine, this is the code:
void DrawUI(){
GameObject buttonObj = transform.GetChild (0).gameObject; //Gets button to clone it
GameObject g;
int N = allCars.Length;
for (int i = 0; i < N; i++)
{
g = Instantiate(buttonObj, transform);
g.transform.Find("name").GetComponent<Text>().text = allCars[i].carName;
g.transform.Find("type").GetComponent<Text>().text = allCars[i].type;
g.transform.Find("price").GetComponent<Text>().text = allCars[i].price+ "€";
if(balance < int.Parse(allCars[i].price))
{
g.transform.Find("price").GetComponent<Text>().color = Color.red;
} else if (balance >= int.Parse(allCars[i].price))
{
g.transform.Find("price").GetComponent<Text>().color = new Color32(53, 140, 3, 255);
}
g.GetComponent<Button>().AddEventListener(i, OpenBuyDialog);
itemIndex = i;
}
Destroy(prefab);
And now I have another method which has to do get the informations of the clicked button, thats the code for it:
public void BuyCar()
{
balance -= int.Parse(allCars[itemIndex].price);
popupNotify.OpenNotification();
}
You might already see the problem, in my for-loop I increase my int variable "itemIndex" and in my second method I'll call
balance -= int.Parse(allCars[itemIndex].price);
and the problem is, if I got for example 5 cars in my DB, "itemIndex" has the value "4" in the end and when I click the first button, it doesn't give me the price from the correct car, instead I get the price of the 5th car. I thought about using an ArrayList/List<>. As I said before, I don't get the it to work..
You could add a variable to each button holding its own associated index. Is Button.AddEventListener a custom method? I can't find it in the API docs. What is it doing with its first argument (i in this case)? If you could just access that value for the clicked button, it would solve your problem.
Otherwise, you could try using an anonymous delegate to essentially include the index as part of each listener. For example in the for loop:
int closureIndex = i ; // Avoid closure problems
g.GetComponent<Button>().AddEventListener( i, () => OpenBuyDialog(closureIndex) );
// If using the standard Unity UI.Button function it would be:
// g.GetComponent<Button>().onClick.AddListener( () => OpenBuyDialog(closureIndex) );
Then use that argument for the index in OpenBuyDialog(), e.g.:
public void OpenBuyDialog(int index)
{
BuyCar(index);
}
public void BuyCar(int index)
{
balance -= int.Parse(allCars[index].price);
popupNotify.OpenNotification();
}

How can I list rooms in Unity? (PUN2)

I need to list the romos there are in my lobby scene. For now, this is the code I've used but I don't know why it isnt working. Is this the correct way?
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
print(roomList.Count + " Rooms");
base.OnRoomListUpdate(roomList);
foreach (var Item in roomList)
{
RoomName = Item.Name;
PlayerAmount = Item.PlayerCount;
MaxPlayers = Item.MaxPlayers;
PhotonNetwork.Instantiate("RoomPrefab", transform.position, transform.rotation);
RoomPrefab.transform.Find("RoomName").GetComponent<Text>().text = RoomName;
RoomPrefab.transform.Find("PlayerInt").GetComponent<Text>().text = PlayerAmount.ToString();
if(MaxPlayers == 4)
{
GameObject.Find("IPlayerA").GetComponent<Image>().sprite = Four;
}
else if (MaxPlayers == 2)
{
GameObject.Find("IPlayerA").GetComponent<Image>().sprite = Two;
}
else if (MaxPlayers == 3)
{
GameObject.Find("IPlayerA").GetComponent<Image>().sprite = Three;
}
RoomPrefab.transform.SetParent(ScrollView.transform, false);
}
}
I need to specify that I'm using Photon's PUN2, so GetRoomList won't work.
PhotonNetwork.GetRoomList() is gone in PUN2. You get rooms list and updates from ILobbyCallbacks.OnRoomListUpdate(List roomList) callback. You can optionally cache it, update it and clear it when needed.
Also you can check updates from PUN to PUN2 here
https://doc.photonengine.com/en-us/pun/v2/getting-started/migration-notes
The OnRoomListUpdate() method is called only when you've explicitly joined the lobby via PhotonNetwork.JoinLobby(). It's not enough just to be connected to the MasterServer as Jevgeni Geurtsen suggested, at least in PUN v2.15 it works this way for me.

Assign string to label Object in C#

I have tried to assign a String to Label but i Cannot able assign to a Label Field
i have Attached my code with it
if (intAdditionalTestId == 16 || intAdditionalTestId == 24)
{
strControlName = "lblMGOSSC" + Convert.ToString(intAdditionalTestId).PadLeft(2, '0') + "01AddUpd";
DisplayMessage(strControlName.ToString().Trim());
lblField = (Label)Page.FindControl(strControlName);
if (lblField.Text.Contains("[ADD]"))
{
intUpdateFlag = 0;
}
else
{
intUpdateFlag = 1;
}
I want to store the value of strControlName to lblField
Error Message Displayed While Running the Code:
Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space.
You are trying to find label using a string which you want to set to as label text. It is wrong.
You should change it;
lblField = (Label)Page.FindControl(strControlName);
to
lblField = (Label)Page.FindControl("lblField");//"ldlField" is ID of label"
lblField.Text = strControlName;

Unity Button Delegates (AddListener)

I'm trying to instantie several button using prefab.
But I've got a problem to Delegate variable.
for(int i = 0; i < _partnerList.partner.Count; i++)
{
GameObject _instance_partner_button = Instantiate(_prefab_partner_button);
_instance_partner_button.name = "_button_"+_partnerList.partner[i].partner_name;
_instance_partner_button.transform.SetParent(GameObject.Find("_UI_menu_partner").transform, false);
// Change Value of The Button ----------------------------------------------------------------
Text _instance_partner_button_text = _instance_partner_button.GetComponentInChildren<Text>();
_instance_partner_button_text.text = _partnerList.partner[i].partner_name;
Button _instance_partner_button_button = _instance_partner_button.GetComponent<Button>();
int _tempInt = i;
// Delegate to Another Script ---------------------------------------------------------------
_instance_partner_button_button.onClick.AddListener(() => _scripts_myScripts_ui.AnimationMenuPartner(_tempInt));
// -------------------------------------------------------------------------------------------
}
The function AnimationMenuPartner() just Debug.Log(_tempInt);
No matter which button I press the result is the same.
I'm maybe missing something, as I see in this link it must be working correctly Link
Thanks you for your help.
Edit :
The Another Script with the function AnimationMenuPartner
public void AnimationMenuPartner(int _tempInt)
{
Debug.Log(_tempInt));
}
The log output print : "4"
Which is the length of the list.

ProcessBar counter C#

I have a question about the ProcessBar on C#,
How would I add the value of 1 to a label if the method used when passing an item within a list box was successful ?
I have a method like this
private static Form1 f1 = Application.OpenForms["Form1"] as Form1;
public static void GroupList1(processBar bar)
{
f1.listBox1.Items.Add("User1");
bar.Value = 100;
}
public static void GroupList2(processBar bar2)
{
f1.listBox1.Items.Add("User2");
bar.Value = 100;
} // Etc, etc - up to GroupList6
I would also like to have a label that tells me how many user's were successfully added (using the bar), I was thinking of adding a method like this :
if (bar.Value = 100)
{
f1.label1.Text = "" + 1;
}
Inside of my GroupList1/2 method, but the label always appears as the value 1 .
This method within the main form of my code loads a separate label :
for(int i = 0; int i < listBox1.Items.Count; i++)
{
label2.Text = i.ToString();
}
So, I would like label 1 to increase by 1 if the user has been loaded into my list box successfully, how would I do this ?
Obviously this isn't actually the code I'm using within my program, a method is used if the selected index changes (which is why I want to increase by 1, to ensure the user parsed the method successfully), but the question still remains as described, thanks.
I dont quite understand well what are you trying to achieve, but if you only look in increasing the value of such label then you can easily do this by
if (bar.Value = 100)
{
f1.label1.Text = ""+(int.Parse(f1.label1.Text)+1);
}
or even a better way to initialize the string if for some reason the Text of the label is not an integer
if (bar.Value == 100)
{
int value;
if(!int.TryParse(f1.label1.Text,out value))
{
f1.label1.Text = "1";
}
else
{
f1.label1.Text = ""+(value+1);
}
}
but the best way to do this is to keep track of the value in a separate variable and just update the content of the label.
It's a bad idea to store the actual count in the label's Text property, instead, create a variable:
private static int count;
Now, change your code to something like this:
if (bar.Value = 100)
{
// Add 1
count += 1;
// Update the UI
f1.label1.Text = count.ToString();
}

Categories