【问题标题】:New created clone prefab should have the same color as the main one新创建的克隆预制件应与主预制件具有相同的颜色
【发布时间】:2019-12-07 14:59:39
【问题描述】:

首先我要创建一个prefab。当我按 r 时,prefab 的颜色为红色。 现在,我按下按钮 c 并克隆 prefab。克隆的颜色现在默认为白色。但是第一个prefab 的颜色为红色,因此克隆也应该具有相同的颜色。 我试图获取prefab 的颜色,然后将其提供给克隆,不幸的是没有成功。

我现在的问题是,如何给预制件的克隆提供与主预制件相同的颜色?例如,当我创建三个预制件克隆并按 b 时,所有四个预制件都应该是蓝色的。

看看我下面的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class globalControl : MonoBehaviour
{
    public GameObject prefabInstance;
    List<Object> prefabInstanceClones = new List<Object>();
    GameObject capsule, sphere, cylinder;

    private void Start()
    {
        capsule = GameObject.Find("Capsule");
        sphere = GameObject.Find("Sphere");
        cylinder = GameObject.Find("Cylinder");
    }
    void Update()
    {
        Debug.Log(prefabInstanceClones.Count);

        if (Input.GetKeyDown("c"))
        {
            prefabInstanceClones.Add(Instantiate(prefabInstance, transform.position, Quaternion.identity));
        }

        if (Input.GetKeyDown("d"))
        {
            var last = prefabInstanceClones[prefabInstanceClones.Count - 1];
            prefabInstanceClones.Remove(last);
            Destroy(last);
        }


        if (Input.GetKeyDown("r"))
        {
            capsule.GetComponent<Renderer>().material.color = Color.red;
            sphere.GetComponent<Renderer>().material.color = Color.red;
            cylinder.GetComponent<Renderer>().material.color = Color.red;
        } else if (Input.GetKeyDown("b"))
        {
            capsule.GetComponent<Renderer>().material.color = Color.blue;
            sphere.GetComponent<Renderer>().material.color = Color.blue;
            cylinder.GetComponent<Renderer>().material.color = Color.blue;
        } else if (Input.GetKeyDown("g"))
        {
            capsule.GetComponent<Renderer>().material.color = Color.green;
            sphere.GetComponent<Renderer>().material.color = Color.green;
            cylinder.GetComponent<Renderer>().material.color = Color.green;
        }
    }

}

提前感谢您!期待您的回音。 :)

【问题讨论】:

  • 您的 rgb 键正在更改场景中已有对象的颜色,而不是预制件。

标签: c# visual-studio unity3d


【解决方案1】:

当您实例化预制件的实例时,即创建预制件的克隆,该预制件的实例可以在播放时进行修改和更改,而无需更新原始预制件。但是,原始预制件的链接仍然保留。

实例覆盖允许您在 Prefab 之间创建变体 实例,同时仍将这些实例链接到同一个 Prefab 资产。

当您修改预制资源时,更改会反映在所有 它的实例。但是,您也可以直接修改 个别实例。这样做会创建一个实例覆盖 具体实例。

这是 Unity 的核心,允许您在运行时更改您的实例(实例覆盖)。

例如: 我们有一个默认预制件,它代表游戏中的一个演员,就像一个敌方机器人,它在不同的状态下改变颜色 - 攻击时为红色,巡逻时为绿色等。我们实例化了许多副本,并且在运行时对每个实例的更改应该是独立的。

当我按下 r 时,预制件的颜色为红色。 我按下按钮 c,预制件正在被克隆。 克隆的颜色现在默认为白色。 但是第一个预制件的颜色为红色,因此克隆也应具有相同的颜色。

鉴于上述情况,您可以看到您正在更改预制件实例的值 - 运行时的实例覆盖。您对实例所做的任何更改都不会在原始预制件上进行。当您实例化新的预制件时,它们将是原始预制件的独立实例。

其次

查找所有游戏对象的调用仅在 start() 运行 - 它仅在场景开始时运行一次。 GameObject.Find() 将返回一个与当时场景中存在的 name 相匹配的 single 游戏对象。 PS 出于性能原因避免使用GameObject.Find - 而是使用FindWithTag

这意味着您更改颜色的代码仅更改场景开始时存在的那些实例。没有代码可以更改克隆的颜色。

要更改所有新克隆的颜色,您可以执行以下操作:

        List<GameObject> prefabInstanceClones = new List<GameObject>();
        ...

        if (Input.GetKeyDown("a"))
        {
            prefabInstanceClones.ForEach(gameObject => { gameObject.GetComponent<Renderer> ().material.color = Color.red; });
        }

希望对您有所帮助。

【讨论】:

  • 非常感谢您的时间和回答!但我收到错误'Object' does not contain a definition for 'GetComponent' and no accessible extension method 'GetComponent' accepting the first argument of type 'Object' could be found (are you missing a using directive or an assembly reference?)
  • 将列表中的类型更改为GameObject,而不是ObjectList&lt;GameObject&gt; prefabInstanceClones = new List&lt;GameObject&gt;();
【解决方案2】:
  public GameObject prefabInstance;
List<Object> prefabInstanceClones = new List<Object>();
//GameObject capsule, sphere, cylinder;

private void Start() {
    //capsule = GameObject.Find("Capsule");
    //sphere = GameObject.Find("Sphere");
    //cylinder = GameObject.Find("Cylinder");
}
void Update() {
    Debug.Log(prefabInstanceClones.Count);

    if (Input.GetKeyDown("c")) {
        prefabInstanceClones.Add(Instantiate(prefabInstance, transform.position, Quaternion.identity));
    }

    if (Input.GetKeyDown("d")) {
        var last = prefabInstanceClones[prefabInstanceClones.Count - 1];
        prefabInstanceClones.Remove(last);
        Destroy(last);
    }


    if (Input.GetKeyDown("r")) {

        prefabInstance.GetComponent<Renderer>().sharedMaterial.color = Color.red;
    } else if (Input.GetKeyDown("b")) {

        prefabInstance.GetComponent<Renderer>().sharedMaterial.color = Color.blue;

    } else if (Input.GetKeyDown("g")) {

        prefabInstance.GetComponent<Renderer>().sharedMaterial.color = Color.green;

    }
}

你可以使用().sharedMaterial这个属性来影响所有的prefabs颜色。

【讨论】:

  • (1) sharedMaterial 意味着所有生成的副本都会改变颜色,这可能是提问者不想要的。 (2) 我不确定您是否可以访问未实例化的预制件的任何组件。
  • 感谢您的帮助!不幸的是,它没有用。 MissingComponentException: There is no 'Renderer' attached to the "Figure" game object, but a script is trying to access it. You probably need to add a Renderer to the game object "Figure". Or your script needs to check if the component is attached before using it. UnityEngine.Renderer.get_sharedMaterial () (at C:/buildslave/unity/build/Runtime/Export/GraphicsRenderers.bindings.cs:140) globalControl.Update () (at Assets/Scripts/globalControl.cs:37)
  • 创建新材质并附加预制对象。它将以这种方式工作。 @DerMitDemZeh
猜你喜欢
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
  • 2018-05-10
  • 1970-01-01
  • 2021-09-16
相关资源
最近更新 更多