- Home /
Use Instantiated clone in the next function in same class
Hi, my question is probably really stupid but I can't seem to find a general rule for it or better, because sometimes it seem to work and sometimes not. Maybe someone can bring some enlightment to me :)
Here I add my variables in the beginning
public GameObject attack;
public GameObject defenseButton;
GameObject attackClone;
GameObject defenseButtonClone;
In the inspector I have dragged the prefabs for attack and defenseButton onto the slots in the script.
In the update function I instantiate the attack GameObjekt as affackClone (inside an if statement)
attackClone = Instantiate(attack);
attackClone.transform.SetParent(thisIsTheCanvas.transform, false);
attackClone.tag = "AttackButton";
In the same script a little further down I have a function called AttackButtonClicked which get's called if the AttackButton gets clicked (On Click () of UI Button). Inside this script I want to destroy the attackClone. But in order to do that I have to define the variable attackClone again using FindwithTag.
public void AttackButtonClicked () {
attackClone = GameObject.FindWithTag ("AttackButton");
Destroy(attackClone);
ShowDefenseButton ();
Debug.Log ("Button Destoryed" + attackClone);
}
I just don't know why I have to assign the variable again? Shouldn't it work all over this script? If not why? Has it something to do with ActionButtonClicked being called by a UI Button? Maybe someone can explain this to me?
EDIT Here's teh fullcode after changing it from the suggestion from the first answer
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class SelectCountry : MonoBehaviour {
public bool attackFromCountry = false;
public bool attackThisCountry = false;
public bool buttonIsThere = false;
//GameObject attackingCountry;
int unitsInAttackingCountry;
//Canvas and Buttons
GameObject thisIsTheCanvas;
public Button attack;
public GameObject defenseButton;
public Button attackClone;
GameObject defenseButtonClone;
//Selected Countries to reset
GameObject firstSelectedCountry;
GameObject secondSelectedCountry;
void Start (){
thisIsTheCanvas = GameObject.Find("Canvas");
}
void Update() {
if (Input.GetMouseButtonDown(0)){
Debug.Log ("LeftClick");
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (hit.collider != null) {
// Select Country to attack from
if (attackFromCountry == false && hit.collider.tag == "Untagged"){
//attackingCountry = hit.collider.GetComponent<CountryBaseClass>();
Debug.Log ("wossers");
unitsInAttackingCountry = hit.collider.GetComponent<CountryBaseClass>().unitsCountry;
if (unitsInAttackingCountry >= 2){
hit.collider.tag = "isActiveAttacker";
attackFromCountry = true;
Debug.Log ("wow");
}
}
// Select Country you want to attack and make it possible to deselect country
else {
if (attackThisCountry == false && hit.collider.tag == "Untagged" && attackFromCountry == true){
hit.collider.tag = "isActiveDefender";
attackThisCountry = true;
Debug.Log ("super");
}
else {
if (attackFromCountry == true && hit.collider.tag == "isActiveAttacker" && attackThisCountry == false){
hit.collider.tag = "Untagged";
attackFromCountry = false;
}
if (attackThisCountry == true && hit.collider.tag == "isActiveDefender"){
hit.collider.tag = "Untagged";
attackThisCountry = false;
}
}
}
}
}
// Show Attack Button if a two countrys are selected
if (attackFromCountry == true && attackThisCountry == true && buttonIsThere == false) {
attackClone = Instantiate(attack);
attackClone.transform.SetParent(thisIsTheCanvas.transform, false);
attackClone.tag = "AttackButton";
buttonIsThere = true;
}
// Destroy attack Button if country is deselected
if (buttonIsThere == true && attackThisCountry == false) {
Destroy(attackClone);
Debug.Log ("Button Destoryed" + attackClone);
buttonIsThere = false;
}
}
// Check if attacked button was klicked and then disable it and show defend button
public void AttackButtonClicked () {
//attackClone = GameObject.FindWithTag ("AttackButton");
//Destroy(attackClone);
attackClone.enabled = false;
ShowDefenseButton ();
Debug.Log ("Button Destoryed" + attackClone);
}
public void ShowDefenseButton () {
defenseButtonClone = Instantiate(defenseButton);
defenseButtonClone.transform.SetParent(thisIsTheCanvas.transform, false);
Debug.Log ("Show Defense");
}
public void DefenseButtonClicked () {
defenseButtonClone = GameObject.FindWithTag ("DefenseButton");
Destroy(defenseButtonClone);
//reset
firstSelectedCountry = GameObject.FindWithTag ("isActiveAttacker");
firstSelectedCountry.tag = "Untagged";
secondSelectedCountry = GameObject.FindWithTag ("isActiveDefender");
secondSelectedCountry.tag = "Untagged";
}
}
$$anonymous$$ore info please!
It's not clear why you think you do have to assign it again. What happens if you don't?
And do you know for sure that the object has been instantiated when the ActionButtonClicked gets called?
If I don't assign it again, meaning "attackClone = GameObject.FindWithTag ("AttackButton");", then the Destroy(attackClone) doesn't work and the attackClone wont get destroyed. This is the output in the console: Button Destoryednull UnityEngine.Debug:Log(Object)
The object it self gets instantiated in the update function and yes it get's instantiated. I can see the clone in the hierarchy.
I thought that the variable attackClone should work in the whole script and not only in the update function.
Answer by InsertFunnyUsernameHere · May 15, 2015 at 07:44 PM
1
Are you sure you want to destroy that button? Maybe you just want to disable it? I can hardly think of a situation where destroying a GUI button would be helpful... In this case attackClone.enabled=false should do the job and later on you can enable it again without the need to instantiate another button.
2
make attackClone public and check in the inspector if it's initialized (not null). If it is indeed initialized then you shouldn't need to call the FindWithTag function
hey thanks for your answer. I made attackClone public and before it is instantiated the field for it in the inspector is empty as soon as it instantiated it appears in the field in the inspector as it should. If i comment this: attackClone = GameObject.FindWithTag ("AttackButton"); out in the AttackButtonClicked function it still says: Button Destoryednull UnityEngine.Debug:Log(Object)
So making it public isn't the solution.
Disabling sounds like a good idea. I changed the GameObject to Button. The instantiation still works fine but now I get: NullReferenceException: Object reference not set to an instance of an object SelectCountry.AttackButtonClicked () (at Assets/Scripts/SelectCountry.cs:118)
I'll try to post the full code in the question
I also want to say that everything works fine if I use the attackClone = GameObject.FindWithTag ("AttackButton");. I just think it is strange and unnecessary. Also if I want to disable the Button I don't know how to find it again, because findwithTag, etc doesn't work on the Type Button :(
Okay so, I could explain you all the problems your code has but the question is, if trying to repair them is worth your time. Your code is very messy and I don't think you will get much further than this without getting tons of issues. In the end it might prove better to just start from scratch and rewrite everything.
If you are going to start again then here are some quick tips 1) $$anonymous$$eep you current scripts. Save them somewhere so after you're done you can compare your new scripts with the old ones 2) Split your code into smaller parts. $$anonymous$$ake one script handle one task and one method handle one basic action, don't just put everything into the update function. 3) Using "Find" functions should be your last resort. Try to learn different ways of accesing your GameObjects (such as storing them in an array or a List) 4) If you seriously want to develop games then you have to learn inheritance, polymorphism and OOP(search on the web). This is going to save you a lot of work. 5) Before even starting try to draw all your classes, systems and relations on a sheet of paper. If you can't do that that means you probably shouldn't start yet and learn more. 6) Sometimes it might hurt, don't give up.
Thanks for your constructive critisism. I am aware that my code probably sucks :) Since I am a hobbyiest game developer I learned all my coding from webtutorial and using try and error. So sadly nobody taught me how to do stuff right. So I will try to do better and folllow your advice.
But still I would like to get an answer to my question...
Alright, I also learned everything by myself so I know the pain.
As to the errors in your code...
1
You put Destroy(attackClone) before Debug.Log("Button Destroyed" + attackClone). Doing so will always result in printing "Button Destroyednull" to the console because by the time you call Debug.Log the attackClone is already destroyed (so it returns null). You should put Debug.Log before the Destroy function call.
2
You can find the exact line in your code which causes the NullReferenceException by simply double clicking the message in the console or by using the $$anonymous$$onoDevelop's debugger. This exception is usually caused by requesting a variable or calling a method from a class which has no instance. $$anonymous$$ake sure it is initialized and the problem should be solved.
Hope this helps
Your answer
Follow this Question
Related Questions
Calling a variable 2 Answers
Pressing space calls the wrong function 1 Answer
Setting the variable on a GameObject to be instantiated (not yet existent) cs and js 2 Answers
IEnumerator problem 1 Answer