• 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
0
Question by chubit · May 01, 2017 at 02:24 PM · 2dgameobjectgeneric

Generic types in C# for a function

I was trying to create a function that returned a GameObject with a sprite, a BoxCollider2D, and some other things. I didn't want to do it every time I make a new object because I make one a lot. I also wanted to attach a component I called BulletBehavior to the object, but BulletBehavior is abstract so I needed to specify which one I wanted to use. This code, for some reason, is not working:

 public static GameObject readyObject<T>(T behavior, Sprite sprite, Vector2 scale){
         GameObject obj = new GameObject ();
         obj.tag = "Bullet";
         obj.AddComponent<SpriteRenderer>();
         obj.GetComponent<SpriteRenderer>().sprite = sprite;
         obj.AddComponent<BoxCollider2D> ().isTrigger = true;
         obj.AddComponent<T>();
         obj.transform.localScale = new Vector3(scale.x, scale.x, 1);
         return obj;
     }


The error is this: Assets/BulletBehavior.cs(11,21): error CS0309: The type T' must be convertible to UnityEngine.Component' in order to use it as parameter T' in the generic type or method UnityEngine.GameObject.AddComponent()'

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
0
Best Answer

Answer by Bunny83 · May 01, 2017 at 02:40 PM

While they dropped the generic constraint for GetComponent, AddComponent still has a constraint on the generic parameter that requires the type used to be derived from "Component". Since your generic parameter "T" has no constraints at all, one could use any type as parameter, even "int" or "string".

So the solution is to add a generic constraint to your parameter "T"

 public static GameObject readyObject<T>(T behavior, Sprite sprite, Vector2 scale) where T : Component
 {
     // [...]

ps; Your method haa a parameter of type T called "behavior", but you don't use that inside your method. It's not really required, at least for what your method currently does. Also you may have a typo in line 8 where you used scale.x twice. If it's intentionally you should use a simple float instead of a Vector2.

Comment
Add comment · 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
0

Answer by FM-Productions · May 02, 2017 at 02:50 PM

Hi @chubit,

Instead of returning a GameObject, why don't you make a script class that has all of your mentioned Components as attributes or fields? The gameObject could then simply be accessed by scriptInstance.gameObject. And maybe you could use an Interface instead of the abstract class? I don't know if it is the right way and please correct me if this is a bad approach, but I think of something like this:

 public static GameObject readyObject<T>(IBulletBehavior behavior, Sprite sprite, Vector2 scale){
          GameObject obj = new GameObject ();
          BulletScript sc = gameObject.AddComponent<BulletScript>( ) as BulletScript;
          sc.setBulletBehavior(behavior);
          //do other logic...
          return obj;
      }



Comment
Add comment · Show 2 · 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 chubit · May 02, 2017 at 09:50 PM 0
Share

Thanks for responding, but I don't think that approach to the problem would work. This is because I don't think I can use an interface based on the other code in the BulletBehavior class. Also, each Component has different properties so I can't have them as fields because there might be 100+ bullets on the screen at once.

avatar image FM-Productions · May 04, 2017 at 03:50 PM 0
Share

Hi, maybe my approach would not be the right, but just to clear a misunderstanding (if I have interpreted your comment correctly). The BulletScripts would not be in a central gameObject, each BulletScript would of course be attached to the Bullet GameObject (since the readyObject function returns the bullet), that means each bullet has only one BulletScript, you can still add other Components to the Bullet object, the BulletScript would simply be an additional component. You can have many other components attached to the bullet object, but you simply make sure that every Bullet object has a BulletScript with a defined BulletBehaviour. You also do not have to use an interface, it was a suggestion, you could use the base (abstract) class of all BulletBehaviours. Since every derived class is also treated like the super class, you can pass the specific implementation of a base class BaseBehaviour. The attribute in the BulletScript would of course also be of the type BaseBehaviour.

 public static GameObject readyObject(BaseBehaviour behavior, Sprite sprite, Vector2 scale){
          GameObject obj = new GameObject ();
          obj.tag = "Bullet";
          obj.AddComponent<SpriteRenderer>();
          obj.GetComponent<SpriteRenderer>().sprite = sprite;
          obj.AddComponent<BoxCollider2D> ().isTrigger = true;
          BulletScript sc = gameObject.AddComponent<BulletScript>( ) as BulletScript;
          sc.setBulletBehavior(behavior);
          obj.transform.localScale = new Vector3(scale.x, scale.x, 1);
          return obj;
      }

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

XBox Controller Angle of Fire Incorrect 0 Answers

How am I supposed to use SetTile( ) on a GameObject's position if its x and y values aren't integers? , 1 Answer

When I build the project gameObjects disappear 0 Answers

Game Object On Touch Event on Android-iPhone 2D 4 Answers

Erasing a gameobject if you have the coordinates. 3 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