Last active
April 15, 2021 09:54
-
-
Save GeorgiyRyaposov/94796f20901e896d899396db92d99187 to your computer and use it in GitHub Desktop.
Unity models imported with animation import
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Assets.Editor | |
{ | |
public class ModelsImporter : AssetPostprocessor | |
{ | |
private void OnPreprocessModel() | |
{ | |
var modelImporter = assetImporter as ModelImporter; | |
if (modelImporter == null) | |
{ | |
Debug.LogError("Error during import of models: ModelImporter is null"); | |
return; | |
} | |
modelImporter.isReadable = false; | |
modelImporter.importMaterials = false; | |
if (modelImporter.assetPath.Contains("Locations")) | |
{ | |
ImportLocationRelatedItem(modelImporter); | |
} | |
if (modelImporter.assetPath.Contains("Skins")) | |
{ | |
ImportSkinRelatedItem(modelImporter); | |
} | |
} | |
private void ImportSkinRelatedItem(ModelImporter modelImporter) | |
{ | |
modelImporter.resampleCurves = false; | |
var animClips = modelImporter.clipAnimations; | |
if (animClips.Length < 3) | |
{ | |
animClips = new ModelImporterClipAnimation[3]; | |
animClips[0] = new ModelImporterClipAnimation | |
{ | |
name = "Walk", | |
firstFrame = 1, | |
lastFrame = 30, | |
loopTime = true | |
}; | |
animClips[1] = new ModelImporterClipAnimation { | |
name = "Balancing", | |
firstFrame = 31, | |
lastFrame = 75, | |
loopTime = true | |
}; | |
animClips[2] = new ModelImporterClipAnimation { | |
name = "Idle", | |
firstFrame = 76, | |
lastFrame = 200, | |
loopTime = true | |
}; | |
modelImporter.clipAnimations = animClips; | |
} | |
var skinsContainer = Resources.Load<SkinsContainer>("Data/SkinsContainer"); | |
if (skinsContainer == null) | |
{ | |
Debug.LogError("Failed to find skinsContainer"); | |
return; | |
} | |
AssetDatabase.StartAssetEditing(); | |
var skinObj = AssetDatabase.LoadAssetAtPath<Object>(modelImporter.assetPath); | |
var prefabInstance = (GameObject)GameObject.Instantiate(skinObj); | |
if (prefabInstance == null) | |
{ | |
Debug.LogError("Failed to initialize prefab " + modelImporter.assetPath); | |
return; | |
} | |
if (prefabInstance.GetComponent<CubeMeshHelper>() == null) | |
{ | |
prefabInstance.AddComponent<CubeMeshHelper>(); | |
} | |
var animator = prefabInstance.GetComponent<Animator>(); | |
if (animator != null) | |
{ | |
var controllerPath = Path.ChangeExtension(modelImporter.assetPath, "controller"); | |
var controller = AssetDatabase.LoadAssetAtPath<AnimatorController>(controllerPath); | |
if (controller == null) | |
{ | |
var animationClips = new List<AnimationClip>(); | |
Object[] objects = AssetDatabase.LoadAllAssetsAtPath(assetPath); | |
foreach (Object obj in objects) | |
{ | |
AnimationClip clip = obj as AnimationClip; | |
if (clip != null) | |
{ | |
animationClips.Add(clip); | |
} | |
} | |
// Creates the controller | |
controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath(controllerPath); | |
var rootStateMachine = controller.layers[0].stateMachine; | |
var idleState = rootStateMachine.AddState("Idle"); | |
idleState.motion = animationClips.FirstOrDefault(c => c.name.ToLower() == "idle"); | |
var walkState = rootStateMachine.AddState("Walk"); | |
walkState.motion = animationClips.FirstOrDefault(c => c.name.ToLower() == "walk"); | |
var balancingState = rootStateMachine.AddState("Balancing"); | |
balancingState.motion = animationClips.FirstOrDefault(c => c.name.ToLower() == "balancing"); | |
} | |
animator.runtimeAnimatorController = controller; | |
} | |
if (prefabInstance.GetComponentInChildren<CubeObstacle>() == null) | |
{ | |
var collectable = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/Prefabs/CollectableCube.prefab"); | |
var collectableInstance = PrefabUtility.InstantiatePrefab(collectable) as GameObject; | |
if (collectableInstance == null) | |
{ | |
Debug.LogError("Failed to find collectable prefab"); | |
return; | |
} | |
collectableInstance.transform.SetParent(prefabInstance.transform); | |
collectableInstance.transform.localPosition = Vector3.zero; | |
} | |
var renderer = prefabInstance.GetComponentInChildren<SkinnedMeshRenderer>(); | |
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; | |
renderer.receiveShadows = false; | |
renderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off; | |
renderer.useLightProbes = false; | |
var playerMaterial = AssetDatabase.LoadAssetAtPath<Material>("Assets/Materials/Player.mat"); | |
if (playerMaterial == null) | |
Debug.LogError("Failed to load player material"); | |
else | |
renderer.sharedMaterial = playerMaterial; | |
var prefab = PrefabUtility.CreatePrefab(Path.ChangeExtension(modelImporter.assetPath, "prefab"), prefabInstance, ReplacePrefabOptions.Default); | |
Object.DestroyImmediate(prefabInstance); | |
var skinGroupName = Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(modelImporter.assetPath))); | |
if (string.IsNullOrEmpty(skinGroupName)) | |
{ | |
Debug.LogError("failed to find skin grouper directory"); | |
return; | |
} | |
var modelName = Path.ChangeExtension(Path.GetFileName(modelImporter.assetPath), string.Empty); | |
modelName = modelName.Remove(modelName.Length-1); //remove dot at end | |
var skinGroup = skinsContainer.skinsData.FirstOrDefault(s => s.name.ToLower() == skinGroupName.ToLower()); | |
if (skinGroup != null) | |
{ | |
var skinData = skinGroup.skins.FirstOrDefault(sd => sd.skinPrefab == prefab || sd.name == modelName); | |
if (skinData == null) | |
{ | |
skinGroup.skins.Add(new SkinData | |
{ | |
name = modelName, | |
skinPrefab = prefab | |
}); | |
} | |
else | |
{ | |
skinData.skinPrefab = prefab; | |
} | |
EditorUtility.SetDirty(skinsContainer); | |
} | |
var pool = GameObject.FindObjectOfType<ObjectPool>(); | |
pool.CreatePoolFromEditor(prefab, 5); | |
AssetDatabase.StopAssetEditing(); | |
AssetDatabase.SaveAssets(); | |
} | |
private void ImportLocationRelatedItem(ModelImporter modelImporter) | |
{ | |
var themesContainer = Resources.Load<ThemesContainer>("Data/ThemesContainer"); | |
if (themesContainer == null) | |
{ | |
Debug.LogError("Failed to find themesContainer"); | |
return; | |
} | |
var stageName = Path.GetFileName(Path.GetDirectoryName(modelImporter.assetPath)); | |
if (string.IsNullOrEmpty(stageName)) | |
{ | |
Debug.LogError("Failed to find directory name of " + modelImporter.assetPath); | |
return; | |
} | |
if (stageName.ToLower() == "topstuff") | |
{ | |
stageName = Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(modelImporter.assetPath))); | |
if (string.IsNullOrEmpty(stageName)) | |
{ | |
Debug.LogError("Failed to find directory name of " + modelImporter.assetPath); | |
return; | |
} | |
} | |
stageName = stageName.ToLower(); | |
//Debug.Log(stageName); | |
var modelName = Path.ChangeExtension(Path.GetFileName(modelImporter.assetPath), string.Empty); | |
var modelPath = modelImporter.assetPath; | |
//Debug.Log(modelPath); | |
//Debug.Log("modelName " + modelName); | |
var model = AssetDatabase.LoadAssetAtPath<GameObject>(modelPath); | |
if (model == null) | |
{ | |
Debug.LogError("Failed to find model at path: " + modelPath); | |
return; | |
} | |
var meshFilter = model.GetComponent<MeshFilter>(); | |
var foundType = false; | |
var themeType = TryGetThemeByPath(modelImporter.assetPath, out foundType); | |
if (!foundType) | |
return; | |
var themeContainer = themesContainer.themesData.FirstOrDefault(t => t.themeType == themeType); | |
if (themeContainer == null) | |
{ | |
Debug.LogError("Failed to find type: " + themeType); | |
return; | |
} | |
ThemeStageData themeStageData = null; | |
foreach (var stageData in themeContainer.themeStagesData) | |
{ | |
if (stageData.themeStageName.ToLower() == stageName) | |
{ | |
themeStageData = stageData; | |
break; | |
} | |
} | |
if (themeStageData == null) | |
{ | |
themeStageData = new ThemeStageData { themeStageName = stageName }; | |
AddNewObjToArray(ref themeContainer.themeStagesData, themeStageData); | |
} | |
AddMeshToStageData(themeStageData, modelName, meshFilter.sharedMesh); | |
EditorUtility.SetDirty(themesContainer); | |
} | |
private static void AddMeshToStageData(ThemeStageData data, string modelName, Mesh mesh) | |
{ | |
if (modelName.StartsWith("Cube2")) | |
{ | |
AddMeshToArray(ref data.cubes2, mesh); | |
} | |
else if (modelName.StartsWith("Cube3")) | |
{ | |
AddMeshToArray(ref data.cubes3, mesh); | |
} | |
else if (modelName.StartsWith("Cube4")) | |
{ | |
data.cube4 = mesh; | |
} | |
else if (modelName.StartsWith("Cube5")) | |
{ | |
data.cube5 = mesh; | |
} | |
else if (modelName.StartsWith("Cube6")) | |
{ | |
AddMeshToArray(ref data.cubes6, mesh); | |
} | |
else if (modelName.StartsWith("Cube8")) | |
{ | |
data.cube8 = mesh; | |
} | |
else | |
{ | |
AddMeshToArray(ref data.topStuff, mesh); | |
} | |
} | |
private static void AddMeshToArray(ref Mesh[] meshes, Mesh mesh) | |
{ | |
if (meshes == null) | |
{ | |
meshes = new Mesh[1]; | |
meshes[0] = mesh; | |
return; | |
} | |
foreach (var oldMesh in meshes) | |
{ | |
if (oldMesh.name == mesh.name) | |
{ | |
//replace?... | |
//meshes[System.Array.IndexOf(meshes, oldMesh)] = mesh; | |
return; | |
} | |
} | |
AddNewObjToArray(ref meshes, mesh); | |
} | |
private static void AddNewObjToArray<T>(ref T[] objectsArray, T newObj) | |
{ | |
System.Array.Resize<T>(ref objectsArray, objectsArray.Length + 1); | |
objectsArray[objectsArray.Length - 1] = newObj; | |
} | |
private static ThemeType TryGetThemeByPath(string path, out bool success) | |
{ | |
if (path.Contains(ThemeType.Canyon.ToString().ToLower())) | |
{ | |
success = true; | |
return ThemeType.Canyon; | |
} | |
Debug.LogError("failed to find theme by path " + path); | |
success = false; | |
return ThemeType.Canyon; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment