Search Unity

Calling method from one C# script in another C# script

Discussion in 'Getting Started' started by jshrek, Feb 27, 2015.

  1. jshrek

    jshrek

    Joined:
    Mar 30, 2013
    Posts:
    220
    Okay I have completed the roll-a-ball and space shooter tutorials but am still a newbie and trying to figure this stuff out... I have read a whole bunch of different stuff on how to call a method from one script in another script but cannot seem to get it to work.

    One of the scripts is just a script all by itself and is not attached to any kind of object, so maybe this is my problem because all the examples I see assume both scripts are attached to some kind of object and are calling some kind of get/find component.

    Anyways I am very confused and nothing I try is working. Any help is appreciated.

    Here are a couple sample scripts that I cannot get work:

    Code (CSharp):
    1. usingUnityEngine;
    2. usingSystem.Collections;
    3.  
    4. public class GameController : MonoBehaviour {
    5.  
    6.     //This script is attached to a game object called GameController
    7.  
    8.     public MyScript ms;
    9.  
    10.     void Start() {
    11.  
    12.         ms.MyMethod(); //this does NOT work :(
    13.  
    14.     }
    15.  
    16. }
    17.  
    18.  
    19. usingUnityEngine;
    20. usingSystem.Collections;
    21.  
    22. public class MyScript : MonoBehaviour {
    23.  
    24.     //This script is NOT attached to any objects at all
    25.  
    26.     void MyMethod() {
    27.  
    28.         Debug.Log ("MyScript > MyMethod");
    29.  
    30.     }
    31.  
    32. }
    33.  
     
  2. Gametyme

    Gametyme

    Joined:
    May 7, 2014
    Posts:
    557
    In unity every script must be attached to an object to work.
     
  3. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,486
    Not true. Unity requires an attached MonoBehaviour to start the game, but in theory once you have started you could run an entire game without a script attached to a GameObject. This is an extreme example, but most projects have scripts with no associated GameObject.

    Where the OP is getting in trouble is with getting an instance of the MyScript class. There are multiple ways to do this. I'll describe two.

    If MyScript is to be attached to a GameObject, then simply attach it and drag it in in the inspector to get a reference.

    If MyScript is not intended to be attached to a GameObject then MyScript cannot inherit from MonoBehaviour, and you must create an instance using the new keyword. As follows.

    Code (CSharp):
    1. usingUnityEngine;
    2. usingSystem.Collections;
    3. public class GameController : MonoBehaviour {
    4.     //This script is attached to a game object called GameController
    5.     public MyScript ms;
    6.     void Start() {
    7.         ms = new MyScript();
    8.         ms.MyMethod();
    9.     }
    10. }
    11. usingUnityEngine;
    12. usingSystem.Collections;
    13. public class MyScript  {
    14.     //This script is NOT attached to any objects at all
    15.     void MyMethod() {
    16.         Debug.Log ("MyScript > MyMethod");
    17.     }
    18. }
    19.  
     
    jenful, kunalxigxag and Ryiah like this.
  4. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    14,540
    Scripts do not need to be attached to a GameObject to work. The reason it isn't working is actually very simple but is caused by two problems.

    First, a script that is not attached to a GameObject cannot inherit from MonoBehaviour. This is essentially because MonoBehaviour is how Unity communicates between a script and a GameObject. Inheriting from MonoBehaviour is only useful when the script is attached to one.

    Second, if the function is not static then you have to instantiate the class it is part of. Additionally the functions need to be public or they will not be accessible outside of the class. This is part of how the language itself works.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. public class GameController : MonoBehaviour {
    5.    //This script is attached to a game object called GameController
    6.     public MyScript ms;
    7.     void Start() {
    8.         // simply call the method if it is static without instantiating
    9.         ms.MyMethodStatic();
    10.  
    11.         // instantiate a copy of the script class and call the non-static method
    12.         ms = new MyScript();
    13.         ms.MyMethod();
    14.     }
    15. }
    16.  
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MyScript {
    6.     //This script is NOT attached to any objects at all
    7.     public void MyMethod() {
    8.         Debug.Log ("MyScript > MyMethod");
    9.     }
    10.  
    11.     public static void MyMethodStatic() {
    12.         Debug.Log ("MyScript > MyMethodStatic");
    13.     }
    14. }
    15.  
     
    Last edited: Feb 28, 2015
  5. jshrek

    jshrek

    Joined:
    Mar 30, 2013
    Posts:
    220
    Awesome guys!! I knew it was probably pretty simple and I was just missing something easy!!
     
  6. jshrek

    jshrek

    Joined:
    Mar 30, 2013
    Posts:
    220
    Okay so this works for methods, but what about public variables in the script?

    So if I declare public bool MyBool; in MyScript, I cannot acces it with ms.MyBool like I can the method.

    See line 11 below ...

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class GameController : MonoBehaviour {
    4.     //This script is attached to a game object called GameController
    5.     public bool SomeBool;
    6.     public MyScript ms;
    7.     void Start() {
    8.         ms = new MyScript();
    9.         ms.MyMethod();
    10.  
    11.         SomeBool = ms.MyBool; //this does not work :(
    12.  
    13.     }
    14. }
    15.  
    16. using UnityEngine;
    17. using System.Collections;
    18. public bool MyBool;
    19.  
    20. public class MyScript  {
    21.     //This script is NOT attached to any objects at all
    22.     void MyMethod() {
    23.         Debug.Log ("MyScript > MyMethod");
    24.         Debug.Log ("MyBool=" + MyBool);
    25.  
    26.     }
    27. }
    28.  
    Thanks for help. I know this may be basic for some of you but when I learned Objective-C, this was the hardest thing to figure out as well!
     
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,486
    MyBool needs to be inside the class brackets!

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MyScript  {
    5.     public bool MyBool;
    6.  
    7.     //This script is NOT attached to any objects at all
    8.     void MyMethod() {
    9.         Debug.Log ("MyScript > MyMethod");
    10.         Debug.Log ("MyBool=" + MyBool);
    11.  
    12.     }
    13. }
    14.  
     
  8. jshrek

    jshrek

    Joined:
    Mar 30, 2013
    Posts:
    220
    Ah yes, the good old typo!!!

    Yep it is working now.

    Thanks for help!
     
    Last edited: Feb 28, 2015
  9. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,486
    Can you describe what is not working? Is it a compiler error, or just not working as you'd expect it.

    Its worth noting that bools are a value type. So SomeBool will not change if MyBool changes. Value types and reference types can cause headaches while you are learning.
     
  10. jshrek

    jshrek

    Joined:
    Mar 30, 2013
    Posts:
    220
    I edited my post above ... it did not seem to work at first but them it started working fine. So not sure exactly what I did or did not do, but it works fine as you posted.

    Thanks
     
  11. Gametyme

    Gametyme

    Joined:
    May 7, 2014
    Posts:
    557
    Thanks for the info. I have seen a few tuts on utube that stated that all scripts new to be attached to an object in unity.
     
  12. jshrek

    jshrek

    Joined:
    Mar 30, 2013
    Posts:
    220
    Okay so for my future information (aka: makes it easy for me to find in the future when I forget how to do this) here is a quick SUMMARY for calling methods in both a script that IS attached to an object and a script that is NOT attached to an object. It also deals with variables as well.

    This example assumes the following:
    - You have a script in the project folder that is NOT attached to any object called TestScriptNoObject.
    - You have some Game Object in the hierarchy called TestGameObject with a script attached called TestGameObjectScript.
    - You have some Game Object in the hierarchy called MainController with a script attached called MainControllerScript. You want to set a var and call a method in both TestScriptNoObject and TestGameObjectScript.

    Code (CSharp):
    1. //MainControllerScript.cs
    2. //NOTE: This script is attached to a GameObject in the hierarchy called MainController.
    3. using UnityEngine;
    4. using System.Collections;
    5. public class MainControllerScript : MonoBehaviour {
    6.  
    7.   public TestScriptNoObject testNoObject = new TestScriptNoObject();
    8.   public TestGameObjectScript testWithObject;
    9.  
    10.   void Start () {
    11.  
    12.     //call to TestScriptNoObject which is not attached to any objects //
    13.     testNoObject.testScriptNoObjectVar = true;
    14.     testNoObject.TestScriptNoObjectMethod ();
    15.  
    16.     //call to TestGameObjectScript which IS attached to the object TestGameObject //
    17.     testWithObject = GameObject.Find("TestGameObject").GetComponent<TestGameObjectScript>(); //NOTE: Make sure TestGameObject is a unique name in the hierarchy and that no other objects have same name.
    18.     testWithObject.testGameObjectVar = true;
    19.     testWithObject.TestGameObjectMethod ();
    20.  
    21.   }
    22. }
    23.  
    Code (CSharp):
    1. //TestGameObjectScript.cs
    2. //NOTE: This script is attached to a GameObject in the hierarchy called TestGameObject.
    3. using UnityEngine;
    4. using System.Collections;
    5. public class TestGameObjectScript : MonoBehaviour {
    6.  
    7.   public bool testGameObjectVar = false;
    8.  
    9.   public void TestGameObjectMethod() {
    10.     Debug.Log ("TestGameObject > TestGameObjectScript > TestGameObejctMethod > testGameObjectVar: " + testGameObjectVar);
    11.   }
    12. }
    13.  
    Code (CSharp):
    1. //TestScriptNoObject.cs
    2. //NOTE: This script is NOT attached to any GameObject.
    3. using UnityEngine;
    4. using System.Collections;
    5. public class TestScriptNoObject { //Notice MonoBehaviour has been removed from class.
    6.  
    7.   public bool testScriptNoObjectVar = false;
    8.  
    9.   public void TestScriptNoObjectMethod() {
    10.     Debug.Log ("TestScriptNoObject > TestScriptNoObjectMethod > testScriptNoObjectVar: " + testScriptNoObjectVar);
    11.   }
    12. }
    13.  
     
    Last edited: Feb 28, 2015
    clausarberg likes this.