2013年9月16日 星期一

Unity3D研究院之自制批量关联材质与贴图插件(五十八)

http://www.xuanyusong.com/archives/2314

         美术做过的模型导出fbx,美术把Fbx和贴图文件给了程序,程序把Fbx导入工程可能会出现贴图和材质没有关联上的问题,如果场景材质非常多,一个一个去给材质贴图非常的费劲。我有一个办法,最好让美术装上Unity,美术在3DMAX中创建模型并且给材质贴图。然后打开Unity,先把贴图文件全部拷贝在Unity中,这样所有贴图就会有一个Unity的路径。Asset/Textures/pic.png 等等、。。。此时在回到3DMAX中,修改一下材质上贴图的路径,用上面Asset/Textures/pic.png 这样类型的路径重新引用一下下在3dmax中,这时候在导出FBX模型,最后将FBX模型放入Unity工程,你会发现所有材质已经被赋值贴图了。
 在插一句,因为Unity是左手坐标系,而3DMAX是右手坐标系,直接导出FBX以后模型X轴的旋转会变成-90。所以建议美术在3DMAX中修改一下模型的位置。方法是:3XMAX中切换顶视图,默认坐标轴向是 :X轴向右 :Y轴向上: Z轴朝向自己。  修改后还是在顶视图中改成:X轴向右: Y轴朝向自己: Z轴朝下。  这时候在导出FBX 放在Unity中就正常了。
         当Fbx导入Unity的时候会自动在当前路径下生成Materials文件夹,为了避免混乱建议每一个原始Fbx分别放在不同文件夹中,最后统一用Prefab来代替。
废话不多说,回到本篇的重点上,请记住一定要美术把材质的名称和贴图的名称保持一致,程序要根据材质名称去找对象的贴图。考虑到项目中会有多个模型使用同一个贴图的情况所以建议大家把贴图都放在同一个文件夹下,必须放在/Assets/Textures文件夹中。如下图所示,在Hierarchy视图中先选择需要批量关联的游戏对象,只需选择父对象就可以,程序会自动遍历所有子对象,然后点击Windows->ApplyMaterial弹出关联窗口。
官网上说是可以先把贴图文件放在Textures文件夹中,然后在把模型文件放入工程,Unity会自动匹配材质和贴图的关系,这个不办法我试过但是不是每次都会成功,我也不知道为什么,所以就写了这个插件。

屏幕快照 2013-05-08 下午9.07.46


如下图所示,可以批量关联材质,也可以批量删除材质。我已经测试过比较多的场景材质和贴图的关联,也希望大家帮我测试测试嘿嘿。。


F5688D8F-34B1-4A8F-A2F6-DD8263D26654

关联前

屏幕快照 2013-05-08 下午9.25.50

关联后
屏幕快照 2013-05-08 下午9.25.54


把插件的代码放在Editor文件夹中,由于你的贴图可能是多个类型的,只需在下面代码的config数组中配置一下,目前我配置了.png .jpg .tag格式,也可以继续拓展。


using UnityEngine;
using System.Collections;
using UnityEditor;

public class ApplyMaterial : EditorWindow
{

  public static  string  [] config =
	{
		".PNG",".JPG",".TGA"
	};

   [MenuItem ("Window/ApplyMaterial")]	
    static void Applay ()
	{       

		Rect  wr = new Rect (0,0,500,500);
        ApplyMaterial window = (ApplyMaterial)EditorWindow.GetWindowWithRect (typeof (ApplyMaterial),wr,true,"widow name");	
		window.Show();

    }

	void OnGUI ()
	{
			if(GUILayout.Button("批量关联材质"))
			{
				ApplayMatrials(true);
			}
			if(GUILayout.Button("批量删除关联"))
			{
				ApplayMatrials(false);
			}
	}

	 void ApplayMatrials(bool isAdd)
	{
		if(Selection.activeGameObject != null)
		{
			foreach(GameObject g in Selection.gameObjects)
			{
				Renderer []renders = g.GetComponentsInChildren<Renderer>();
				foreach(Renderer r in renders)
				{
					if(r  !=  null)
					{
						foreach(Object o in r.sharedMaterials)
						{
								string path = AssetDatabase.GetAssetPath(o);
								Material m = Resources.LoadAssetAtPath(path,typeof(Material)) as Material;

								if(isAdd)
								{
									if(m.mainTexture  == null)
									{
										Texture t = GetTexture(m.name);
										if(t != null)
										{
											m.mainTexture = t;
										}else
										{
											Debug.Log("材质名:" + o.name + " 材质替换失败,请检查资源" );
										}
									}
								}else
								{
									m.mainTexture = null;

								}
						}
					}
				}
			}	

			this.ShowNotification(new GUIContent("批量关联材质贴图成功"));
		}else
		{
				this.ShowNotification(new GUIContent("没有选择游戏对象"));
		}
	}

	static Texture GetTexture(string name)
	{
		foreach(string suffix in config)
		{
			Texture t = Resources.LoadAssetAtPath("Assets/Textures/" + name+suffix,typeof(Texture)) as Texture;
			if(t != null)
				return t;
		}
			return null;						
	}
}

最后是本文的下载地址:http://vdisk.weibo.com/s/AFWi4  
祝大家学习愉快,啦啦啦啦德玛西亚~~~~