Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • 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 /
  • Help Room /
avatar image
0
Question by Chubzdoomer · Oct 23, 2015 at 12:22 PM · c#collisiongameobjectsfunctionsobject-oriented-programming

(C#/OOP) Accessing one public function belonging to multiple gameObjects?

I'm facing a bit of an OOP dilemma and would greatly appreciate any help.

My current situation is this: I'm designing a horizontal SHMUP and the player's ship shoots lasers. I've given the lasers collision detection so that when they collide with anything tagged as "Enemy," the player's score is increased and both the enemy and laser are destroyed.

I've since decided to add a second enemy, and that's where I've encountered problems. Rather than copy--paste the code from the first enemy's script, I decided to muck around with OOP by creating a brand new script for the second enemy and having it inherit everything from the first one. In other words, the second enemy's script is now a child to the first enemy's.

The problem I'm having is related to both enemies sharing identical functions, namely the "getValue" function, which is a public function that returns an integer storing how much the enemy is worth when destroyed. (This is especially true since I've made the second enemy worth more than the first one.)

The laser calls the "getValue" function when it makes contact with enemies. My plan is to have the laser (or rather its script) do most of the dirty work by calling public functions belonging to other gameObjects. For example, it grabs the score from the enemy's "getValue" script, then increases the player's score by calling an "increaseScore" function belonging to the player's ship's script.

Here's an example of the laser's code in which it calls the enemy's "getValue" function:

     void OnCollisionEnter(Collision other)
     {
         if (other.gameObject.CompareTag("Enemy"))
         {
             float score;

             // Get how many points the enemy is worth
            score = other.gameObject.GetComponent<Enemy1Script>().getValue();

             // Give the player as many points as the enemy is worth
             player.GetComponent<PlayerScript>().increaseScore(score);

             // Destroy both the enemy and laser
             Destroy(other.gameObject);
             Destroy(this.gameObject);
         }
     }

My specific problem is this: How am I supposed to make the code on line 7 (score = . . .) also apply to the second enemy if I must specifically type the name of the enemy's script in GetComponent? The first enemy's script is named Enemy1Script and the second enemy's is Enemy2Script, but I can only enter one, even despite the fact that both scripts share the same "getValue" function! In other words, I want to access the "getValue" function regardless which enemy (or enemy's script) it belongs to; but I seemingly can't.

I understand that I could use a series of If--Then statements to take different actions based on the gameObject's name. For example, if its name were Enemy1, Enemy1Script's "getValue" would be accessed via GetComponent. If it were Enemy 2, then Enemy2Script's "getValue" would be accessed. But to me that seems like a long-winded way of doing it and would, at least in my opinion, almost defeat the purpose of using tags!

Is there any other way to get around this besides a series of If--Then statements like I described? Am I perhaps going about this the wrong way by having the lasers handle everything by calling public functions themselves?

Again, I would greatly appreciate any help. Thank you in advance!

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 fafase · Oct 23, 2015 at 01:43 PM

What you are after is polymorphism:

 public class Parent  : MonoBehaviour{
      public virtual MyMethod(){ print("Parent")}
 }
 public class Sub: Parent{
     public override MyMethod(){print("Child");}
 }
 
 public class Manager:MonoBehaviour{
      public Parent [] objects;
      void Start(){
          foreach(Parent p in parents){
                 p.MyMethod();
          }
     }
 }

To understand the process, create an object with Parent script and one with Sub script. Then drag both in the Parent array. Press play and enjoy.

I won't go into details since the net has all you need. Again, polymorphism.

Comment
Add comment · Show 1 · 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 Chubzdoomer · Oct 23, 2015 at 07:05 PM 0
Share

Wow, this is exactly what I was looking for! Works like a charm! I'm still trying to wrap my head around how it works, but thanks to you I now know that polymorphism is a very magical and powerful thing!

avatar image
0

Answer by Baste · Oct 23, 2015 at 02:25 PM

There's two solutions here:

  • Create a common base class named Enemy. It should be abstract (ie. can't be implemented directly). Then let your different enemies inherit from Enemy. So you'd have

    public abstract class Enemy : Monobehaviour {

       //all the behaviour you used to have in the first Enemy
    
         public abstract int getValue(); //your subclasses will have to override this
    
     }
    
    

Then when you implement the actual enemies, you let them inherit from Enemy:

 public class SmallEnemy : Enemy {
     public override int getValue() {
         return 1;
     }
 }

 public class LargeEnemy : Enemy {
     public override int getValue() {
         return 5;
     }
 }

Now when you do GetComponent, it will find either the SmallEnemy or the LargeEnemy script, and use that script's getValue to figure out the value

  • Just have the one enemy class. Expose the amount of points in the inspector. Create more enemies by creating prefabs with different sprites and different values in the points field.

This is the most "Unity" way of doing this thing, and is often a bunch easier to implement. When you do this, you should split the different behaviours of an enemy into different scripts - so you have one health script and one move/attack script on the same prefab. Then you create new enemies by mixing and matching those scripts into new enemies.

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

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.

Follow this Question

Answers Answers and Comments

34 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

Related Questions

Difference between C# Invoke and Unity Invoke 0 Answers

Properly attach to a GameObject after collision? 0 Answers

Doubt about placing items on tables 1 Answer

Unity3d OnCollisionEnter not firing 1 Answer

Advance Colision Detection 1 Answer


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