【问题标题】:How to dynamically set a random Material on a GameObject如何在游戏对象上动态设置随机材质
【发布时间】:2018-11-21 21:01:03
【问题描述】:

我是 unity 的新手,我只是想知道如何从 C# 设置材质?

我有一个预制模型,我可以从编辑器更改纹理没问题。我要做的是在生成预制件实例时随机设置材质。

这是我要更改的字段:

我正在使用以下代码创建这些:

Instantiate(eggPrefab, spawnPos, Quaternion.identity);

(其中 eggPrefab 是一个公共的 Transform)。

我希望这是足够的信息!

谢谢。

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    实例化 GameObject 后,从中获取 MeshRenderer,然后更改其材质:

    public GameObject eggPrefab;
    public Vector3 spawnPos;
    public Material mat;
    
    void Start()
    {
        GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
        obj.GetComponent<MeshRenderer>().material = mat;
    }
    

    如果您没有材质,则可以使用着色器创建一个并将其分配给 MeshRenderer:

    GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
    
    //Find the Standard Shader
    Material mat = new Material(Shader.Find("Standard"));
    //Set Texture on the material
    //mat.SetTexture("_MainTex", yourTexture);
    
    obj.GetComponent<MeshRenderer>().material = mat;
    

    最后,如果您有多个材质,则使用materials 属性而不是material 属性并将您的材质数组分配给它:

    GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
    
    //Find the Standard Shader
    Material mat = new Material(Shader.Find("Standard"));
    //Set Texture on the material
    //mat.SetTexture("_MainTex", yourTexture);
    
    //Create array of mats (Create one for example)
    Material[] mats = new Material[1];
    mats[0] = mat;
    
    obj.GetComponent<MeshRenderer>().materials = mats;
    

    编辑:

    我错过了随机部分。如果要随机选择材质,只需使用Random.Range 从材质数组中选择一项即可。

    public GameObject eggPrefab;
    public Vector3 spawnPos;
    public Material[] mats;
    
    void Start()
    {
        GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
        int matIndex = UnityEngine.Random.Range(0, mats.Length);
        obj.GetComponent<MeshRenderer>().material = mats[matIndex];
    }
    

    【讨论】:

    • @ls_dev 每次分配给 Renderer.material 时,您(不知何故)分配了一个新的材质实例并增加了绘制调用的数量。始终使用 Renderer.sharedMaterial 来避免这种情况。
    • @KevinRemo 不。不是每次。它仅在渲染器上的每次调用中发生一次。此外,有时您需要Renderer.material,然后是Renderer.sharedMaterial。这完全取决于 OP 正在做什么,因为如果您有许多对象/预制件引用一种材料,则应使用 Renderer.material 更改它们的 individual 颜色。如果您想使用该材质更改对象的所有颜色,请使用Renderer.sharedMaterial。 OP 可能会使用 MaterialBlock 来阻止创建新实例,但它会破坏批处理。
    • 谢谢你的帮助,我明天试试这个并更新线程。
    • @ls_dev 应该注意的是,Renderer.material 在第一次调用时会自动克隆材料。它是“让开发人员轻松做事”的辅助功能之一。
    【解决方案2】:

    我认为将随机材料行为与创建行为混合在一起会使事情变得过于复杂。只需在Start 上创建一个随机化游戏对象材质的组件,它就会在您实例化您的预制件时运行。

    public class MaterialRandomiser : MonoBehaviour {
    
      [SerializeField]
      private Material[] _materials;
      [SerializeField]
      private Renderer _renderer;
    
      public void Start () {
        ChangeMaterial();
      }
    
      public void Reset () {
        _renderer = GetComponent<Renderer>();
      }
    
      public void ChangeMaterial () {
        _renderer.material = SelectRandomMaterial();
      }
    
      private Material SelectRandomMaterial () {
        return _materials[Random.Range(0, _materials.Length)];
      }
    
    }
    

    将它附加到您的预制件上,现在当您生成它们时,它们将具有随机材料。您现在还可以选择在非预制对象上使用相同的代码。只是不要忘记分配材料!

    【讨论】:

    • 这实际上非常容易添加,无需更改我现有的任何代码。谢谢!
    【解决方案3】:

    您可以使用材料数组执行以下操作。

        public Material[] materialsArray;
        public GameObject prefab;
        private Vector3 pos = new Vector3(0, 0, 0);
        private Quaternion rot = Quaternion.identity;
    
        private void Start()
        {
            Material mat = RandomMaterial(materialsArray);
            InstantiateWithMaterial(prefab, pos, rot, mat);
        }
    
        public Material RandomMaterial(Material[] _array_)
        {
            return _array_[Random.Range(0, _array_.Length)];
        }
    
        public void InstantiateWithMaterial(GameObject _prefab_, Vector3 _pos_, Quaternion _rot_, Material _mat_)
        {
            GameObject obj_ = Instantiate(_prefab_, _pos_, _rot_);
            obj_.gameObject.GetComponent<MeshRenderer>().material = _mat_;
        }
    

    这应该可以按照您的意愿工作,只需放置在一个空的游戏对象上,然后用您想要的所有材质填充材质数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多