Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Using monobehaviour variable to allow one script to control multiple.

Discussion in 'Scripting' started by JamesL98, Mar 29, 2019.

  1. JamesL98

    JamesL98

    Joined:
    Oct 9, 2014
    Posts:
    50
    Hello fellow unity people, so the title is super unclear and I'll try and explain what I'm trying to do the best I can.
    So I have a script that sends a raycast out to observe objects in the scene, if I've set an object in the scene to be able to be observed it will display the name of that object on screen through UI text, as an example looking at a table will say "Table" but looking at something not important such as terrain will not say anything.

    So the problem begins when some of these objects but not all are interactable an example is a door should be interactable but a rock isnt. So I have the script for observing and I have a script for if the object is interactable, now some objects will be able to be picked up whilst others like doors will have another trigger for animation or cutscene.

    I want to know if there is a way I can use a monobehaviour as a variable so I can manually assign either a door script or a pickup object script and when ready the player can press a key and it will do something like myMonoBehaviour.Begin(); which would call on whatever script I've assigned to save making a ton of if statements.

    I tried just using:
    Code (CSharp):
    1. public MonoBehaviour scriptToCall;
    2.  
    3. scriptToCall.doSomething();
    and i know i could do something like this:

    Code (CSharp):
    1. public DoorScript myDoor;
    2. public bool isDoor;
    3. if(isDoor)
    4. { myDoor.dosomething();}
    5.  
    6. else if(isPickup)
    7. {myPickup.dosomething();}
    8.  
    But I don't want to use individual references like that;
    Because I may eventually have so many different interactables as it's one of the main game mechanics.

    Is this even possible to do and if I was unclear just let me know I'll try and rephrase it. If someone canchelp me out or give an idea that would save a lot of headaches from using 100000 if statements. Thanks in advance

    EDIT: because i feel like im confusing myself with my own post haha, kind of like how UI buttons allow you to select a script and then call a function but i want to be able to drag one of many scripts in and call the same function on whatever script im using then the script can handle what it does on its own.
     
    Last edited: Mar 29, 2019
  2. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    You can make an interactable class with your common methods and then inherit from that class for each type of object, like so;

    Code (CSharp):
    1. public abstract class Interactable : MonoBehaviour
    2. {
    3.     public abstract void OnInteract();
    4. }
    5.  
    6. public class Rock : Interactable
    7. {
    8.     public override void OnInteract()
    9.     {
    10.        //Do Nothing
    11.     }
    12. }
    13.  
    14. public class Door : Interactable
    15. {
    16.     public override void OnInteract()
    17.     {
    18.         //Code to open door
    19.     }
    20. }
    or you can implement an interface

    Code (CSharp):
    1. public interface Interactable
    2. {
    3.     void OnInteract();
    4. }
    5.  
    6. public class Rock : MonoBehaviour, Interactable
    7. {
    8.     public void OnInteract()
    9.     {
    10.        //Do Nothing
    11.     }
    12. }
    13.  
    14. public class Door : MonoBehaviour, Interactable
    15. {
    16.     public void OnInteract()
    17.     {
    18.         //Code to open door
    19.     }
    20. }
    Then you can search for the class or interface. You could do the same for your observer class.
     
  3. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I might just add a script called something like InteractableObject with standard methods for interacting, which just call delegates to other scripts on the object for the actual code to run. Then you just need to know whether the InteractableObject component is on the object or not to tell if it can be interacted with.
     
  4. Jujo100

    Jujo100

    Joined:
    Jan 20, 2013
    Posts:
    14
    Hi,

    I'm not sure what you mean by using a Monobehaviour as a variable.

    I'm guessing you want to be able to look at an object in the world and be able to call a script on that object like Interact() no matter what the object is.

    You may want to look into c# interfaces for this. On your interactable object you would implement an interface. Something like IInteractable which contains an Interact() method, then from the ray cast script you could could use hitInfo.collider.GetComponent<IInteractable>().Interact();

    You can check for null on the GetComponent return in case you have an object that does not implement IInteractable.
    Each object has it's own code within it's Interact method. So a door might open or a button might be pressed etc..

    Hopefully this is the sort of thing you're after.

    Good luck!!
     
  5. JamesL98

    JamesL98

    Joined:
    Oct 9, 2014
    Posts:
    50
    The interface looks like a path I might go down, for now I've just used the send message function to get it working in the mean time. Thankyou everyone for your help im self taught in c# so I lack a but of basic tools.