我目前正在使用C#在Unity中开发一个益智游戏。我判断玩家是否获胜的方法是看一堆游戏对象是否具有相同的材质。如何确定有多少个游戏对象附有特定的材质?
我目前正在使用C#在Unity中开发一个益智游戏。我判断玩家是否获胜的方法是看一堆游戏对象是否具有相同的材质。如何确定有多少个游戏对象附有特定的材质?
以下是关于IT技术的翻译内容:
这段代码应该会对你有所帮助。
当你调用此方法并传入想要检查的材质时,它将返回当前在场景中使用相同材质的游戏物体数量。
//-----------------------------------------------------------------------------
// 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”中打开窗口。
//---------------------
//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;
}
}
if (col.GetComponent<MeshRenderer> ())
col.GetComponent<MeshRenderer> ().sharedMaterial = mat;
.sharedMaterial
比使用.material
更安全,因为它创建材质的新实例(我从@fredrik-widerberg的回答中纠正了这个最后的断言,因为我是错误的)。
最后一个提示是,如果您不知道,获取Renderer
组件允许您访问所有渲染器类型(如MeshRenderer
,SkinnedMeshRenderer
,...)。private int CountMaterials(Material material)
{
int count = 0;
foreach (var gameObject in gameObjects)
{
if (gameObject.GetComponent<MeshRenderer>().sharedMaterial == material)
count++;
}
return count;
}
if(CountMaterials(mat) > CountMaterials(mat2))
{
Debug.Log("1 Wins");
}
else
{
Debug.Log("2 Wins");
}
编辑:在分配材质时,请确保使用sharedMaterial而不是material,因为分配material会创建材质的新实例。