- Home /
Using AddComponent to add a Sub Class using a String
I'm trying to temporarily add a component that is a sub class in order to load certain variables.
var equipTex = GetEquipment("Gloves");
Gloves inherits from a type "Equipment".
public string GetEquipment(string equipmentName)
{
var equipName = (Equipment)gameObject.AddComponent(equipmentName);
Debug.Log(equipName);
}
When I try the code above, I will get this:
Can't add component because class 'Gloves' doesn't exist! UnityEngine.GameObject:AddComponent(String)
However, if I were to assign "equipmentName" to Equipment, it will not give me that error.
I'm beginning to believe that subclasses cannot be used by storing their name as a string, and calling them by that string, but classes that inherit from Monobehaviour can.
Is their something that I'm not getting? Or will I have to try another method?
This should work, but Unity can't find the Gloves class apparently . Are both classes implemented in C# ?
Yep. That's why I'm getting a major headache. The class "Gloves" is written in the same script as "Equipment" <-- The only one deriving from monobehavior. Is that a problem, because I really don't want to write a script for each equipment...
In a separate script from where the Equipment classes are: Equipment$$anonymous$$anager();
What do you mean "in the same script as 'Equipment' ? It's declared inside Equipement ? Or does it inherit from it, in another file / scope ?
Answer by fafase · Nov 16, 2012 at 09:35 AM
OK here I got it working with a generic type:
void GetEquipment() where T : class, new(){
gameObject.AddComponent(typeof(T));
}
and you call like this:
GetEquipment<Gloves>();
It works for me, so there is no reason it should not work for you. :)
Edit: Let's take an example. One file:
using UnityEngine;
using System.Collections;
public class Equipment : MonoBehaviour {
public Vector3 velocity;
public Transform _transform;
protected int health;
public virtual void Start(){
velocity = new Vector3(Random.Range(0.5f,1.5f),0,0);
_transform = GetComponent<Transform>();
}
public virtual void Update(){
//Some Update
}
}
public class Gloves : Equipment {
public int variable;
public override void Start () {
base.Start();
variable =10;
}
public override void Update () {
base.Update ();
}
}
Ok so we have in the same file two classes Equipment and Gloves that inherits from Equipment
Just for the example here is a third independent class:
using UnityEngine;
using System.Collections;
public class NPC : Enemy {
public int varToShowInTheInpsector;
public override void Start(){
base.Start ();
varToShowInTheInpsector = 100;
}
public override void Update(){
//Some stuff happening here
}
}
Now we have an object with another script that is not any of those above:
using UnityEngine;
using System.Collections;
public class MyClass : MainClass {
public override void Start () {
base.Start ();
}
public override void Update () {
//Many stuff here
if(Input.GetKeyDown(KeyCode.A))
GetEquipment<Gloves>();
else if(Input.GetKeyDown(KeyCode.B))
GetEquipment<NPC>();
else if(Input.GetKeyDown(KeyCode.C))
GetEquipment<Equipment>();
}
void GetEquipment() where T : class, new(){
gameObject.AddComponent(typeof(T));
}
}
Try that on and you will see new script popping up on your inspector. I added some public variable so that you can see that the appropriate class is created. You see how easy it gets to add any custom component?
Ah, this is a little new to me (Generic types). Is it possible to use this in such a way that I can call it like: GetEquipment () <--- equipmentName, considering each equipment will have it's own type? (with a base class of Equipment?)
I will extend my answer with a larger example. Give me a few $$anonymous$$utes, I 'll be back
Answer by Seth-Bergman · Nov 16, 2012 at 09:16 AM
Your problem is, this is half C#, half JavaScript!!! Otherwise though, what you are trying to do will work perfectly, if you just get the SYNTAX right:
case JavaScript:
function GetEquipment(equipmentName : String)
{
var equipName = (Equipment)gameObject.AddComponent(equipmentName);
Debug.Log(equipName);
return equipName.ToString(); //????
}
...
var equipTex = GetEquipment("Gloves");
in JAVASCRIPT, the class and subclass are declared this way:
[http://answers.unity3d.com/questions/7614/does-unity-support-inheritance-and-subclassing.html][1]
case C#:
public string GetEquipment(string equipmentName)
{
Equipment equipName = (Equipment)gameObject.AddComponent(equipmentName);
Debug.Log(equipName);
return (string)equipName; // ???
}
....
string equipTex = GetEquipment("Gloves");
the classes here are declared this way:
public class Equipment : MonoBehaviour
{
...etc
public class Gloves : Equipment
{
...etc [1]: http://answers.unity3d.com/questions/7614/does-unity-support-inheritance-and-subclassing.html
If you refer to var being UnityScript, var is also a c# keyword http://msdn.microsoft.com/en-us/library/bb383973.aspx
Well, actually, you can declare a variable as 'var' in C# too. So his code is correct in C#.
I was about to note that. I tried the same thing as above, but strangely, I'm getting the same error.
OOps, my mistake... thought you were declaring the classes wrong, didn't know about that with var too.. :)
at any rate
the reason your script isn't working, incedentally, is that you need to save each class in a SEPARATE script
the name of the file is the reference to the contained class
I got it working with both classes in the same file. This is just a matter of making the function generic and telling the compiler you want the type to be a class and have the new constraint.
Fact is there might be some less scary ways but they would be longer to write and debug :).
Answer by FakeBerenger · Nov 16, 2012 at 09:26 AM
I tested it, and your problem is that Gloves is in the same file as Equipment. Create a Gloves.cs. It would have worked with AddComponent( typeof(Gloves) ) though.
I had a feeling that was the reason. I was trying to be lazy and call the equipment by name, though, the problem with the second part of your solution, combined with my "lazy idea" is that i wouldn't be able to use (typeof(equipmentName)), since the contents of "equipmentName" would be the type.
I'm mainly using the string technique so that I won't have to write 20+ .CS files for like, 5 lines of code in each .CS.
Yeah, they have a tendency of wasting a lot of time when they don't work :D
So, ultimately though, your original suspicion was correct, it seems:
using the STRING version rather than the generic was the problem.. :
(as originally stated ) ...subclasses cannot be used by storing their name as a string, and calling them by that string, but classes that inherit from $$anonymous$$onobehaviour can.
Answer by SrBilyon · Nov 16, 2012 at 09:33 AM
For the moment, to get it in a working condition, I started writing functions for each Equipment, and I'm using
SendMessage(equipmentName);
to call the function with the appropriate name of the Equipment I want. That function will load the values I need, and presto. Now that I think about it, writing a class for each equipment would have been a little overboard, since I only need the classes to hold variables XD
What are you guy's opinion on this?
Your answer
Follow this Question
Related Questions
Making a static class derive from MonoBehaviour in C# 3 Answers
Issues Inheriting classes and monoBehaviour 1 Answer
How to store data in script and attach it later? 0 Answers
Will using a Monobehaviour script versus a non-Monobehaviour script use less memory? 2 Answers
can't place inherited class of an abstract class in editor? 1 Answer