0

I'm currently writing a script to control environmental lighting of the scene. I have a drop down list and three scripts for different environmental lighting, script1, script2 and script3. In my control script, I wrote:

public class ControlScript : MonoBehaviour {

    public Dropdown dropdown;
    public script1 s1;
    public script2 s2;
    public script3 s3;

    public void change() {
        int option = dropdown.value;
        disableAll();

        switch (option){
        case 0: 
            s1.enabled = true;
            break;

        case 1:
            s2.enabled = true;
            break;

        case 2:
            s3.enabled = true;
            break;
        }

    private void disableAll() {
        s1.enabled = false;
        s2.enabled = false;
        s3.enabled = false;
    }
}

Then I attached this script to camera, set the scripts accordingly and set the change() method listens to the onValueChanged() event.

The change() method reacts correctly with the dropdown list, however, the scripts s1/s2/s3 are not enabled properly and thus performs no function. I tried to attach the s1,s2,s3 to the camera additionally, but doesn't seem to work.

Is there a way to solve this problem?

-------------------------------Edit Update------------------------------- The scripts s1, s2, s3 are just sudo codes to illustrate what I intend to do in this project. script s1 is an environmental lighting script using spherical harmonics, script s2 uses monte carlo sampling and script s3 uses median cut algorithm. The three scripts works well on their own when they are attached to the camera, however when I tried to control them using another script, after they have been disabled, even when setting them to be enabled the scripts still not function properly.

  • Without the contents of `script1`/2/3, knowing why enabling and disabling the script doesn't do what is desired is virtually impossible. Also, you should follow convention and name all of your class names with a starting capital letter, e.g. `Script1` and preferably name it something meaningful, like `LightingSetup1` – Draco18s no longer trusts SE May 11 '17 at 13:22
  • @Draco18s Thank you for your advice, however here the script is just sudocode to illustrate what I want to do. I attached the scripts to the camera object and tried with gameObject.GetComponent, however the script is still not working – dddddddaxing May 11 '17 at 13:52

2 Answers2

3

You need to make sure that:

  • The class and script names of the three scripts are Script1, Script2 and Script3, i.e.: public class Script1 : MonoBehaviour {} and Script1.cs (case sensitive, please use a capital first letter for class names).
  • That all three scripts are assigned as a component to a game object.
  • That you have properly assigned the reference to all three of them, via Inspector, in the Control Script, like this: enter image description here

And it should all work, your code in the Control Script is ok.

Edit: try to use this code in all the three scripts, and look what happens in the console when you switch from Option A to B (or C etc.) in the dropdown (code is just for Script1, edit it for 2 and 3 ofc).

using UnityEngine;

public class Script1 : MonoBehaviour {

    private void OnEnable() {
        Debug.Log("Script 1 Activated");
    }

    private void OnDisable() {
        Debug.Log("Script 1 Deactivated");
    }
}
Galandil
  • 4,169
  • 1
  • 13
  • 24
  • Thank you very much for your advice, however this is exactly what I did, and the disable works well. After I called disableAll(), then in the change() method, even I see in the editor that script0 is ticked, and Debug.log(script0.enabled) prints true, the script is still not functioning. However if I don't call disableAll(), it would function normally. – dddddddaxing May 11 '17 at 14:22
  • Can you post the code of s1, s2 and s3? What's script0 btw? – Galandil May 11 '17 at 14:25
  • s1/s2/s3 are just short names for the real scripts, and the scripts all implement long algorithms for different sampling methods. I'm not sure if it is the dropdown list that makes them not working. – dddddddaxing May 11 '17 at 14:43
  • I'll edit my answer and add some code, use it to make a quick test. – Galandil May 11 '17 at 14:50
  • Thank you very much for your help! I have tested your code and it works fine in this scenario. However I tested with my own code, the problem is that, even before selecting anything in the dropdown list, the scripts are enabled until other options are chosen. If I disable the scripts in the Start() or in the editor before playing, even enable the script later won't work at all. Do you have any suggestions for this problem? – dddddddaxing May 11 '17 at 21:44
  • Well, if with my test code in the 3 scripts everything works, then there must be something wrong in the code of at least one of your 3 scripts. Out of curiosity, are you always disabling only the script component (via `.enable = false`) or are you disabling the game objects containing the scripts (via `SetActive(false)`)? – Galandil May 13 '17 at 12:24
-1

Note: * As pointed out by @Programmer, if you're trying to use the class as a component to for a GameObject then you can't create it's instance using new yourself. As then it won't be known to Unity and it's core methods like Start,Update, OnXX won't be called. You should use new only if your solve goal is to use the Script as a normal C# class which has nothing to do with Unity.

You can't provide script itself as the value for the variables. Variables shown in the Inspector window expect objects. In case of scripts it's easy as you can just call their constructor to instantiate the instances like below

/* don't use `new` if scripts are inherited from MonoBehavior or are intended
 * to be managed by Unity. Instead use someGameObject.AddComponent<script1>
 * This will have to be done where script instance is created. 
 * This instance can be accessed by using the method provided in the second
 * part of this answer.
 */
s1 = new script1();
s2 = new script2();
s3 = new script3();

However if you're trying to share .enabled field between classes then you will have to find a way to share these instances. One way is to attach them on an empty object, lets call it OptionManager and attach all the scripts to it. Now you will have to provide an instance of OptionManager to the ControlScript by exposing a public field of it. After that you can get s1, s2, s3 in it's components, see the example below

public class ControlScript : MonoBehaviour {
    public ScriptManager scriptManager;
    public Dropdown dropdown;

