- Home /
Using GetComponent in multiple scripts for same component? C#
Hello everyone. The title pretty much explains it all. I'm trying to reference the player's lives in my game in multiple scripts to make multiple things happen if it hits zero, but I keep getting errors in scripts that reference it. It's like Unity is only letting me use GetComponent on it once, then it won't work anymore. By the way, I'm trying to get a script and use it's playerlives variable/score variable. I tried static at first, but then the static variables are stuck that way and won't reset if the player presses the restart button. Here are 2 of my scripts; the first has the problems, the second works fine. By the way, the script component I'm referencing is called "PlayerData."
using System.Collections;
public class Endless : MonoBehaviour {
private Transform myTransform;
public float minspeed = 1f;
public float maxspeed = 10f;
public float currentspeed;
int x,y,z;
// Use this for initialization
void Start () {
myTransform = transform;
currentspeed = Random.Range(minspeed, maxspeed);
x = Random.Range (-10, 10);
y = 8;
z = -1;
myTransform.position = new Vector3 (x,y,z);
}
// Update is called once per frame
void Update () {
myTransform.Translate (Vector3.down * currentspeed * Time.deltaTime);
if (myTransform.position.y <= -8) {
x = Random.Range (-10, 10);
currentspeed = Random.Range (minspeed, maxspeed);
myTransform.position = new Vector3 (x, 8, z);
Instantiate(myTransform, new Vector3(x, 8, z), Quaternion.identity);
}
}
void OnTriggerEnter (Collider collider){
GameObject PlayerData = GameObject.Find ("PlayerData");
PlayerData playerdata = PlayerData.GetComponent ("PlayerData");
//if laser hits enemy, destroy enemy
if(collider.gameObject.CompareTag("Laser")){
Instantiate(myTransform, new Vector3(x, 8, z), Quaternion.identity);
Destroy (gameObject);
}
if (collider.gameObject.CompareTag ("Player")) {
playerdata.score += 50;
//Unity denies this and gives this msg: Assets/Scripts/Endless.cs(37,28): error CS0266: Cannot implicitly convert type UnityEngine.Component' to
PlayerData'. An explicit conversion exists (are you missing a cast?) Destroy(this.gameObject); } }
//Script that works with GetComponent
using UnityEngine;
using System.Collections;
public class MyGUI : MonoBehaviour {
// Use this for initialization
void Start () {
//how to call an unstatic component from another gameobject
//in this case, I called it's script component so I could reference nonstatic variables.
//GameObject PlayerData = GameObject.Find ("PlayerData");
//PlayerData playerdata = PlayerData.GetComponent ("PlayerData");
}
// Update is called once per frame
void Update () {
}
void OnGUI () {
GameObject PlayerData = GameObject.Find ("PlayerData");
PlayerData playerdata = PlayerData.GetComponent ("PlayerData");
GUI.Box (new Rect (700, 25, 300, 100), "Score : " + playerdata.score + " Lives: " + playerdata.playerlives);
}
}
Sorry if the question is confusing. All help is appreciated!
Answer by Hoeloe · Mar 13, 2014 at 12:42 AM
The problem is that the non-generic GetComponent
method returns something of type Component
, not of the type you're trying to assign it.
First of all, if there is a generic version of a method (that is, one that uses triangle brackets) then always, always, always, ALWAYS use it. It is more efficient, and less confusing in your code. In this case, it would also solve your problem, as it would return the correct type, too.
Secondly, I recommend looking up some of the basics of programming, particularly how objects and types work, and specifically how to read error messages. While in everyday usage of a computer, it's generally not particularly important that you understand error messages thrown at you, in programming, it is vital. Make sure to read the error messages you get given. Let's examine this one.
Cannot implicitly convert type UnityEngine.Component to PlayerData. An explicit conversion exists (are you missing a cast?)
Okay so, what does this say? Well, it says that Unity is trying convert the types of something. Namely, it's trying to convert something from the type UnityEngine.Component
to the type PlayerData
. It says that no implicit conversion exists. This means that C# doesn't know how to change the type of something like this, without you explicitly telling it to. So how do you explicitly change the type? You use what's called a cast. Casting is a way of saying "I want this to be this type". It is not always possible to cast something from one type to another, but in this case, you can (to see why, look up inheritance and casting). In C#, there are two kinds of casting: the regular cast, and the as cast. I'll do a quick example of both:
Say you have an object called Obj
, and you want it to be of type ScriptType
, but it is actually of type Component
(we will assume ScriptType inherits from Component via Monobehaviour). Well, we can do this with a regular cast:
(ScriptType)Obj
This notation means: "The thing immediately following these brackets should be the type specified in these brackets." C# will then try and change the type of the object from whatever it currently is to what you want it to be. Crucially, if it can't do this, then you will get an error (namely an InvalidCastException).
You can also do it like this:
Obj as ScriptType
This means something very similar: "I want this object to be of this type." This does exactly the same thing as the regular cast except when it fails. While the regular cast will throw an error, this one will just set the value to null
. It is worth taking into account these differences. In most cases, you should use the regular cast, because in most cases, a failed cast means something has gone wrong in your program. The as cast has its uses, but they are not as many as you might think.
Hopefully this has given you a bit of a glimpse into what has gone wrong, and how to fix it.
Thank you for this! You did way more than I asked, and you even went above and beyond to explain casts to me and such! I'm still new to C# (I've only done web languages in the past), so this was extremely helpful! Thank you very much.
And thank you for being willing to learn and not just looking for a quick fix. You'll go far with that attitude.
Answer by highpockets · Mar 13, 2014 at 12:47 AM
PlayerData playerData = PlayerData.GetComponent<PlayerData>();
Should do the trick
I'm very against people just posting the code like this, because it encourages "copy and paste" program$$anonymous$$g. At least a brief explanation of why this fixes it would be better, ignoring the fact that I already told him to do this in my answer.
This didn't even work anyways O_o
It says that the bracket ")" isn't expected. I can't get it to work with anything, even a cast. Anyone know why?
Hey buds, I was posting this quickly on my phone, I was trying to help the guy/girl. Since you had the luxury of having time for a lengthly explanation...... well, congratulations!! I guess that makes you a better man or an exceptional woman. FYI, at the time I was posting, there was no answer, so I wasn't trying to pull a quick one like you suggest. You would have known that if you took a look at the posting times though, since you're such a thorough person, I find it hard to believe that you didn't check that. So, before you pull out comments to describe people as ignorant, maybe you should take the time, that I know you have, to scrutinize the facts, so I don't have to waste my time proving my innocents and, in turn, your ignorance....... To those whom are looking, this is not my answer to a question, just a fun little rebuttal, so don't 'copy and paste'.
How's that for an explanation Hoeloe. BTW, nightbane, the code works, I use it all the time. Anyways, I'm glad you got it working, just not so sure I like your lecturer ( and I guess $$anonymous$$e as well ).
I had to come back because I realize that maybe you haven't actually answered this yet, but just accepting the answer above in appreciation for the description on casts.
Sorry to ask the obvious, but I'm just making sure that you have a game object named PlayerData in your hierarchy and on that game object, you have a component named PlayerData??
Yeah, my Gameobj is called PlayerData with the script attached named PlayerData as well.
Your answer
Follow this Question
Related Questions
Multi similar script Components same game object 1 Answer
C# GetComponent, component not turning off. 2 Answers
Distribute terrain in zones 3 Answers