Max09在模型到处的模型和U3D场景的尺寸不一致,Max09中的1m导到U3D中,只有0.01m,这时可以在U3D中将模型的FbxImporter中将Scale Factor改为1。
上述事情也可以通过脚本直接处理:
using UnityEditor;
using UnityEngine;
using System.Collections;
public class FBXSeting : AssetPostprocessor
{
void OnPreprocessModel()
{
ModelImporter modelImporter = (ModelImporter)assetImporter;
if(assetImporter.assetPath.Contains(".fbx"))
{
modelImporter.globalScale = 1.0f;
modelImporter.generateMaterials = ModelImporterGenerateMaterials.None;
}
}
}
U3D有自动生成材质的功能(FbxImporter/Materials Generation,有3个选项可选),但我推荐使用脚本统一处理所有模型的材质。下面的代码抛砖引玉,通过菜单修改模型材质的颜色:
using UnityEditor;
using UnityEngine;
using System.Collections;
public class MaterialGeneration
{
[MenuItem("Actor/Generate Material")]
static void Execute()
{
foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets))
{
if (!(o is GameObject)) continue;
if (o.name.Contains("@")) continue;
//if (!AssetDatabase.GetAssetPath(o).Contains("/characters/")) continue;
GameObject charFbx = (GameObject)o;
foreach (SkinnedMeshRenderer smr in charFbx.GetComponentsInChildren<SkinnedMeshRenderer>(true))
{
smr.material.color = Color.red;
}
}
}
}
上面是处理人物材质的蒙皮网格的材质,对于场景模型,则改为修改MeshRenderer的数据。思路大致如此,细节以此类推。
根据本人自己的经验,将modelImporter.generateMaterials设为PerMaterial(支持多重材质),然后批处理Fbx模型的Mesh,找到其材质,并修改之(包括修改Shader及Shader数据)。不建议删除现有材质,然后自己创建材质,并赋予给相应的Mesh,因为这种做法有个不好的地方:U3D重启后,材质关联丢失。而前面的方法,只是修改Mesh所关联材质的数据,后者是修改关联。
思绪:
U3D虽然降低了游戏编程门槛,不过定制功能真心强大,继续探索中......
有些地方需要手动创建Prefab,可以通过以下代码实现代码批处理创建:
Object tempPrefab = EditorUtility.CreateEmptyPrefab("Assets/" + name + ".prefab");
tempPrefab = EditorUtility.ReplacePrefab(go, tempPrefab);
通过脚本给模型prefab添加AnimationEvent:
using UnityEditor; using UnityEngine; using System.IO; using System.Collections; using System.Collections.Generic; public class AnimationEventBatch { [MenuItem("Animation/AnimationEvent Batch")] static void Execute() { List<string> lstAnimName = new List<string>(); foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets)) { if (!(o is GameObject)) continue; if (o.name.Contains("@")) continue; if (o.name.Contains("anim") || o.name.Contains("ANIM")) continue; if (o.name.Contains("meta")) continue; GameObject charFbx = (GameObject)o; AnimationClip[] clips = AnimationUtility.GetAnimationClips(charFbx.animation); foreach(AnimationClip clip in clips) { if(clip.name.Contains("Take 0")) continue; List<AnimationEvent> events = new List<AnimationEvent>(AnimationUtility.GetAnimationEvents(clip)); if(HasStartEvent(events) && HasEndEvent(events)) continue; if(!HasStartEvent(events)) { AnimationEvent startEvent = new AnimationEvent(); startEvent.time = 0.0005f; startEvent.functionName = "StartCallBack"; events.Add(startEvent); } if(!HasEndEvent(events)) { AnimationEvent endEvent = new AnimationEvent(); endEvent.time = clip.length - 0.0005f; endEvent.functionName = "EndCallBack"; events.Add(endEvent); } AnimationUtility.SetAnimationEvents(clip, events.ToArray()); } EditorUtility.DisplayDialog("fbxname", clips[0].name, "OK"); } } static bool HasStartEvent(List<AnimationEvent> events) { foreach(AnimationEvent eventElem in events) { if(eventElem.functionName == "StartCallBack") return true; } return false; } static bool HasEndEvent(List<AnimationEvent> events) { foreach(AnimationEvent eventElem in events) { if(eventElem.functionName == "EndCallBack") return true; } return false; } }
上述代码仅供参考,代码中有几个注意事项:
(1)一定要在现有AnimationEvent[]数组的基础上添加,而不是新建一个这样的数组,然后Set给对应的AnimationClip,这样会导致现有的关键帧事件丢失;
(2)要避免重复添加同意关键帧事件(貌似u3d对于同样时间同样函数名的关键帧只会添加一次);
(3)可以看到,在添加关键帧事件时,只需要给出函数的名字,那么,在此动作执行时,U3D会检查这个GameObject身上的所有组件脚本,如果组件A包含此名字的函数,则会执行此函数。并且所有组件的此名字的函数都会执行一次。
批量设置图片的格式:
public class GuideUITextureProcess { [MenuItem("Editor/Texture/GuideUITexture")] static void Execute() { foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets)) { if (!(o is Texture)) continue; Texture tex = o as Texture; string path = AssetDatabase.GetAssetPath(tex); TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter; textureImporter.textureType = TextureImporterType.GUI; AssetDatabase.ImportAsset(path); } AssetDatabase.Refresh(); } }
Prefab.Apply操作的回调:
using UnityEngine; using UnityEditor; [InitializeOnLoad] public class PrefabExtension : MonoBehaviour { static PrefabExtension() { UnityEditor.PrefabUtility.prefabInstanceUpdated += OnPrefabInstanceUpdate; } static void OnPrefabInstanceUpdate(GameObject instance) { UnityEngine.Debug.Log("[Callback] Prefab.Apply on instance named :" + instance.name); GameObject prefab = UnityEditor.PrefabUtility.GetPrefabParent(instance) as GameObject; string prefabPath = AssetDatabase.GetAssetPath(prefab); UnityEngine.Debug.Log("@Prefab originPath=" + prefabPath); } }
继续探索中......