    private script1 s1;
    private script2 s2;
    private script3 s3;

    void Start() {
        s1 = scriptmanager.GetComponent<script1>();
        s2 = scriptmanager.GetComponent<script2>();
        s3 = scriptmanager.GetComponent<script3>();
    }
    //.... rest of the code
11thdimension
  • 10,333
  • 4
  • 33
  • 71
  • Thank you very much for your answer! I tried a similar way by attaching the scripts to the camera object in the editor, then call GetComponent to enable/disable the script, but although it is shown as active, the script is still not functioning. – dddddddaxing May 11 '17 at 13:53
  • 1
    You're wrong: in the Inspector you can give a reference to ANY type (`GameObject`, `Transform`, a class inheriting from `MonoBehaviour`, etc.). Moreover, you can't create new instances of a `MonoBehaviour` subclass with the `new` keyword. – Galandil May 11 '17 at 14:09
  • `s1 = new script1();` should be `s1 = gameObject.AddComponent();.` See [here](http://stackoverflow.com/a/37399263/3785314) for more information. – Programmer May 11 '17 at 17:32
  • @Galandil No it wont work. A `Script` is not an instance in itself (it's a class, text if you will). We need to either create an instance ourselves or attach the script as a component to another object, then only we can assign it to a field in an objects component. Script itself can not be dragged on to the field in the inspector. – 11thdimension May 12 '17 at 03:19
  • @Programmer I have only used Unity since version 5, and it seems to be working in there with only the `warning` (same from your reference). I don't know which version you're referring to. Here's a link to the test project for the same https://github.com/ConsciousObserver/TestScriptRefInInspector – 11thdimension May 12 '17 at 03:26
  • Your answer is misleading and incorrect. I made my first comment so that you will correct it. The `script1` script inherits from `MonoBehaviour`. You shouldn't be creating instance of scripts that inherit from `MonoBehaviour` with the `new` keyword. Read the link I provided for ways to create a new instance. – Programmer May 12 '17 at 03:53
  • I agree that `MonoBehavior` instance should not be created by using `new`, however it's not an exception as mentioned in the link you have provided. It's just a warning, if it was an exception before version 5, then may be Unity decided to make it a warning only. As Unity makes every Script inherit from `MonoBehavior` by default, whether intention was that or not. I'm treating Script1 as a simple class, which is not intended to be used as a `Component` as it doesn't have any of the MonoBehavior methods. – 11thdimension May 12 '17 at 04:12
  • 1
    Script1 is not a simple class. It is a class with `MonoBehavior` because OPS used the `enabled` variable which can only be found on `MonoBehavior`. The main reason of inheriting `MonoBehaviour` is so that you can attach your script to your GameObject and I am sure that's what OP is doing. If you use the `new` keyword, you won't be able to do this. The Awake,Start and Update functions won't be called. You can't enable/disable the script. Already, two people have tried to correct you but failed. – Programmer May 12 '17 at 04:36
  • Ok, now I see that, `enabled` is from `Behavior`, and he is trying to probably activate/deactivate objects in the screen. It's given that if instance is created manually then Unity won't have anything to do with it. I only dealt with the part where OP is trying to drag the script on the public field of another script. I will edit the answer to include that, – 11thdimension May 12 '17 at 08:07