Импорт анимации из Blender

Импорт текстур, моделей, звуков и пр.

Импорт анимации из Blender

Сообщение bgeyts667 25 авг 2010, 09:36

Как создать анимации в Blender так, чтобы при импорте в Unity они существовали отдельно и можно было запускать их посредством Java Script?
_bgeyts667@gmail.com
Аватара пользователя
bgeyts667
UNITрон
 
Сообщения: 175
Зарегистрирован: 25 авг 2010, 08:30
  • ICQ

Re: Импорт анимации из Blender

Сообщение Neodrop 25 авг 2010, 10:26

Так же, как где угодно - экспортируем в FBX модель, добавляя к имени собаку @walk.fbx к примеру
Тогда после импорта в двиг, этот файл будет просто анимацией.
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Импорт анимации из Blender

Сообщение Mahamed9628 05 сен 2010, 18:35

Спасибо! Именно то, что нужно.
Mahamed9628
UNец
 
Сообщения: 19
Зарегистрирован: 05 авг 2010, 12:55

Re: Импорт анимации из Blender

Сообщение Parhelion 07 сен 2010, 15:42

Проблема с импортом анимации персонажа. Не хочется плодить темы поэтому спрошу здесь.

Есть .blend-файл в котором хранится анимация пероснажа. Решено было разделить анимацию на "верх"(торс, руки, голова) и "низ" (таз, ноги). Т.е скелет один, но в одной анимации ключи проставлены только для верха, а в другой отдельной анимации ключи проставлены только для низа. Затем эти анимации предполагается смешивать программно.

