• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by petur · Feb 01, 2018 at 04:49 PM · scriptableobjecttypeaddcomponentskills

Assign a variable of type "type" on the inspector or best work around

Hello. Can I have a variable of type "Type" in a scriptable object, and can I assign it somehow in the inspector?

What I want to achieve

Code in the scriptable object:

 public class BaseSkill : ScriptableObject
 {
     public Type skillImplementationType;
 }

Code where I use that info:

 gameObject.AddComponent< myBaseSkill.skillImplementationType >();


Why

I am making an RPG and skills are monobehaviours attached to character gameobjects. Since many skills have similar behaviours but different attributes (for example, a FireBall deals 40 damage and GreatFireBall 60) I do not need a different monobehaviour for every skill. So I have a BaseSkill scriptableobject with all the info about a skill. I want to somehow store in that scriptableobject what class do I need to add to a gameobject so the character it represents can use said skill.

So, both "fireball" and "greatfireball" would add the class "projectileSkill" to the gameobject, but the "GroundSlam" skill would add the "areaDamageSkill" instead.

  • All skills inherit from a Skill class.

  • There are no other instances of that monobehaviour present so neither "typeof()" nor "GetType()" are of any use.

Is there any way to implement this?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by MacDx · Feb 01, 2018 at 05:29 PM

What you can do is parse a string into a Type using the static GetType method from the Type class. Something like:

 //This will add a Fireball script to the gameobject
 string typeString = "Fireball";
 Type t = Type.GetType(typeString);
 gameObject.AddComponent(t); //Assuming Fireball inherits at least from component, of course.

Hope this helps!

By the way AFAIK, this is not correct C# :

 gameObject.AddComponent< myBaseSkill.skillImplementationType >();

You cannot use an expression as the generic parameter for the method or class, it should always be a class name. Unity provides methods with normal Type parameters for those cases (Where said type inherits from unity's object, or component in this particular case).

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image petur · Feb 01, 2018 at 05:38 PM 0
Share

Thank you very much, that will work fine!

About your side note about the AddComponent function, are you sure? The second description in the manual suggests otherwise. https://docs.unity3d.com/ScriptReference/GameObject.AddComponent.html

avatar image MacDx petur · Feb 01, 2018 at 05:41 PM 1
Share

No prob. Also, yes I'm sure and the docs do not suggest otherwise. Take a closer look:

This:

 gameObject.AddComponent ( myBaseSkill.skillImplementationType);

And this:

 gameObject.AddComponent <myBaseSkill.skillImplementationType> ();

Are 2 very different things. And the second one is wrong. Try it out.

avatar image MacDx MacDx · Feb 01, 2018 at 05:45 PM 0
Share

If you don't understand the difference between them I suggest you to do some research on C#'s generic methods.

https://docs.microsoft.com/en-us/dotnet/csharp/program$$anonymous$$g-guide/generics/generic-methods

avatar image
4

Answer by Bunny83 · Feb 01, 2018 at 09:44 PM

The best workaround is to implement a custom editor or propertydrawer that allows you to select a type and have a wrapper to store the type as assembly-qualified type name. I've written such an editor extension some time ago but can't find it ^^. However i've found this solution that numberkruncher posted.


Though everything MacDx said is right so make sure you use the System.Type version of AddComponent and not the generic version.


edit

I just found my general purpose "SerializableType" class. It allows you to serialize any System.Type that represents an actual type, even types with generic arguments. Of course generic types can't be used in AddComponent as Components need to be concrete types without generic parameters. It's only a serialized version of System.Type. It doesn't include any "visual" editor magic. Along with the SerializableType i've also created a SerializableMethodInfo. Though if you're not familiar with reflection you may just ignore this ^^.


Apart from the general purpose SerializableType i've also found my MonoScriptAttribute and the associated property drawer (MonoScriptPropertyDrawer). It allows you to simply attach the [MonoScript] attribute to a serialized string variable and get an object field where you can drag and drop monoscripts from the project (script assets). It will store the type name in the string variable. The MonoScript attribute also allows you to filter the allowed types.

 [MonoScript(typeof(IMyInterface))]
 public string componentTypeName;

This would only allow dragging component types to the object field which implement the given interface. It was just a simple implementation. It may be useful depending on the exact usecase.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image mikeNspired · Aug 26, 2019 at 08:32 PM 0
Share

Dude!! This is $$anonymous$$oney!!! The $$anonymous$$onoScriptAttribute. Works perfect.

System.Type type = System.Reflection.Assembly.GetExecutingAssembly ().GetType (componentTypeName); AddComponent(type);

This opens up so many more possiblities to making scripts more modular.

avatar image Nick62 · Jun 29, 2020 at 02:39 PM 0
Share

How does this solution ($$anonymous$$onoScriptAttribute and the associated property drawer ($$anonymous$$onoScriptPropertyDrawer)) work when refactoring (rena$$anonymous$$g) an assigned class?

avatar image Bunny83 Nick62 · Jun 29, 2020 at 05:39 PM 1
Share

Well, it doesn't ^^. A serialized type name is data, not code. So when you refactor a type name in your code it won't affect the serialized data. Therefore the type that was serialized does no longer exist. In theory It might be possible to not only save the actual type name but also store the GUID of the $$anonymous$$onoScript asset. That way we might be able to detect any refactoring inside Unity. Keep in $$anonymous$$d that changing the name of a $$anonymous$$onoBehaviour or ScriptableObject also requires a change of the actual filename (along with the meta file). So that's in general not a trivial issue.


Keep in $$anonymous$$d that most serialization systems have this issue. For example the BinaryFormatter will completely choke on any serialized data if any of the involved types received a name change or rena$$anonymous$$g / addition / removal of fields.

avatar image marek_PLH · Feb 11, 2021 at 11:27 AM 0
Share

If anyone would encounter an issue with $$anonymous$$onoScriptAttribute not detecting classes inside namespaces then change script.GetClass().Name to script.GetClass().FullName; in line 89.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

79 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

ScriptableObject problem and creating a new class instance 1 Answer

ScriptableObject.CreateInstance(Type T) keep crashing 2 Answers

Skill system 0 Answers

C# string as type for AddComponent 2 Answers

Cant add a script as component. Type is derived by base class 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges