改变一个对象会改变所有实例化的对象

Changing an object change all the instantiated objects

我知道问题的主题已经被问过并且已经给出了一些答案,但我再次问这个问题是因为当我尝试应用其他主题的答案时我失败了。

我遇到的问题是,我有一个预制件(四边形)'Star',里面有一个 material 和一个脚本,它会在一段时间后改变颜色:

using UnityEngine;

public class Star: MonoBehaviour {
  public enum StarType {
    BRIGHT,
    DARK,
    F,
    K,
    L,
    P
  }

  private Ship ship;
  private StarType starType;
  private float timeLimit = .30f, timer;
  private System.Random rand;

  public void Awake() {
    ship = FindObjectOfType<Ship>();

    timer = .0f;
    rand = new System.Random();
  }

  public void Start() {
    refactor();
  }

  public void Update() {
    timer += Time.deltaTime;
    if(timer > timeLimit) {
        refactor();
        timer = .0f;
    }
  }

  public void LateUpdate() {
    transform.eulerAngles = new Vector3(ship.transform.eulerAngles.x,
                                        ship.transform.eulerAngles.y,
                                        ship.transform.eulerAngles.z);
  }

  public void refactor() {
    starType = (StarType) rand.Next(0, 
             System.Enum.GetValues(typeof(StarType)).Length);
    switch(starType ) {
    case StarType.BRIGHT:
        renderer.material.color = Color.white;
        break;
    case StarType.DARK:
        renderer.material.color = Color.black;
        break;
    case StarType.F:
        renderer.material.color = Color.red;
        break;
    case StarType.K:
        renderer.material.color = Color.cyan;
        break;
    case StarType.L:
        renderer.material.color = Color.green;
        break;
    case StarType.P:
        renderer.material.color = Color.magenta;
        break;
    }
  }

  public StarType getStarType() {
    return starType;
  }
}

这颗星在块中实例化class:

public class Chunk : MonoBehaviour {
  public Star star;

  private IList<Star> stars;

  public void Awake() {
    stars = new List<Star>();

    Star auxStar = (Star) Instantiate(star, transform.position, 
                      Quaternion.identity);
    auxStar.transform.SetParent(transform);

    stars.Add(auxStar);
  }
}

我原以为每颗星星都会独立地改变颜色,但事实并非如此,它们都变成了相同的颜色。

我试过使用 sharedMaterial 而不是 material 正如我在一些 asnwers 上读到的那样,尽管结果和行为看起来是一样的?,我尝试给星星随机初始颜色,但最我得到的是其中一些颜色改变为与其余颜色不同的颜色,尽管它们之间仍然相同(而且我一直在尝试改变颜色,而不仅仅是在创建时)。 我也读过创建 material 并在实例化时分配给每个人,但我没有运气:

auxStar.renderer.material = (Material) 
                                 Instantiate(star.renderer.material);

有人知道如何处理这个问题吗?

尝试使用 Random.Range() 因为 System.Random 是由系统时间生成的。正如我们所知,时间并不是真正随机的。它仍然依赖于毫秒时间并生成随机的逻辑,因为我们无法真正判断随机将 运行.

自 System.Random 运行s 在您的脚本正在使用的 1 个时间线上。 Random.Range() 是一个你可以考虑的赌注,因为它使用 SystemTime 和平台的 运行 上的独立时间。与 Time.DeltaTime 分享。

根据 Unity API reference,您做的是对的。 您的代码中的问题是您正在实例化 MonoBehaviour

public Star star;
...
Star auxStar = (Star) Instantiate(star, transform.position, Quaternion.identity);

其中 star 是 MonoBehaviour,您没有使用 Mesh Render and/or Material 实例化实际的 GameObject。相反,请确保您正在实例化正确的 GameObject Prefab,而不仅仅是组件,如下所示:

public GameObject starPrefab;
...
GameObject starClone = (GameObject) Instantiate (starPrefab);
Star auxStar = starClone.GetComponent<Star> ();

通过这种方式,如果需要,您可以控制 GameObject 以及与克隆对象关联的每个组件,在本例中为 Star。您不必实例化预制件 Material 因为它已经实例化了。 这是一个简单的例子:

using UnityEngine;
using System.Collections;

public class SpawnStar : MonoBehaviour {

    public GameObject StarPrefab;
    public bool InstantiateStar = false;

    void Update () {
        if (InstantiateStar) {
            GameObject starClone = (GameObject)Instantiate (StarPrefab);

            float r = Random.Range (0f, 1f);
            float g = Random.Range (0f, 1f);
            float b = Random.Range (0f, 1f);
            float a = Random.Range (0f, 1f);

            starClone.renderer.material.color = new Color (r, g, b, a);
            InstantiateStar = false;
        }
    }
}

旁注:确保在游戏过程中不要修改预制件,因为它是所有其他克隆对象的来源。