- Home /
C# Inheriting from MonoBehaviour but still be able to instantiate with new()? How should I do this?
I'm trying to write a simple 'Conditions' combat system that allows for conditions to be applied to characters such as stun, poison, etc. I have the following generic class in C#:
public class Condition<T> where T : ICondition, new()
{
T condition = new T();
public void ApplyCondition() {
condition.ApplyCondition();
}
}
And an implementation of ICondition for stun:
public class Stun : MonoBehaviour, ICondition
{
private Material material = (Material)Resources.Load ("../Materials/Stunned");
public void ApplyCondition() {
ApplyStun();
}
private void ApplyStun() {
renderer.material = material;
}
}
Basically I just want the character to change material when he is hit with stun.
But of course, I'm doing something wrong here cause I get the following error:
You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed...
Which I know is because Stun inherits from MonoBehaviour and it is getting Newed in the Condition class, BUT I need it to inherit from MonoBehaviour so that it has access to the renderer component of the object it's attached to.
How should I be doing this instead?
I've stopped using new now and tried changing it to gameObject.AddComponent\ but still hitting some confusing issues. Is AddComponent the better way to go at least?
Yes, AddComponent is the desired way to add monobehaviours. $$anonymous$$eep in $$anonymous$$d you can grab a reference at the same time you addcomponent.
I'm trying to add the component this way (won't show up correctly in these comments so I pasted here http://pastebin.com/qzgBC$$anonymous$$Dz)
except it's now giving me "Can't add script behaviour ". Generic $$anonymous$$onoBehaviours are not supported"
Not really sure how to add the component correctly
What do you mean? There's exactly two opening brackets and two closing brackets
Answer by Bunny83 · Jan 03, 2013 at 07:40 PM
Sure it doesn't work because "Generic MonoBehaviours are not supported". It's easy as that. Also to be able to use a MonoBehaviour derived class it has to be placed in a script file with the same name. Of course a generic class can't work, Component types are determined by the class / filename. A generic type represents endless different "types".
Besides that you can only add classes as components that are derived from MonoBehaviour. Your generic class isn't derived from MonoBehaviour. Also i don't really get for what you want this generic? It does nothing "generic". It just encapsulates an ICondition object (which is just an interface so it could be anything that implements that interface).
You can simply add your Stun class as component since it actually is a component. Thanks to the interface you could access all components that implements that interface like this:
var conditions = (ICondition[])GetComponents(typeof(ICondition));
Note: You can't use the generic version of Getcomponent because UT put a constraint on the generic parameter and only allows types that are derived from Component which interfaces are not. However this "type" version works pretty well, so just add your class like this:
gameObject.Addcomponent<Stun>();
Yeah you're right, it doesn't do anything 'generic'. I really want to do this by inheritance ins$$anonymous$$d (Having Condition as an abstract class and then writing a bunch of classes that inherit/extend Condition, such as Stun, Poison, etc) however I've been instructed that Condition $$anonymous$$UST be a generic class. Not really sure why they want me to do it like this, but yeah
It makes no sense to make something a generic class without any use of the generic parameter. What are your exact requirements? Do you have to use Unity? Do they have to be Components?
$$anonymous$$eep in $$anonymous$$d that you can implement your own Strategy. You don't have to use the one that's built into Unity. Unity's systems is more restricted since Unity wants the control of when and how components are created / added.
I have to use Unity, and I must make use of a generic class named 'Condition'. It does not have to be a component, I just made it into a component since I was running into issues with making an instance of Stun in Condition (which didn't end up solving anything).
I think I'm just going to use inheritance after all. It may be the guy who wrote the instructions just chose the wrong word with 'generic' or he could be testing my design decisions and actually expecting me not to use it. It just makes no sense otherwise
Don't be afraid to email your Instructor know about the $$anonymous$$onobehaviour generic's limitation -- he might change the requirements.
Answer by jogo13 · Jan 03, 2013 at 06:55 PM
New answer from a better understanding of the question.:)
This is not generics, but you could make Condition an abstract 'base' class:
public abstract class Condition : MonoBehaviour {
And make stun, poison etc inherit from Condition:
public class Stun : Condition{
Any class that had a Condition variable could store stun, poison etc in that variable.
Thanks, that's actually the way I was thinking about doing it too, except my program$$anonymous$$g brief states that Condition $$anonymous$$UST be a generic class (I'm doing a take home test). It's a little strange design wise but it must be so.
Well, in this case you have to change one of those things:
Don't use a generic class
Don't attach it as component but keep your own list of objects
Don't use Unity3d because it doesn't support generic components.
Your answer
Follow this Question
Related Questions
An OS design issue: File types associated with their appropriate programs 1 Answer
C# Conception - Hide inherited members and functions 1 Answer
[C#] Using Static Create() methods with inheritance and Monobehaviours? 3 Answers
MonoBehaviour Inheritance, Singletons and Generics 1 Answer
Is it possible to make sealed overridden MonoBehaviour method. 0 Answers