首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何检测有多少游戏对象具有特定的材质?

如何检测有多少游戏对象具有特定的材质?
EN

Stack Overflow用户
提问于 2018-06-03 06:12:39
回答 1查看 1.1K关注 0票数 7

因此,我目前正在使用c#在unity中开发一款益智游戏。我判断玩家是否获胜的方法是看一堆游戏对象是否有相同的素材。如何确定有多少游戏对象附加了某种材质?

EN

回答 1

Stack Overflow用户

发布于 2018-06-03 09:08:23

这段代码应该会对你有所帮助。

当调用此方法传递要检查的材质时,它会返回当前在场景中处于活动状态的使用相同材质的GameObjects的数量。

代码语言:javascript
复制
    //-----------------------------------------------------------------------------
    // getObjsWithMat
    //-----------------------------------------------------------------------------
    public static int getObjsWithMat (Material mat) {
        Material m_DefaultMat = mat;
        int m_c = 0;

        GameObject[] AllObjs = Object.FindObjectsOfType<GameObject> ();
        foreach (GameObject Obj in AllObjs) {
            if (Obj.activeInHierarchy) {
                if (Obj.GetComponent <Renderer> ()) {
                    foreach (Material Mat in Obj.GetComponent <Renderer> ().sharedMaterials) {
                        if (Mat == m_DefaultMat)
                            m_c++;
                    }
                }
            }
        }

        return m_c;
    }

这是我在编辑器中用来测试它的实现。既然我做了它,而且我不需要它,我想它可能会在某个时候帮助别人,所以它就在这里。您需要将其复制到名为'GetStatsWindow.cs‘的脚本中,该脚本必须位于名为'Editor’的文件夹中。你可以从菜单" window /Find Objects with Material“在编辑器中打开窗口。

代码语言:javascript
复制
//---------------------
//FrankGames production
//---------------------

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

public class GetStatsWindow : EditorWindow {

    private static Material m_DefaultMat = null;
    private static int m_c = -1;
    private static int m_c2 = 0;

    private static bool m_DisplayResult = false;
    private static Vector2 m_RectPos = Vector2.zero;

    private static GameObject[] m_ObjsFound = new GameObject[0];

    private static bool m_Working = false;

    //-----------------------------------------------------------------------------
    // ShowWindow
    //-----------------------------------------------------------------------------
    [MenuItem ("Window/Find Objects with Material")]
    public static void ShowWindow () {
        EditorWindow.GetWindow (typeof (GetStatsWindow));
    }

    //-----------------------------------------------------------------------------
    // OnGUI
    //-----------------------------------------------------------------------------
    void OnGUI () {
        EditorGUILayout.BeginVertical ();

        EditorGUILayout.HelpBox ("First, select a material in the 'Material to find' Input field.\nThan press the 'Find' Button.\nAfter some calculations (it could take some time, depending on your Hardware and the amount of objects and Materials that it has to check.", MessageType.Info);

        if (m_Working)
            EditorGUI.BeginDisabledGroup (true);

        m_DefaultMat = EditorGUILayout.ObjectField ("Material to find", m_DefaultMat, typeof (Material), true) as Material;

        if (m_DefaultMat == null && !m_Working)
            EditorGUI.BeginDisabledGroup (true);

        if (GUILayout.Button ("Find Objects")) {
            getObjWithMat ();
        }

        if (m_DefaultMat == null && !m_Working)
            EditorGUI.EndDisabledGroup ();

        if (m_Working)
            EditorGUILayout.LabelField ("Calculating...");

        if (m_c != -1) {
            if (GUILayout.Button ("Clear result") && EditorUtility.DisplayDialog ("Are you sure?", "Do you really want to clear the result of your search?", "Continue", "Cancel")) {
                m_DefaultMat = null;
                m_c = -1;
                m_c2 = 0;
                m_DisplayResult = false;
                m_RectPos = Vector2.zero;
                m_ObjsFound = new GameObject[0];
                m_Working = false;
            } else {

                EditorGUILayout.LabelField (m_c2 + " Objects have been checked!");
                EditorGUILayout.LabelField (m_c + " Objects with the '" + m_DefaultMat.name + "' Material have been found!");

                m_DisplayResult = EditorGUILayout.Toggle ("Display Results", m_DisplayResult);

                if (m_DisplayResult) {
                    EditorGUILayout.LabelField ("Objects found with '" + m_DefaultMat.name + "':");

                    m_RectPos = EditorGUILayout.BeginScrollView (m_RectPos);
                    EditorGUILayout.BeginVertical ();
                    EditorGUI.BeginDisabledGroup (true);
                    for (int i = 0; i < m_ObjsFound.Length; i++) {
                        EditorGUILayout.ObjectField ("[" + i + "] Object found", m_ObjsFound [i], typeof(GameObject), true);
                    }
                    EditorGUI.EndDisabledGroup ();
                    EditorGUILayout.EndVertical ();
                    EditorGUILayout.EndScrollView ();

                }
            }
        }

        if (m_Working)
            EditorGUI.EndDisabledGroup ();

        EditorGUILayout.EndVertical ();
    }

    //-----------------------------------------------------------------------------
    // getObjWithMat
    //-----------------------------------------------------------------------------
    public static int getObjWithMat (Material mat = null) {
        if (mat != null)
            m_DefaultMat = mat;
        else if (m_DefaultMat == null)
            return -1;

        m_Working = true;

        m_c = 0;
        m_c2 = 0;

        List<GameObject> Objs = new List<GameObject> ();

        GameObject[] AllObjs = Object.FindObjectsOfType<GameObject> ();
        foreach (GameObject Obj in AllObjs) {
            m_c2++;
            bool Found = false;
            if (Obj.activeInHierarchy) {
                if (Obj.GetComponent <Renderer> ()) {
                    foreach (Material Mat in Obj.GetComponent <Renderer> ().sharedMaterials) {
                        if (Mat == m_DefaultMat) {
                            Found = true;
                            m_c++;
                        }
                    }
                }
            }
            if (Found)
                Objs.Add (Obj);
        }

        m_ObjsFound = Objs.ToArray ();
        Objs.Clear ();

        m_Working = false;

        return m_c;
    }

}

编辑我看到了你分享的代码示例,用来改变材料。

相反,尝试:

代码语言:javascript
复制
if (col.GetComponent<MeshRenderer> ())
    col.GetComponent<MeshRenderer> ().sharedMaterial = mat;

这是因为在访问组件之前检查GameObject是否具有该组件,即使这对于您的解决方案可能不是必需的,它也可以防止某些“空异常引用”的发生。此外,使用.sharedMaterial比使用.material更安全,因为它创建了一个新的材料实例(我从@fredrik-widerberg的答案中更正了这最后一个补充信息,因为我是错误的)。最后一个技巧,如果你不知道,获取Renderer组件,允许你访问所有的渲染器类型(比如MeshRendererSkinnedMeshRenderer,...)。

我希望我能帮上忙!

迭戈

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50661586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档