在U3D中用正則表達式實現FBX文件的自動分割

1.前言
MAX製作角色動畫還是很便利的,cs骨骼系統加上自帶的bone骨骼就能勝任基本的絕大部分的多足動物骨骼的構建。
導出爲FBX的時候有時候會提示進行動畫烘焙,類似法線烘焙之類的求解過程,實際上magic spring插件的原理也和這裏差不多吧。
將導出的FBX直接導入U3D的時候,常常會出現材質丟失的問題,這個時候重新導入材質就好。
然後就到了分割的時候了。
2.普通的分割方式
 在FBX文件的動畫選項卡中新建一個剪輯,然後制定起始和結束的幀號,設定勾選有關的參數即可。
雖然操作上是很方便,但是實際流程中,需要在MAX中記錄幀號,然後對着記錄下來的信息一點一點設定,還是覺得有點麻煩……
之前沒有接觸U3D的時候,甚至還需要把信息傳給其他人員來進行操作,這樣出錯的環節就增多了。
3.利用正則的快速分割
因爲記錄幀號的時候會遵照一定的格式,所以用正則來做的話會很方便。
U3D特殊文件夾中Editor文件夾中的腳本可以調用U3D自帶的部分API,嘗試以這個爲突破口來進行下去吧!
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.IO;
using System.Text.RegularExpressions;
using System;
using System.IO;


public class FbxAnimListPostprocessor : AssetPostprocessor
{
	public void OnPreprocessModel()
	{
		if (Path.GetExtension(assetPath) == ".FBX")//判斷拓展名FBX
		{
			try
			{
				string fileAnim;
				if (DragAndDrop.paths.Length <= 0)//若文件名合法性
				{
					return;
				}
				fileAnim = DragAndDrop.paths[0];
				string ClipText = Path.ChangeExtension(fileAnim, ".txt");//按照相同文件名尋找txt文件
				StreamReader file = new StreamReader(ClipText);
				string sAnimList = file.ReadToEnd();//處理後的動畫列表,
				file.Close();//關閉文件
				//
				if (EditorUtility.DisplayDialog("是否從下列文件中導入已關聯的FBX動畫?",
					fileAnim, "導入", "取消"))//標題、正文、選項卡
				{
					System.Collections.ArrayList List = new ArrayList();
					ParseAnimFile(sAnimList, ref List);//自定義的parse方法

					ModelImporter modelImporter = assetImporter as ModelImporter;
					//modelImporter.clipAnimations. = true;
					modelImporter.clipAnimations = (ModelImporterClipAnimation[])
						List.ToArray(typeof(ModelImporterClipAnimation));//轉換正則捕捉到的結果

					EditorUtility.DisplayDialog("已導入動畫",
						"已導入剪輯數量 "
						+ modelImporter.clipAnimations.GetLength(0).ToString(), "OK");
				}
			}
			catch { }

	}

	void ParseAnimFile(string sAnimList, ref System.Collections.ArrayList List)
	{
		Regex regexString = new Regex(" *(?<firstFrame>[0-9]+) *- *(?<lastFrame>[0-9]+) *(?<loop>(loop|noloop| )) *(?<name>[^\r^\n]*[^\r^\n^ ])",
			RegexOptions.Compiled | RegexOptions.ExplicitCapture);

		Match match = regexString.Match(sAnimList, 0);//逐條獲取
		while (match.Success)
		{
			ModelImporterClipAnimation clip = new ModelImporterClipAnimation();

			if (match.Groups["firstFrame"].Success)//寫入firstName
			{
				clip.firstFrame = System.Convert.ToInt32(match.Groups["firstFrame"].Value, 10);
			}
			if (match.Groups["lastFrame"].Success)//寫入lastName
			{
				clip.lastFrame = System.Convert.ToInt32(match.Groups["lastFrame"].Value, 10);
			}
			if (match.Groups["loop"].Success)//寫入loop信息
			{
				clip.loop = match.Groups["loop"].Value == "loop";
			}
			if (match.Groups["name"].Success)//寫入name
			{
				clip.name = match.Groups["name"].Value;
			}

			List.Add(clip);//在輸出結果的List中增加定義完成的clip

			match = regexString.Match(sAnimList, match.Index + match.Length);//讀取下一節內容
		}
	}
}
在Asset文件夾下創建Editor文件夾,然後新建一個Divider.cs文件使用以上代碼。
在FBX文件的同一目錄下創建同名的txt文檔,內容格式如下:
起始幀號-結束幀號 循環信息 剪輯名
然後拖動文件進入U3D中指定的文件夾下,會彈出是否導入關聯動畫的窗體,此時選擇取消的話就會正常導入。
如圖,對應上面txt文件中的內容,模型導入的時候自動生成了剪輯列表!

4.後話
不過,其實最本質的解決方法不應該是在MAX中嗎??
像是老Flash8那樣指定幀標籤,給幀制定幀名,用一個字符串來表示特定的幀,這樣的話後期調整就會更加靈活,如果FBX文件中帶有這種信息並且U3D中可以識別,那麼完全不需要這樣做。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章