首页 文章

如何在Unity3d中运行时在GameObject上加载脚本,材质?

提问于
浏览
0

我是Unity3d和JS脚本的新手,我需要帮助来简化我正在开发的应用程序中的场景和代码这是我的场景的概念:

有一个相机,通过层屏蔽看到三个平面 . 还有一种材料用作交换纹理,以及在每个平面上分别运行此交换的脚本 . 为了运行这个脚本,我使用带有滚动列表按钮的GUI,所以当按下button1时,摄像头只能看到plane1,而script1会在这个平面上运行纹理材质1 . 按下相应的按钮,在其他2个平面上也会发生相同的情况 . 您可以在附图1中查看此概念:

enter image description here

我需要你的帮助,是通过只保留一个相机的平面来简化这个场景,并附加相应的脚本(1,2,3等),材料作为纹理(1,2,3等)当玩家在运行时触摸相应的GUI按钮时,同一平面 . 需要提一下的是,GUI按钮位于附加到空GameObject的名为“GUI”的脚本上,而我需要动态附加的脚本和材料位于名为“Animator”的GameObject上,作为Camera的子项 . 您可以在附图2中查看此概念 .

enter image description here

我相信这个功能可以通过使用例如“gameObject.AddComponent(”myScript“)”,但由于我是一个菜鸟,我无法实现它 . 此外,我不知道如何在运行时在这个平面上应用不同的材料 . 所以我需要一些帮助和一个编码示例,因为我发现很难只看到提示而没有看到一个例子 .

感谢大家抽出时间阅读这篇文章,希望有人能够帮助我解决这个问题 .

Edit 1

好吧,为了让任何愿意帮助的人更加全面,并且随后我的答案得到了帮助,我发布了Hierarchy和Inspector的截图,以及Unity项目的代码片段 .

在图3中,Hierarchy的视图,我显示,脚本“ShowAnimation”在gameObject“Animation_Buttons_Controller”上 . 通过这个脚本,我想访问例如父对象游戏对象“AnimationCamera”中的gameObject子“Animator2inScene2” .

enter image description here

在图像4中,Inspector的视图,我显示了材质元素“Texture_Animator2_Material”,以及应该仅在运行时添加到此gameObject上的脚本“ScriptTextureAnimator2” .

enter image description here

以下是脚本“ShowAnimation.js”中的代码片段,它必须访问gameObject子元素“Animator2inScene2”并在此gameObject子元素上添加材质元素“Texture_Animator2_Material”和脚本“ScriptTextureAnimator2”:

if (GUI.Button (Rect (2,2,100,20), "PlayAnimation2")) 
            {
            var addScriptOnPlane2 : GameObject[] = GameObject.FindGameObjectsWithTag("Animator");     
            //for(var addTextureScript2 : GameObject in addScriptOnPlane2)

if(addScriptOnPlane2)
            { 

            // Adds the script named ScriptTextureAnimator2 to the game object child "Animator2inScene2"
            gameObject.AddComponent("ScriptTextureAnimator2");

            // Adds the script named Texture_Animator2_Material to the game object child "Animator2inScene2"
            var addMaterial : Material;

            addMaterial = Resources.Load("Materials/Materials/Texture_Animator2_Material",typeof(Material)) as Material;

}
}

问题是在游戏中,我没有gui按钮上的功能和控制台中的以下错误:

“NullReferenceException:对象引用未设置为对象的实例ScriptTextureAnimator2.FixedUpdate()”

我知道,我错过了一些对于编译至关重要的东西,但那可能是什么呢?请查看我的编码推荐 . 谢谢 .

2 回答

  • 1

    我真的很感谢你用这个问题制作图片,从而使阅读更加愉快:)

    要在运行时更改脚本,您需要销毁旧脚本并添加新脚本:

    Destroy the old script:

    Destroy(plane.GetComponent(TestScript)); // get component of type TestScript
    

    Add the new script:

    plane.AddComponent(TestScript); // add component of type TestScript
    

    要在运行时更改材料:

    准备材料的全局变量,并使用检查器中的材料进行分配:

    var material1 : Material;
    var material2 : Material;
    var material3 : Material;
    

    然后您可以将材料更改为您选择的材料,如下所示:

    plane.renderer.material = material1; // change plane material to material1

    看到您的示例,这些脚本将放在GUI Button中 .
    因此,您需要在GUI按钮脚本中创建公共游戏对象变量,以便您可以将平面分配给它 .
    请注意,在上面的代码中,我总是将 plane 写为基类,这就是我在GUI按钮中对公共游戏对象的意义 .

    只需声明 plane 游戏对象变量,如下所示:

    var plane : GameObject;
    

    并在检查员处为其指定平面物体 .

    希望这可以帮助!

    EDIT 1:
    该错误可能是由于错误放置了代码段引起的 .
    你有没有把你的功能放到 OnGUI()
    我修改了您的代码以满足您的需求:

    function OnGUI () {
        if (GUI.Button (Rect (2,2,100,20), "PlayAnimation2")){
            var addScriptOnPlane2 : GameObject[] = GameObject.FindGameObjectsWithTag("Animator");     
    
            for(var addTextureScript2 : GameObject in addScriptOnPlane2)
            { 
                // Adds the script named ScriptTextureAnimator2 to the game object child "Animator2inScene2"
                addTextureScript2.AddComponent("ScriptTextureAnimator2");
    
                // Adds the script named Texture_Animator2_Material to the game object child "Animator2inScene2"
                var addMaterial : Material;
    
                addMaterial = GameObject.Instantiate(Resources.Load("Materials/Materials/Texture_Animator2_Material",typeof(Material))) as Material;
    
                addTextureScript2.renderer.material = addMaterial;
            }
        }
    }
    

    请注意,要将脚本和材质添加到所需的游戏对象,如果要从其他游戏对象中执行此操作,则必须指定该游戏对象的变量 .

    gameObject.AddComponent("ScriptTextureAnimator2"); 
    // gameObject = this.gameObject = Animation_Buttons_Controller gameobject
    // change it to addTextureScript2.AddComponent("ScriptTextureAnimator2");
    

    我还指定了之前没有做过的材料 .
    请注意 Resources.Load 将在 Assets 中搜索目录 Resources ,因此请确保将材料放在那里 .

  • 0

    Adding scripts.

    TestScript newScript = gameObject.AddComponent<TestScript>();
    

    最新版本的Unity允许在同一游戏对象上使用脚本的多个实例 .

    Adding materials.

    在项目中创建“Resources”文件夹,并在此文件夹中创建一个新材料“TestMaterial” . 您可以使用Resources例程在运行时加载此材料:

    Material testMaterial = Resources.Load( 
       "TestMaterial", 
       typeof(Material) 
    ) as Material;
    

    您可以将子文件夹“Materials”添加到“Resources”中,并将TestMaterian放入此子文件夹:

    Material testMaterial = Resources.Load( 
       "Materials/TestMaterial", 
       typeof(Material) 
    ) as Material;
    

    请注意这一点装载的材料是 shared material . 即如果在运行时更改它,更改将保存在项目中 . 您仍然可以将此材质放在任何渲染器上,但您必须使用sharedMaterial属性:

    this.renderer.sharedMaterial = testMaterial;
    

    如果要避免在运行时更改共享材料,则必须创建实例:

    Material testMaterialInstance = GameObject.Instantiate( Resources.Load(
       "Materials/TestMaterial", 
       typeof(Material) 
    ) as Material ) as Material;
    

    现在您可以安全地更改此材质,并且可以使用材质属性放置到渲染器:

    this.renderer.material = testMaterialInstance ;

相关问题