Проблема собственно в том что в блендере все ок. Но при импорте .blend-файла Юнити проставляет всем костям ключи (0,0,0 - для tranform и rotation, 1,1,1 - scale).
Так вот эти ключи мешают номарльному смешиванию анимаций верха и низа =(.
Их можно руками удалять уже в юнити в редакторе анимаций, но это долго и придется не один раз делать.

Может я где-то туплю? Может есть какие-то способы смешивания хитрые. По идее Additive должен работать, но почему-то не хочет. Заранее спасибо.
Parhelion
UNец
 
Сообщения: 10
Зарегистрирован: 08 май 2010, 10:26

Re: Импорт анимации из Blender

Сообщение Paul Siberdt 07 сен 2010, 20:58

Думаю, это не Юня ставит ключи, а экспортер варит анимацию покадрово. Поищите флажок в настройках экспорта, а лучше пользуйтесь форматом FBX

Насчет аддитива - да, одной из первых проблем, с которой я столкнулся в Unity - это некорректное адиттивное смешивание анимаций. На сим бросил это занятие. Риквест с примером пылится в ящиках Юнетковцев. :D
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт

Re: Импорт анимации из Blender

Сообщение Parhelion 08 сен 2010, 12:48

fbx я конечно пробовал, перебрал все настройки - нифига. А анимация видимо действительно запекается покадрово. Несмотря на то что редактор анимаций в юнити показывает что ключи стоят только в первом и последнем кадре. Это уже видимо работа оптимизатора.
Неужели никто не смешивал подобным образом анимации? Был бы благодарен за пример.
Parhelion
UNец
 
Сообщения: 10
Зарегистрирован: 08 май 2010, 10:26

Re: Импорт анимации из Blender

Сообщение AndreyMust19 27 июл 2011, 23:13

экспортируем в FBX модель, добавляя к имени собаку @walk.fbx к примеру

А нельзя сохранить в отдельный файл только анимацию? Во всех FBX-файлах с @ кроме анимации лежит модель и скелет, оттого они и весят столько же, сколько сам персонаж.
Можно сохранить несколько анимаций в файл?
Нужна помощь? Сами, сами, сами, сами, сами... делаем все сами
AndreyMust19
Адепт
 
Сообщения: 1119
Зарегистрирован: 07 июн 2011, 13:19

Re: Импорт анимации из Blender

Сообщение Zaicheg 27 июл 2011, 23:23

А нельзя сохранить в отдельный файл только анимацию? Во всех FBX-файлах с @ кроме анимации лежит модель и скелет, оттого они и весят столько же, сколько сам персонаж.

Нельзя. Хотя после импорта вы можете раскрыть модель-ассет, выбрать аним. клип, нажать Ctrl+D (дублировать) и получить клип отдельно от модели (модель можно удалить).

Можно сохранить несколько анимаций в файл?

Можно. Потом порезать при импорте в юнити. Описано в справке -- в мануале, в разделе по импорту анимаций.
Дьяченко Роман
e-mail: _zaicheg.reg@gmail.com
skype: zaicheg12
vkontakte: _vk.com/zaichegq
Работа: _wie3.com _www.sanviz.com
Аватара пользователя
Zaicheg
Адепт
 
Сообщения: 3024
Зарегистрирован: 19 июн 2009, 15:12
Откуда: Череповец

Re: Импорт анимации из Blender

Сообщение Neodrop 27 июл 2011, 23:51

Можно сохранить в отдельный файл. Но не из Блендера. Прямо из Unity
Я выкладывал тут на форуме скрипт-экспортёр.
Или можно качнуть Antares Project (не путать с Universe) - там есть.
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Импорт анимации из Blender

Сообщение seaman 27 июл 2011, 23:54

Можно посмотреть CharacterCustomization. Там есть скрипт, который все лишнее, кроме анимации удаляет при импорте модели:
Синтаксис:
Используется csharp
    // This method is called immediately after importing an FBX.
    void OnPostprocessModel(GameObject go)
    {
        if (!assetPath.Contains("/characters/")) return;

        // Assume an animation FBX has an @ in its name,
        // to determine if an fbx is a character or an animation.
        if (assetPath.Contains("@"))
        {
            // For animation FBX's all unnecessary Objects are removed.
            // This is not required but improves clarity when browsing assets.

            // Remove SkinnedMeshRenderers and their meshes.
            foreach (SkinnedMeshRenderer smr in go.GetComponentsInChildren<SkinnedMeshRenderer>())
            {
                Object.DestroyImmediate(smr.sharedMesh, true);
                Object.DestroyImmediate(smr.gameObject);
            }

            // Remove the bones.
            foreach (Transform o in go.transform)
                Object.DestroyImmediate(o);
        }
    }
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Импорт анимации из Blender

Сообщение lazykiller 28 июл 2011, 13:08

хотел сделать отрезалку анимации потом узнал что такая есть в антаресе, решил переделать для своих нужд. код кривоватый, но работает стабильно. корутины тогда ещё не начал изучать посему кажется, что всё зависло и умерло. по-завершению в папке с анимациями 2 текстовых файла один список анимации(можно загружать в массив) второй - отчёт. после отрезания анимаций юнька некоторое время будет импортировать файлы этих анимаций. также сделал добавление ВСЕХ анимаций из выбранной папки на объект. вобщем вот код.


Синтаксис:
Используется csharp
//Created by Neodrop
//Batch Extract/Attach by Tsar4k
//neodrop@unity3d.ru
// Based on http://answers.unity3d.com/questions/65 ... -animation

using UnityEditor;
using UnityEngine;

class AnimationTools4k : MonoBehaviour
{
    const string duplicatePostfix = ""; // "_copy";

    static void CopyClip(string importedPath, string copyPath)
    {
        AnimationClip src = AssetDatabase.LoadAssetAtPath(importedPath, typeof(AnimationClip)) as AnimationClip;
        AnimationClip newClip = new AnimationClip();
        newClip.name = src.name + duplicatePostfix;
        AssetDatabase.CreateAsset(newClip, copyPath);
        AssetDatabase.Refresh();
    }


    static void ExtractAnimationsCopyClip(AnimationState state, string newName, string copyPath)
    {
        // Get selected AnimationClip
        AnimationClip imported = state.clip as AnimationClip;
        if (imported == null)
        {
            Debug.Log("Selected object is not an AnimationClip");
            return;
        }

        // Find path of copy
        string importedPath = AssetDatabase.GetAssetPath(imported);
        copyPath += "/" + newName + ".anim";

       
        CopyClip(importedPath, copyPath);      
       
       
        AnimationClip src = AssetDatabase.LoadAssetAtPath(importedPath, typeof(AnimationClip)) as AnimationClip;
        AnimationClip newClip = new AnimationClip();
        newClip.name = src.name + duplicatePostfix;
        AssetDatabase.CreateAsset(newClip, copyPath);
//        AssetDatabase.Refresh();


        AnimationClip copy = AssetDatabase.LoadAssetAtPath(copyPath, typeof(AnimationClip)) as AnimationClip;
        if (copy == null)
        {
            Debug.Log("No copy found at " + copyPath);
            return;
        }
        // Copy curves from imported to copy
        AnimationClipCurveData[] curveDatas = AnimationUtility.GetAllCurves(imported, true);
        for (int i = 0; i < curveDatas.Length; i++)
        {
            AnimationUtility.SetEditorCurve(
                copy,
                curveDatas[i].path,
                curveDatas[i].type,
                curveDatas[i].propertyName,
                curveDatas[i].curve
            );
        }
    }




    [MenuItem("Assets/Animation Tools/Extract All Animations To Folder")]
    static void ExtractAnimations()
    {
        System.IO.DirectoryInfo dif = new System.IO.DirectoryInfo(Application.dataPath.Replace("Assets", "") + AssetDatabase.GetAssetPath(Selection.activeObject));
        System.IO.FileInfo[] finfo = dif.GetFiles("*.fbx");

        if (finfo.Length == 0)        
        {
            Debug.Log(".FBX files not found in selected folder");
            return;
        }

        string folderForAnimation = Application.dataPath.Replace("Assets", "") + AssetDatabase.GetAssetPath(Selection.activeObject) + "_AnimationsOnly";
        System.IO.Directory.CreateDirectory(folderForAnimation);
        string copyPathFolder;
/*
       
        copyPathFolder = EditorUtility.OpenFolderPanel("Select folder for extract .anim from .FBX", folderForAnimation, "");
        if (copyPathFolder == "") { return; };
        Debug.Log(copyPathFolder);

*/

        copyPathFolder =  AssetDatabase.GetAssetPath(Selection.activeObject) + "_AnimationsOnly";


        AssetDatabase.Refresh();

        int unusedPath = Application.dataPath.Length - 6;


        System.Collections.Generic.List<string> animationsToLoad = new System.Collections.Generic.List<string>();
        System.Collections.Generic.List<string> animationsDublicate = new System.Collections.Generic.List<string>();
        System.Collections.Generic.List<string> animationsToLoadLog = new System.Collections.Generic.List<string>();
        System.Collections.Generic.List<string> filesWitoutAnimations = new System.Collections.Generic.List<string>();

        int animationsCounFull = 0;
        for (int i = 0; i < finfo.Length; i++)
        {
            GameObject currentFbx = AssetDatabase.LoadAssetAtPath(finfo[i].FullName.Remove(0, unusedPath), typeof(GameObject)) as GameObject;

            animationsToLoadLog.Add("File     " + i + " " + finfo[i].FullName);
            animationsToLoadLog.Add("");
           
            int animationsCounLocal = 0;
            foreach (AnimationState state in currentFbx.GetComponent<Animation>())
            {

                string newName = state.name;

                if (state.name.StartsWith("Take "))
                {
                    newName = currentFbx.name + "_" + state.name;
                }


                string animationHolder = Application.dataPath.Replace("Assets", "") + AssetDatabase.GetAssetPath(state.clip);
               
                if (System.IO.Path.GetFileName(finfo[i].FullName) == System.IO.Path.GetFileName(animationHolder))
                {
                    ExtractAnimationsCopyClip(state, newName, copyPathFolder);
                    animationsToLoadLog.Add("   +Anim " + animationsCounLocal + " " + newName);
                    animationsToLoad.Add(newName);
                    animationsCounLocal++;
                }
                else
                {
                    animationsToLoadLog.Add("   -Anim " + animationsCounLocal + " " + newName);
                    animationsToLoadLog.Add("    realFile   " + System.IO.Path.GetFileName(animationHolder));
                    animationsDublicate.Add(newName);
                    animationsCounLocal++;
                }
                animationsToLoadLog.Add("");
                animationsToLoadLog.Add("");
                //     Debug.Log(newName);
            }
            if (animationsCounLocal == 0)
            {
                filesWitoutAnimations.Add(System.IO.Path.GetFileName(finfo[i].FullName));
            }
            animationsCounFull += animationsCounLocal;
        }

        animationsToLoad.Sort();
        animationsDublicate.Sort();


        System.IO.StreamWriter animationsFileStream = new System.IO.StreamWriter(copyPathFolder + "/_AnimationsToLoadList.txt");
        foreach (string animationName in animationsToLoad)
        {
            animationsFileStream.WriteLine(animationName);
        }
        animationsFileStream.Close();


        animationsFileStream = new System.IO.StreamWriter(copyPathFolder + "/_AnimationsExtractorLog.txt");
        foreach (string animationName in animationsToLoadLog)
        {
            animationsFileStream.WriteLine(animationName);
        }

        animationsFileStream.WriteLine("");
        animationsFileStream.WriteLine("Total Animations Checked " + animationsCounFull);
        animationsFileStream.WriteLine("Total Animations Exported " + animationsToLoad.Count + " see _AnimationsToLoadList.txt file");
        animationsFileStream.WriteLine("");
        animationsFileStream.WriteLine("Dublicates " + animationsDublicate.Count);
        animationsFileStream.WriteLine("Dublicate List");
        animationsFileStream.WriteLine("");

        foreach (string animationName in animationsDublicate)
        {
            animationsFileStream.WriteLine(animationName);
        }

        animationsFileStream.WriteLine("");
        animationsFileStream.WriteLine("Total FBX Files Checked " + finfo.Length);
        animationsFileStream.WriteLine("Without Animations " + filesWitoutAnimations.Count);
        animationsFileStream.WriteLine("");
        animationsFileStream.WriteLine("Files without Animations List");
        animationsFileStream.WriteLine("");

        foreach (string fileName in filesWitoutAnimations)
        {
            animationsFileStream.WriteLine(fileName);
        }


        animationsFileStream.Close();

        AssetDatabase.Refresh();

    }



    [MenuItem("Assets/Animation Tools/UnLink Animation", true)]
    static bool CopyCurvesToDuplicateValidator()
    {
        return Selection.activeObject.GetType() == typeof(AnimationClip);
    }



    [MenuItem("Assets/Animation Tools/UnLink Animation")]
    static void CopyCurvesToDuplicate()
    {
        // Get selected AnimationClip
        AnimationClip imported = Selection.activeObject as AnimationClip;
        if (imported == null)
        {
            Debug.Log("Selected object is not an AnimationClip");
            return;
        }

        // Find path of copy
        string importedPath = AssetDatabase.GetAssetPath(imported);
        string copyPath = importedPath.Substring(0, importedPath.LastIndexOf("/"));
        copyPath += "/" + imported.name + ".anim";

        CopyClip(importedPath, copyPath);
       
        AnimationClip copy = AssetDatabase.LoadAssetAtPath(copyPath, typeof(AnimationClip)) as AnimationClip;
        if (copy == null)
        {
            Debug.Log("No copy found at " + copyPath);
            return;
        }
        // Copy curves from imported to copy
        AnimationClipCurveData[] curveDatas = AnimationUtility.GetAllCurves(imported, true);
        for (int i = 0; i < curveDatas.Length; i++)
        {
            AnimationUtility.SetEditorCurve(
                copy,
                curveDatas[i].path,
                curveDatas[i].type,
                curveDatas[i].propertyName,
                curveDatas[i].curve
            );
        }
    }



    [MenuItem("Assets/Animation Tools/Attach All Animations From Folder")]
    static void AttachAllAnimations()
    {
        GameObject gameObjectToAnimate = Selection.activeObject as GameObject;
        if (gameObjectToAnimate == null)
        {
            Debug.Log("Selected object is not an GameObject");
            return;
        }

        if (gameObjectToAnimate.GetComponent<Animation>() == null)
        {
            Debug.Log("Selected object is GameObject but not have Animation component (to add do: Component -> Miscellanious -> Animation)");
            return;
        }


        string animationFolderPath = EditorUtility.OpenFolderPanel("Load .anim of Directory", Application.dataPath, "");
        if (animationFolderPath == "") { return; };

        System.IO.DirectoryInfo dif = new System.IO.DirectoryInfo(animationFolderPath);
        System.IO.FileInfo[] finfo = dif.GetFiles("*.anim");
       
        if (finfo.Length == 0)
        {
            Debug.Log(".anim files not found in selected folder");
            return;
        }


        int unusedPath = Application.dataPath.Length - 6;

        for (int i = 0; i < finfo.Length; i++)
        {
            AnimationClip currentClip = AssetDatabase.LoadAssetAtPath(finfo[i].FullName.Remove(0, unusedPath), typeof(AnimationClip)) as AnimationClip;
            gameObjectToAnimate.animation.AddClip(currentClip, currentClip.name);
            Debug.Log(i+" - animation "+ currentClip.name + " added");
            AssetDatabase.Refresh();
        }
       
    }

}


зы работает только для *.FBX
Аватара пользователя
lazykiller
UNец
 
Сообщения: 17
Зарегистрирован: 18 июл 2011, 17:44

Re: Импорт анимации из Blender

Сообщение Morphine 23 сен 2011, 18:54

После импорта анимации из Блендера вылезла проблема: при проигрывании анимации рук некорректно отображается часть руки на сгибе пальцев. Без анимации руки нормально отображаются, можно двигать кости, с привязкой тоже все отлично. Подскажите в чем может быть проблема и как ее решить.
У вас нет доступа для просмотра вложений в этом сообщении.
Morphine
UNец
 
Сообщения: 8
Зарегистрирован: 26 май 2010, 21:35

Re: Импорт анимации из Blender

Сообщение seaman 23 сен 2011, 21:17

В блендере так же? По рисунку кажется что либо кривой скининг, либо просто мало поликов на сгибе.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Импорт анимации из Blender

Сообщение Morphine 23 сен 2011, 21:25

seaman писал(а):В блендере так же? По рисунку кажется что либо кривой скининг, либо просто мало поликов на сгибе.

Нет, в блендере все отлично.. Это после импорта в юнити такая хрень вылазит
Morphine
UNец
 
Сообщения: 8
Зарегистрирован: 26 май 2010, 21:35

Re: Импорт анимации из Blender

Сообщение seaman 23 сен 2011, 21:48

Второй вариант - там квад, а не два трианла и Юнити его делит на трианглы не так как блендер - не там диагональ делает. Разделите в блендере вручную.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

След.

Вернуться в Медиа

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1