【问题标题】:Unity attach script to another script not workingUnity将脚本附加到另一个脚本不起作用
【发布时间】:2017-05-12 16:17:41
【问题描述】:

我目前正在编写一个脚本来控制场景的环境照明。我有一个下拉列表和三个用于不同环境照明的脚本,script1、script2 和 script3。在我的控制脚本中,我写道:

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;
    }
}

然后我将此脚本附加到相机,相应地设置脚本并设置 change() 方法侦听 onValueChanged() 事件。

change() 方法可以正确响应下拉列表,但是脚本 s1/s2/s3 未正确启用,因此无法执行任何功能。我尝试将 s1,s2,s3 附加到相机上,但似乎不起作用。

有没有办法解决这个问题?

-------------------编辑更新-------------- ----------------- 脚本 s1、s2、s3 只是 sudo 代码,用于说明我打算在这个项目中做什么。脚本 s1 是使用球谐函数的环境照明脚本,脚本 s2 使用蒙特卡罗采样,脚本 s3 使用中值切割算法。这三个脚本在连接到相机时单独运行良好,但是当我尝试使用另一个脚本控制它们时,在它们被禁用后,即使将它们设置为启用,脚本仍然无法正常运行。

【问题讨论】:

  • 如果没有script1/2/3 的内容,要知道为什么启用和禁用脚本不能达到预期效果几乎是不可能的。此外,您应该遵循约定并以大写字母开头的所有类名命名,例如Script1 并最好将其命名为有意义的名称,例如 LightingSetup1
  • @Draco18s 感谢您的建议,但是这里的脚本只是 sudocode 来说明我想要做什么。我将脚本附加到相机对象并尝试使用 gameObject.GetComponent,但脚本仍然无法正常工作

标签: c# unity3d unity5


【解决方案1】:

您需要确保:

  • 三个脚本的类名和脚本名分别为Script1Script2Script3,即:public class Script1 : MonoBehaviour {}Script1.cs(区分大小写,类名请使用大写首字母)。
  • 所有三个脚本都作为一个组件分配给游戏对象。
  • 您已通过 Inspector 在Control Script 中正确分配了对所有三个的引用,如下所示:

一切正常,控制脚本中的代码没问题。

编辑:尝试在所有三个脚本中使用此代码,并查看当您在下拉菜单中从选项 A 切换到 B(或 C 等)时控制台中会发生什么(代码仅适用于 Script1,编辑它适用于 2 和 3 ofc)。

using UnityEngine;

public class Script1 : MonoBehaviour {

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

    private void OnDisable() {
        Debug.Log("Script 1 Deactivated");
    }
}

【讨论】:

  • 非常感谢您的建议,但这正是我所做的,并且禁用效果很好。在我调用 disableAll() 之后,在 change() 方法中,即使我在编辑器中看到 script0 被勾选,并且 Debug.log(script0.enabled) 打印为 true,脚本仍然无法运行。但是,如果我不调用 disableAll(),它会正常运行。
  • 能发一下s1、s2、s3的代码吗?顺便说一句,script0 是什么?
  • s1/s2/s3 只是真实脚本的简称,脚本都针对不同的采样方法实现了长算法。我不确定是否是下拉列表使它们无法正常工作。
  • 我将编辑我的答案并添加一些代码,用它来进行快速测试。
  • 非常感谢您的帮助!我已经测试了您的代码,它在这种情况下运行良好。但是我用自己的代码进行了测试,问题是,即使在选择下拉列表中的任何内容之前,脚本也会被启用,直到选择其他选项。如果我在播放前禁用 Start() 或编辑器中的脚本,即使稍后启用脚本也根本不起作用。您对这个问题有什么建议吗?
【解决方案2】:

注意: * 正如@Programmer 所指出的,如果您尝试将类用作GameObject 的组件,那么您无法使用new 创建它的实例你自己。这样Unity 就不会知道它,并且不会调用像Start,Update, OnXX 这样的核心方法。仅当您的解决目标是将脚本用作与 Unity 无关的普通 C# 类时,您才应使用 new

您不能提供脚本本身作为变量的值。 Inspector 窗口中显示的变量需要对象。如果是脚本,这很容易,因为您可以调用它们的构造函数来实例化如下所示的实例

/* 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();

但是,如果您尝试在类之间共享 .enabled 字段,那么您必须找到一种方法来共享这些实例。一种方法是将它们附加到一个空对象上,我们称之为OptionManager 并将所有脚本附加到它。现在,您必须通过公开其公共字段来向ControlScript 提供OptionManager 的实例。之后,您可以在其组件中获取s1, s2, s3,请参见下面的示例

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

【讨论】:

  • 非常感谢您的回答!我尝试了类似的方法,将脚本附加到编辑器中的相机对象,然后调用 GetComponent 来启用/禁用脚本,但尽管它显示为活动,但脚本仍然无法运行。
  • 你错了:在 Inspector 中,你可以引用任何类型(GameObjectTransform、继承自 MonoBehaviour 的类等)。此外,您不能使用 new 关键字创建 MonoBehaviour 子类的新实例。
  • s1 = new script1(); 应该是 s1 = gameObject.AddComponent&lt;script1&gt;();. 有关详细信息,请参阅 here
  • @Galandil 不,它不会工作。 Script 本身并不是一个实例(它是一个类,如果你愿意,可以是文本)。我们需要自己创建一个实例或将脚本作为组件附加到另一个对象,然后只有我们可以将它分配给对象组件中的字段。脚本本身不能拖到检查器中的字段上。
  • Script1 不是一个简单的类。这是一个带有MonoBehavior 的类,因为OPS 使用了只能在MonoBehavior 上找到的enabled 变量。继承MonoBehaviour 的主要原因是您可以将脚本附加到您的游戏对象,我相信这就是 OP 正在做的事情。如果您使用new 关键字,您将无法执行此操作。不会调用 Awake、Start 和 Update 函数。您无法启用/禁用脚本。已经有两个人试图纠正你但失败了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
  • 2015-11-03
  • 2018-05-11
  • 1970-01-01
相关资源
最近更新 更多