- Home /
Get unity to recognize prefab in C#
Hi. This seems like it should be pretty basic. I have a prefab called Grapple_Arrow. It contains meshes and scripts. I want to instantiate one of these when I hit a key, lets say. According to documentation I should do something like:
public class example : MonoBehaviour {
public Missile projectile;
void Update() {
if (Input.GetButtonDown("Fire1")) {
Missile clone;
clone = Instantiate(projectile, transform.position, transform.rotation);
clone.timeoutDestructor = 5;
}
}
}
Except that if I do exactly that with my prefab, I get an error:
error CS0246: The type or namespace name `Grapple_Arrow' could not be found. Are you missing a using directive or an assembly reference?
What I can do is this (feels like a workaround):
public class LerpzGrapple : MonoBehaviour {
public GameObject theGrapple;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
// later change this to getButtonDown
if (Input.GetKeyDown(KeyCode.Return)) {
GameObject grapple = Instantiate(theGrapple, transform.position, transform.rotation) as GameObject;
//grapple.OriginatingObject = gameObject;
Grapple grappleScript = grapple.GetComponent("Grapple") as Grapple;
grappleScript.originatingObject = gameObject;
}
}
}
And lo, it actually instantiates an object (actually I just figured this part out while typing the question). But it seems kind of a roundabout way. Can't I just add a line "using MyPrefab" or #include MyPrefab or something?
As it is, I can only instantiate a generic GameObject (which I even have to cast from Object to GameObject?!) when it seems I could have access to the exact prefab and all its many scripts and properties. (That's how it would be if I was working in pure code anyway.) From my generic GameObject, to access a property I have to do GetComponent()... which, while I don't know how it actually works, it looks like it's doing a string comparison. I hope that's in the precompile stage only. :)
So the crux of my long-winded question here is:
- am I doing this right?
- Is any part of my code redundant or suboptimal?
- Is there an easier / better way (in C#) ?
Answer by Eric5h5 · Mar 14, 2011 at 08:24 AM
Your "workaround" is generally how it's done, except you can combine all those steps into one. Also you should generally not use strings in GetComponent (see the docs, although in addition to performance, you get compile-time error checking instead of runtime), and using generics is simpler.
(Instantiate(theGrapple, transform.position, transform.rotation) as GameObject).GetComponent<Grapple>().originatingObject = gameObject;
You could shorten it by declaring the prefab like this:
public Grapple theGrapple;
Then you can cast to Grapple when instantiating:
(Instantiate(theGrapple, transform.position, transform.rotation) as Grapple).originatingObject = gameObject;
What type you use depends primarily on what's most convenient to refer to with the instantiated object.
public Grapple theGrapple; <---- Yes this is what I want to do! But it throws an error.
Ok, my exact prefab name is Grapple_Arrow in the Project view. I only have the standard includes in my C# file. I declare:
public Grapple_Arrow theGrapple;
As soon as I hit save, I get this error:
The type or namespace name `Grapple_Arrow' could not be found. Are you missing a using directive or an assembly reference?
So what could be wrong with my prefab that would cause this error? What you wrote is what I wanted to do in the first place. I just tried it again and got the error again.
Just one more note, Grapple is the C# script attached to the Grapple_Arrow prefab.
@robertbeverly: you can't use the prefab name as a type; it's just an identifier name and isn't generally used in code for anything (aside from Resources.Load). The script/class name (typically they are the same) can be used as a type.
Answer by Lab013 · Mar 14, 2011 at 08:26 AM
There's nothing really inherently wrong with how you are instantiating/using grapple. I presume that you are getting that error because Grapple_Arrow is a prefab. Prefabs themselves aren't types, they're components or GameObjects, so you can't create a variable who's type is a prefab name.
Please don't use this site for advertising. You can put that sort of thing in your bio.
Please don't advertise on this site* (I assure you I was not just using this site for advertising). Excuse my ignorance. I presumed from the dividers appearance that it was commonly used as a signature separator under which case the use of a link to my thread would be appropriate. I didn't realize that it is protocol to put a link like that in the semantically incorrect 'bio' section of my profile. Thank you for the correction.
Lab013 maybe that's it then? I thought the whole point of prefabs was that you could instantiate them at runtime. I can drag it into the public iVar if it's created as a gameObject. But then I have to treat it like a gameObject until I retrieve its custom components specifically. $$anonymous$$ind of weird when you're used to pure code, where if you write a class or a protocol for an object you can always access its known methods or properties.
@Lab013: sorry, but this isn't a forum, and signatures aren't used.
@Eric5h5 Yes, I am new to this format, and signatures are used in many areas, as I said, thank you for the correction.
@robertbeverly You can instantiate them at runtime, however, you don't instantiate them by name. You drag the prefab instance from the project view and link it into the GameObject variable in your script.