Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 /
avatar image
0
Question by xandermacleod · Jun 09, 2013 at 12:40 PM · c#functionclassaccessunknown

How can I access a function without knowing the script/class name to which it belongs?

Here is the situation. (This situation is purely hypothetical for now, I'm explaining the situation so you can tell me the best approach before I attempt to write the code).

The game isn't exactly a beat-em-up; but for the purposes of this example, you can think of it like a beat-em-up for now.

I have a hundred different character prefabs that each of which needs to have a script attached to it with some kind of "Attack" function. The function will include different code depending on which character prefab it is attached to. So for example, one character might swing a sword when the attack function is called, whereas another character might shoot a bow.

It is a multiplayer game, and so, each player picks a character in a menu screen, and afterwards battle commences. Depending on which characters were selected, a prefab of each character is instantiated and assigned to a player at the beginning of combat.

Separate to all of this I have an InputManager script that is checking what inputs have been pressed by either player and then needs to call the attack function on that player's character accordingly.

Is there an easy way to do this without having to have a massive 100-long "switch/case" statement on a single script which the InputManager attempts to access? The moment that I try to separate out the attack function so that is inside of multiple scripts/classes I get the problem of finding a way of identifying the class to which the attack function belongs (at least as far as I'm aware). Because different players can pick the same character I can't really have some static function for each of the characters different attacks (again as far as I'm aware).

My question is this; how would you go about solving this kind of issue? (I'm aware I might be thinking about it the wrong way, so any suggestions are welcome).

P.S. I will be using C#, although javascript solutions are also welcome.

Comment
Add comment · Show 1
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 xandermacleod · Jun 09, 2013 at 12:43 PM 0
Share

It would be ideal if there was a way of accessing a function on "some" script that has been assigned to a GameObject without having to specify which script it is (so long as only one script on the object has that function). But I don't know if that's possible / how to do that.

2 Replies

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

Answer by aldonaletto · Jun 09, 2013 at 02:33 PM

A good solution is to use SendMessage("Attack") - the function Attack is called by name, thus you don't have to worry about the script name. This is used in the good (but unfortunately no more available) FPS Tutorial: the function "Fire" is called via SendMessage in the weapon script, no matter which weapon is select. If you want to call a function by name in another object, just prefix SendMessage with a reference to the object:

 somePlayer.SendMessage("Attack");

If Attack is in a script attached to a child of somePlayer, use BroadcastMessage instead: this version calls the specified function in any script down in the hierarchy.

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 xandermacleod · Jun 09, 2013 at 03:17 PM 0
Share

That works perfectly! And so simple! Thanks loads.

And the Broadcast$$anonymous$$essage allows for parameters as well! Is there any cons to using either Send$$anonymous$$essage or Broadcast$$anonymous$$essage that I should be aware of?

avatar image aldonaletto · Jun 09, 2013 at 08:42 PM 0
Share

Send$$anonymous$$essage/Broadcast$$anonymous$$essage/Send$$anonymous$$essageUpwards are said to be a little slow, but this is true only when compared to direct calls. They are fast enough for most purposes, specially when called in response to user input. The FPS Tutorial used this function to fire attacks (like you want to do), and also to apply damage - objects, enemies and the player had an ApplyDamage function which was called via Send$$anonymous$$essage. There were situations in this FPS Tutorial where dozens of Send$$anonymous$$essage/Broadcast$$anonymous$$essage functions were called each frame without causing any perceptible performance drop.

avatar image
3

Answer by Nanorock · Jun 09, 2013 at 01:22 PM

This is a design issue. You should have all your script sharing the same interface.

 class MyPlayer_1_Script : MonoBehaviour , PlayerScript
 {
     public void attack(){/*You attack specific to player 1 goes here*/}
     blabla
 }
 class MyPlayer_2_Script : MonoBehaviour , PlayerScript
 {
     public void attack(){/*You attack specific to player 2 goes here*/}
     blabla
 }
 interface PlayerScript
 {
     void attack();
 }
 

etc.

In this case all you would need to grab is PlayerScript myPlayer = "your selected Player" , and input would just have to call myPlayer.attack();

Now if you'd like to directly call that just knowing the gameObject, you would use a MonoBehavior base class like so:

 class MyPlayer_1_Script : PlayerScript
 {
     public override void attack(){/*You attack specific to player 1 goes here*/}
     blabla
 }
 class MyPlayer_2_Script : PlayerScript
 {
     public override void attack(){/*You attack specific to player 2 goes here*/}
     blabla
 }
 class PlayerScript : MonoBehavior
 {
     public virtual void attack(){}
 }

You would then with your gameObject simply do:

 PlayerScript player = myGameObject.GetComponent<PlayerScript>();
 player.attack();
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 xandermacleod · Jun 09, 2013 at 01:45 PM 0
Share

thanks very much, this sounds like the right approach. I'll give em a try and post up again here if there's any issues.

avatar image xandermacleod · Jun 09, 2013 at 02:37 PM 0
Share

I'm still having a little trouble with this. Using the interface method, half the problem is the bit which says PlayerScript myPlayer = "your selected player". I currently don't have a way of Unity working out which class/script it needs to be looking at. Anyway, I think you pre-empted that with your second solution, so onto that one.

The problem I'm getting with the second solution is an error with the abstract.

Specifically:

The modifier 'abstract' is not valid for this item.


Any ideas why that could be happening?

avatar image Nanorock · Jun 09, 2013 at 06:02 PM 0
Share

I just saw that abstract is not valid for $$anonymous$$onoBehaviour class. Use virtual ins$$anonymous$$d, I edit my answer to reflect that

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

17 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

Related Questions

Can't get script to access other script/class (c#) 1 Answer

Can I access variables of scripts that inherit from abstract classes? 2 Answers

Make inspector show changes of class variable value in function? 1 Answer

How do I use a function in a class more than once? 4 Answers

Unity C# Start function without extending Mono 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