Unity3D研究院之利用unity自带API提前合并场景Mesh

Unity自带了合并Mesh的功能,最简单的做法就是在Root节点勾选static选项,它的原理就是运行时合并。但是最近我在开发的时候就遇到了问题,因为我们场景非常庞大,Mesh的顶点不能超65535所以Unity会自动把合并的mesh分成了很多分mesh,总之顶点都小于65535。

在IOS上测试都是正常的,可是在有些Android机器是场景就出问题了。就是渲染不正确,所以得到的结论就是不能完全依赖Unity的合并Mesh功能。再说Mesh合并的太大一样会带来性能的影响。所以我就在想能不能有策略性的合并Mesh.答案肯定是可行的,比如我根据gameObject的位置找出50米之内的MeshRender然后进行合并。如果是运行时合并,为了避免大量查找所带来的性能消耗,可以在Editor下提前把需要合并的mesh序列化在场景里。 在场景加载的Awake里进行合并。

我在说说另一种生成文件的方式。今天我想说的就是把有些mesh提前合并成.asset文件,直接写在unity工程里。网上我找到了一些别的文章,但都是要生成一个全新的大mesh,然后把之前的小mesh全都隐藏了。我感觉没有unity原有的方式好,因为假如原有的gameObject上挂了一些脚本, 这样一隐藏脚本也就失去了某些意义。。而且还不能单独的显示/隐藏某一个特定的mesh。

如下图所示,美术把所有的mesh都放在了Root节点下面。每一个MeshFilter都应该是美术自己创建的FBX里的。

我现在想做的就是,把某些MeshFilter合并,生成一个新的Mesh,并且要直接修改在原有的MeshFilter上的mesh。如下图所示,最终的结果。

为了避免重名我会根据当前场景的路径在平级目录下生成一个文件夹,把生成的mesh文件放进去。并且替换原有meshFilter上的mesh文件。

下面是我的代码。

using UnityEngine;
using System.Collections;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.IO;
 
public class CreateMesh  {
 
	[MenuItem("Tools/create")]
	static void Start1 () 
	{
		GameObject root = GameObject.Find("Root");
 
		if(root)
		{
			MeshRenderer [] meshRenderers = root.GetComponentsInChildren<MeshRenderer>();
 
			GameObject [] gos = new GameObject[meshRenderers.Length];
			for(int i = 0; i< meshRenderers.Length;i++)
			{
				gos[i] =meshRenderers[i].gameObject; 
			}
 
			string scenePath = EditorSceneManager.GetSceneAt(0).path;
			string meshScenePath = scenePath.Replace(".unity","_mesh");
			string fullPath = Path.Combine(Directory.GetCurrentDirectory(),meshScenePath);
 
			if(Directory.Exists(fullPath))
				Directory.Delete(fullPath,true);
			Directory.CreateDirectory(fullPath);
			string assetPath = FileUtil.GetProjectRelativePath(fullPath);
 
			StaticBatchingUtility.Combine(gos,root);
			for(int i =0; i< gos.Length; i++)
			{
				Mesh mesh = gos[i].GetComponent<MeshFilter>().sharedMesh;
				string meshPath = AssetDatabase.GetAssetPath(mesh);
 
				if(string.IsNullOrEmpty(meshPath))
				{
					string path = Path.Combine(assetPath,Random.Range(int.MinValue,int.MaxValue) +".asset");
					AssetDatabase.CreateAsset(mesh,path);
				}
 
			}
		}
		AssetDatabase.Refresh();
		EditorSceneManager.MarkAllScenesDirty();
	}
}

StaticBatchingUtility.Combine 这方法有两个重载

1.参数root节点。这样使用起来就有点限制了, 因为美术就得提前放需要合并的mesh放在一个规定的节点下。假如我想把一个节点合并成多个 mesh就不行了。

2.参数是 数组 和一个顶层节点。 这个用起来就方便多了。我可以把我需要合并的gameObject放在一个数组里,然后给他们指定一个节点就行了。(指定在地图的顶层节点上就行了)

最后欢迎大家一起讨论。 目前我还是在 运行时合并 和 提前合并 中拿捏不定!!

猜你喜欢

转载自blog.csdn.net/mango9126/article/details/101703496