Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Dynamic type for accessing "script objects/components..."

Discussion in 'Scripting' started by bloomingdedalus, Dec 24, 2013.

  1. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    Previously I've been using direct casting to communicate between scripts. For example, Script A wants to talk to Script B and the following code will be in Script A:

    Code (csharp):
    1. public class ScriptA : MonoBehavior
    2. {
    3.     private ScriptB scr_ScriptB = ScriptBGameObject.GetComponent("ScriptB");
    4.         void Update()
    5.         {
    6.             scr_ScriptB.DoStuff();
    7.         }
    8. }
    However, I am working on a link library and I would like to pass "script references" of the kind declared in the above script. Is there a generic type that can be used as a substitute if I want it to be able to handle multiple kinds of "script objects?" Or is it simply a bad idea to pass a monobehavior derived class object to a dll? If this isn't possible, I know of a few workarounds, but I'd just feel more comfortable with the algorithm if I can actually pass a script object to the dll regardless.

    e.g.

    Code (csharp):
    1. public class ScriptA : MonoBehavior
    2. {
    3.     private string ScriptName = "ScriptB";
    4.     private GENERIC_TYPE_HERE scr_ScriptB = ScriptBGameObject.GetComponent(ScriptName);
    5.         void Update()
    6.         {
    7.             scr_ScriptB.DoStuff();
    8.         }
    9. }
     
    Last edited: Dec 24, 2013
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Well... In your example, you're not passing anything to anyone. Would you mind rewording what you mean?

    Are you trying to invoke a method of an unknown type?
     
  3. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    I'm trying to use a variable that will be a monobehavior script reference. e.g. an instance of "ScriptB" - however - because "ScriptB" is a class object, it has to be explicitly cast as "ScriptB" in the declaration. The point is that I would be able to dynamically set the string "ScriptName" in the second code example and it would still work provided whatever MonoBehavior class I pass to it has a method called "DoStuff()".

    I didn't pass anything in the pseudocode above. I'll write something more explicit here using a full code example from both scripts and put in all caps what I lack the knowledge to implement - I'm just trying to figure out how to leave out the "UNKNOWN_TYPE_HERE" typecast and use something generic that will work regardless the name of "ScriptB":

    Code (csharp):
    1. public class ScriptB : Monobehaviour
    2. {
    3.     private ScriptA MyManagerScript = FindObjectWithTag("ScriptA").GetComponent("ScriptA");
    4.  
    5.     void Start()
    6.     {
    7.         MyManagerScript.SetScriptName("ScriptB");
    8.         MyManagerScript.SetGameObjectReference(gameObject);
    9.     }
    10.  
    11.     public void DoStuff()
    12.     { ... }
    13. }
    14.  
    15. ----------------------------------------------------------------------
    16.  
    17. public class ScriptA : Monobehaviour
    18. {
    19.     private string ScriptName;
    20.     private UNKNOWN_TYPE_HERE ScriptReference;
    21.     private GameObject ScriptGameObject;
    22.  
    23.     void Update()
    24.     {
    25.         if (ScriptGameObject)
    26.         {
    27.              ScriptReference = ScriptGameObject.GetComponent(ScriptName);
    28.              ScriptReference.DoStuff();
    29.         }
    30.  
    31.        
    32.     }
    33.  
    34.     public void SetScriptName(string temp)
    35.     {
    36.         ScriptName = temp;
    37.     }
    38.  
    39.     public void SetGameObjectReference(GameObject temp)
    40.     {
    41.          ScriptGameObject = temp;
    42.     }
    43.  
    44. }
    45.  
     
    Last edited: Dec 24, 2013
  4. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Now... Why would you want that? Usually, invoking method like that is a bad idea and is signs of a poor code design.

    You CAN invoke method by signature assumption using the dynamic keyword (http://msdn.microsoft.com/en-us/library/dd264741.aspx) which is basically a typeless, runtime resolved container. Usually, it's used in COM object communication or in external doc (XML) invokation.

    Frankly, I would stay away from dynamic. It's way too easy to mess something with it.

    Another way, is to explicitly declare a method signature using an interface. If you never used interface, you should learn about them. They are powerful and very important part of the polymorphism pattern in C#. (http://msdn.microsoft.com/en-us/library/ms173156.aspx)

    Code (csharp):
    1.  
    2. public interface IDoStuff
    3. {
    4.     void DoStuff();
    5. }
    6.  
    7. public class MyClassA : MonoBehaviour, IDoStuff
    8. {
    9.     public void DoStuff() { // Do something in there }
    10. }
    11.  
    12. public class MyClassB : MonoBehaviour, IDoStuff
    13. {
    14.     public void DoStuff() { // Do something in there }
    15. }
    16.  
    And interface can be cast into, such as;

    Code (csharp):
    1.  
    2. private IDoStuff instance;
    3.  
    4. public void GetInstance(IDoStuff instance)
    5. {
    6.     this.instance = instance;
    7. }
    8.  
    9. public void MakeItDoStuff()
    10. {
    11.     instance.DoStuff();
    12. }
    13.  
     
  5. BrUnO-XaVIeR

    BrUnO-XaVIeR

    Joined:
    Dec 6, 2010
    Posts:
    1,687
    In Unity, behaviour classes are always the same of the script name.
    If you know its name you know its type.