如何在Unity中在运行时更改对象的层?

13

我有一个在Unity中放置墙壁的WallCreator脚本,还有另一个WallCreatorSwitcher脚本,通过检查开关来打开/关闭WallCreator。 我还想使用GetComponent<WallCreator>().wallPrefab.layer = LayerMask.NameToLayer("LayerName");在那里更改wallPrefab的图层,因此当选中开关时(WallCreator ON),图层为"Ignore Raycast" - 它可以正常工作,如果取消选中开关(WallCreator OFF),则图层为"Default" - 但问题是,在这种情况下它没有更改图层。

public class WallCreatorSwitcher : MonoBehaviour {

public Toggle toggle;
public Text text;


// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
    if (toggle.isOn)
    {
        GetComponent<WallCreator>().enabled = true;
        Debug.Log("Wall Creator is ON");
        text.enabled = true;
        GetComponent<WallCreator>().wallPrefab.layer = LayerMask.NameToLayer("Ignore Raycast");

    }

    else
    {
        GetComponent<WallCreator>().enabled = false;
        Debug.Log("Wall Creator is OFF");
        text.enabled = false;
        GetComponent<WallCreator>().wallPrefab.layer = LayerMask.NameToLayer("Default");

       }

   }    

}

3
你在这里遇到的问题可能是GetComponent<WallCreator>().enabled = false;使该组件完全无法交互,因此你可能需要先将其打开、更改图层,然后再关闭它。或者,在关闭之前切换图层。 - Alfie Goodacre
即使我删除了 GetComponent<WallCreator>().enabled = false;(这样我就可以在切换未选中时放置墙壁),该层仅针对新对象更改。我的意思是,例如,我使用切换器 ON 放置 wall1 - 它的层是 "Ignore Raycast",然后我将切换器切换为 OFF,放置 wall2 - 它的层是 "Default",但 wall1 的层不会更改。 - artur47wien
2
我没有意识到你指的是之前放置的墙,那完全是另一个问题了。新的墙在更改后会出现在默认层中 - 这是因为更改预制件会更改创建墙时放置的内容,而不是已经存在的内容。要更改所有墙的层,您可以执行以下操作(假设墙具有标记“wall”):GameObject [] walls = GameObject.FindGameObjectsWithTag(“wall”); 然后您可以通过foreach循环对它们进行操作。 - Alfie Goodacre
1
你还应该发布你的 WallCreator 脚本,并描述每个脚本所附加的位置。 - Programmer
@AlfieGoodacre 是的,我可能没有正确地表达我的问题。无论如何,你的回答帮了我很多,现在它正常工作了,谢谢。 - artur47wien
@artur47wien 如果是这样,我会将其添加为答案 :) - Alfie Goodacre
2个回答

13
新的墙在放置后,如果在预制件中进行更改,则位于“默认”层中 - 这是因为更改预制件会更改创建墙时放置的内容,而不是已经存在的内容。要更改所有墙的层,您可以执行类似于以下内容的操作(假设墙具有标记“wall”)
GetComponent<WallCreator>().wallPrefab.gameObject.layer = LayerMask.NameToLayer("Default");
GameObject[] walls = GameObject.FindGameObjectsWithTag("wall");
foreach(GameObject wall in walls)
{
    wall.layer = LayerMask.NameToLayer("Default");
}
这将循环遍历场景中的每堵墙并将其层级更改为您想要的层级。同样重要的是,WallCreator 的属性也必须被更改,这样在此更改之后放置的墙将保留在新层级而不是旧层级上。

2

看起来你没有引用wallPrefab的gameObject,这可能是问题所在。请将代码更改为:

GetComponent<WallCreator>().wallPrefab.layer = LayerMask.NameToLayer("Ignore Raycast");

致:

GetComponent<WallCreator>().wallPrefab.gameObject.layer = LayerMask.NameToLayer("Ignore Raycast");

不过,如果没看到其他脚本,我不能确定这样做能解决问题。


1
阅读他们评论中的这一部分 - “我将wall1与切换打开放置 - 它的层是“忽略射线”,然后我将切换关闭,放置wall2 - 它的层是“默认”,但是wall1的层并没有改变”,层确实在改变,但他们实际上希望旧墙壁更改层。 - Alfie Goodacre
没想到,这个问题解决了。不过最好还是引用gameObject进行编程实践。我觉得你上面的评论可以解决问题,找到所有对象并改变它们的层级! - KenSchnetz
1
循环遍历它们的附加好处还包括您可以从FindGameObjectsWithTag中获取GameObject - Alfie Goodacre
没错,代码行数少了,你可以确信层级已经改变了。干得漂亮,这是一个非常优雅的解决方案。 - KenSchnetz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接