Unity:游戏在编辑器中工作,但在构建时不工作。编辑器代码与构建不同吗?

Unity: Game works in editor but doesn't when built. Does editor code differ from build?

我使用 Unity 引擎创建的简单游戏有问题。在这个游戏中,玩家可以捡起物体并与之互动。我正在做的是,当玩家正在看一个物体并且在范围内时,该物体会改变颜色。这在编辑器中工作正常,不会抛出任何错误。

然而,在构建游戏时,一切似乎都正常,直到我查看对象并尝试与之交互。颜色变为粉红色,就好像没有 material/texture。当我移开视线时它保持粉红色,当它应该变成原来的 color.Also 调试时没有错误。

在编辑器中:

查看对象之前

查看对象后

在内置游戏中:

查看对象之前

查看对象后

代码:

调用变色的交互:

    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, raycastDistance, layerMask))
    {


        if (hit.collider.tag=="Computer") {
            hit.collider.GetComponentInChildren<Image> ().color = Color.cyan;

            return;
        }

        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);

        if (lastHit != null) {

            if (lastHit != GameObject.Find (hit.collider.name)) {
                lastHit.GetComponent<ManipulateColor> ().setDefaultColor ();
            }
        }

        lastHit = GameObject.Find (hit.collider.name);
        lastHit.GetComponent<ManipulateColor> ().setColor ();

        interactionText.text = lastHit.GetComponent<Interactable> ().interactionText;
        interactionText.enabled = true;

        canInteract = true;

    }
    else
    {
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * raycastDistance, Color.white);

        if (lastHit != null) {
            lastHit.GetComponent<ManipulateColor> ().setDefaultColor ();
        }

        interactionText.enabled = false;
        canInteract = false;
    }

// 颜色变化 class:

public Color colorToSet = Color.green;

private Color defaultColor;

private List<Color> childrenColors = new List<Color>();
private List<Color> colorListToUse = new List<Color> ();

private Renderer rend;

private bool hasChildren = false;
private bool parentHasRender = false;

// Use this for initialization
void Start () {


    if (gameObject.transform.childCount > 0) {
        hasChildren = true;
        if (gameObject.GetComponent<Renderer> ()!=null) {
            rend = gameObject.GetComponent<Renderer> ();
            childrenColors.Add (rend.materials [0].color);
            parentHasRender = true;
        } 

        foreach (Transform child in gameObject.transform) {


            if (child.gameObject.GetComponent<Renderer> ()!=null) {

                rend = child.gameObject.GetComponent<Renderer> ();
                childrenColors.Add (rend.materials [0].color);
            }

        }

    } else {
        rend = gameObject.GetComponent<Renderer> ();
        defaultColor = rend.materials[0].color;
    }


    colorListToUse = childrenColors;

}

public void setColor(){




    if (hasChildren) {
        if (parentHasRender) {
            rend = gameObject.GetComponent<Renderer> ();
            rend.materials[0].shader = Shader.Find ("_Color");
            rend.materials[0].SetColor ("_Color", colorToSet);


            rend.materials[0].shader = Shader.Find ("Specular");
            rend.materials[0].SetColor ("_SpecColor", colorToSet);
        }


        foreach (Transform child in gameObject.transform) {
            if (child.gameObject.GetComponent<Renderer> ()!=null) {
                rend = child.gameObject.GetComponent<Renderer> ();
                rend.materials[0].shader = Shader.Find ("_Color");
                rend.materials[0].SetColor ("_Color", colorToSet);



                rend.materials[0].shader = Shader.Find ("Specular");
                rend.materials[0].SetColor ("_SpecColor", colorToSet);
            }



        }

    } else {
        rend.materials[0].shader = Shader.Find("_Color");
        rend.materials[0].SetColor ("_Color", colorToSet);


        rend.materials[0].shader = Shader.Find("Specular");
        rend.materials[0].SetColor ("_SpecColor", colorToSet);
    }

}

public void setDefaultColor(){



    if (hasChildren) {
        if (parentHasRender) {

            rend.materials[0].shader = Shader.Find("_Color");
            rend.materials[0].SetColor ("_Color", colorListToUse[0]);


            rend.materials[0].shader = Shader.Find("Specular");
            rend.materials[0].SetColor ("_SpecColor", colorListToUse[0]);
            colorListToUse.RemoveAt (0);
        }


        foreach (Transform child in gameObject.transform) {
            if (child.gameObject.GetComponent<Renderer> ()!=null) {
                rend = child.gameObject.GetComponent<Renderer> ();
                rend.materials[0].shader = Shader.Find ("_Color");
                rend.materials[0].SetColor ("_Color", colorListToUse[0]);



                rend.materials[0].shader = Shader.Find ("Specular");
                rend.materials[0].SetColor ("_SpecColor", colorListToUse[0]);
            }
        }


    } else {
        rend = gameObject.GetComponent<Renderer> ();
        rend.materials[0].shader = Shader.Find("_Color");
        rend.materials[0].SetColor ("_Color", defaultColor);


        rend.materials[0].shader = Shader.Find("Specular");
        rend.materials[0].SetColor ("_SpecColor", defaultColor);

    }


    colorListToUse = childrenColors;
}

已解决:

删除所有 Shader.Find 和 SetColor,而仅使用 rend.materials[0].color = colorToSet 解决了问题;

删除所有 Shader.Find(“...”) 调用,因为它确实尝试加载具有该名称的着色器,该名称不存在并导致统一显示心爱的粉红色后备着色器。

首先

rend.materials[0].shader = Shader.Find("_Color");
rend.materials[0].SetColor ("_Color", colorToSet);


rend.materials[0].shader = Shader.Find("Specular");
rend.materials[0].SetColor ("_SpecColor", colorToSet);

将毫无用处,因为您覆盖了第 3 行中的 materials[0].shader 而不是仅更改了此新着色器的 SpecColor。这使得第 1+2 行变得多余/无效。


关于你的问题:是的,构建的行为与编辑器有点不同。在构建项目中,如果从未引用过(=> 显然从未使用过),则项目中的大部分 Assets/Scripts 等都会被删除。

来自Shader.Find

Note that a shader might be not included into the player build if nothing references it! In that case, Shader.Find will work only in the editor, and will result in pink "missing shader" materials in the player build. Because of that, it is advisable to use shader references instead of finding them by name. To make sure a shader is included into the game build, do either of:

1) reference it from some of the materials used in your scene,

2) add it under "Always Included Shaders" list in ProjectSettings/Graphics or

3) put shader or something that references it (e.g. a Material) into a "Resources" folder.


但实际上在我看来,您并不是真的想在运行时更改 material 的 Shader,而是更改颜色。

所以不用

rend.materials[0].shader = Shader.Find("_Color");
rend.materials[0].SetColor ("_Color", colorListToUse[0]);

你应该只使用

rend.materials[0].color = colorToSet;

改变material的颜色。另见 Material.color

如果你只分配了一个 material 你也可以简单地使用

rend.material.color = colorToSet;

如果您还需要设置 SpecColor,您应该已经在编辑器中将相应的 material 设置为镜面反射,然后您仍然可以使用

rend.materials[0].SetColor ("_SpecColor", colorToSet);