从0到1开发数字人:数字人动画预加载与avatar动态创建

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using Random = UnityEngine.Random;
using System.Linq;
//using UnityEditor.Animations;
using System.Reflection;
//using UnityEditor;
public class AnimationLoader : MonoBehaviour
{
public string localDataDirectory = “data/animators/”;
public string localDataDirectoryFileName = “data/animators/init.json”;
public List animationURLs = new List();
private List animatorControllers = new List();
private bool isPlaying = false;
private Animator animator;

private void Start()
{
    animator = GetComponent<Animator>();
    LoadInitialAnimationUrls();
    if (animationURLs.Count > 0)
    {
        StartCoroutine(LoadAnimations());
    }
}
public string GetBaseDir()
{
    if (Application.platform == RuntimePlatform.Android)
        return Application.persistentDataPath;
    return Application.dataPath;
}
private void LoadInitialAnimationUrls()
{
    string filePath = Path.Combine(GetBaseDir(), localDataDirectoryFileName);
    Debug.LogError($"local {filePath}");
    if (File.Exists(filePath))
    {
        string json = File.ReadAllText(filePath);
        animationURLs = JsonUtility.FromJson<UrlList>(json).urls;
    }
    LoadDefaultInitialAnimationUrls();
}

private void LoadDefaultInitialAnimationUrls()
{
    string defaultAnimationsPath = Path.Combine(Application.streamingAssetsPath, "anims");
    string[] defaultAnimationFiles = Directory.GetFiles(defaultAnimationsPath, "*.anim");

    List<string> defaultUrls = new List<string>();
    foreach (string file in defaultAnimationFiles)
    {
        string url = file;//"file://" + 
        defaultUrls.Add(url);
    }
    if (animationURLs == null)
        animationURLs = new List<string>();

    if(defaultUrls!=null&&defaultUrls.Count>0)
    {
        animationURLs.AddRange(defaultUrls);
        Debug.LogError("添加默认动画成功");
    }

}
public void StartAnimation(Animator animator)
{
    this.animator = animator;
    isPlaying = true;
    StartCoroutine(PlayAnimations());
}
public void StartAnimation()
{
    isPlaying = true;
    StartCoroutine(PlayAnimations());
}

public void StopAnimation()
{
    isPlaying = false;
    StopCoroutine(PlayAnimations());
}

private IEnumerator LoadAnimations()
{
    foreach (string url in animationURLs)
    {
        string localPath = GetLocalPath(url);
        if (File.Exists(localPath))
        {
            yield return StartCoroutine(LoadAnimationFromLocal(localPath));
        }
        else
        {
            yield return StartCoroutine(DownloadAnimation(url, localPath));
        }
    }
}

private IEnumerator LoadAnimationFromLocal(string localPath)
{
    var localLoadRequest = AssetBundle.LoadFromFileAsync(localPath);
    yield return localLoadRequest;

    if (localLoadRequest.assetBundle != null)
    {
        var controller = localLoadRequest.assetBundle.LoadAsset<RuntimeAnimatorController>("AnimatorController");
        if (controller != null)
        {
            var clips = localLoadRequest.assetBundle.LoadAllAssets<AnimationClip>();
            var item = new AnimatorControllerItem(controller, clips);
            animatorControllers.Add(item);
        }
        localLoadRequest.assetBundle.Unload(false);
    }
}

private IEnumerator DownloadAnimation(string url, string localPath)
{
    using (UnityWebRequest www = UnityWebRequest.Get(url))
    {
        yield return www.SendWebRequest();

        if (www.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError("Failed to download animation: " + www.error);
        }
        else
        {
            File.WriteAllBytes(localPath, www.downloadHandler.data);
            yield return StartCoroutine(LoadAnimationFromLocal(localPath));
        }
    }
}

private string GetLocalPath(string url)
{
    if (url.ToLower().StartsWith("http"))//本地文件,直接返回
    {
        Uri uri = new Uri(url);
        string path = uri.AbsolutePath.TrimStart('/');
        return Path.Combine(GetBaseDir(), localDataDirectory, path);
    }
    return url.Replace("file://", "");
}

private IEnumerator PlayAnimations()
{
    while (isPlaying)
    {
        if (animatorControllers.Count == 0)
        {
            yield return new WaitForSeconds(3);
            continue;
        }

        AnimatorControllerItem item = animatorControllers[Random.Range(0, animatorControllers.Count)];
        var dur = item.GetCurrentClipLength()+6;
        item.PlayAnimator(animator);

        yield return new WaitForSeconds(dur);

        ShuffleAnimatorControllers();
    }
}

private void ShuffleAnimatorControllers()
{
    for (int i = 0; i < animatorControllers.Count; i++)
    {
        AnimatorControllerItem temp = animatorControllers[i];
        int randomIndex = Random.Range(i, animatorControllers.Count);
        animatorControllers[i] = animatorControllers[randomIndex];
        animatorControllers[randomIndex] = temp;
    }
}

private void Update()
{
    if (Input.GetKeyDown(KeyCode.S))
    {
        StartAnimation();
    }
    else if (Input.GetKeyDown(KeyCode.T))
    {
        StopAnimation();
    }
}

}

[System.Serializable]
public class UrlList
{
public List urls;
}

public class AnimatorControllerItem
{
public RuntimeAnimatorController controller;

public AnimationClip[] Clips { get; }

public string[] ClipNames;
private string clipName;

public AnimatorControllerItem(RuntimeAnimatorController controller)
{
    this.controller = controller;


}

public AnimatorControllerItem(RuntimeAnimatorController controller, AnimationClip[] clips) : this(controller)
{

    Clips = clips;
    //GetStateNames(controller);
    ClipNames = GetClipNames();// clips.Select(p=>p.name).ToArray();

    if (ClipNames == null|| ClipNames.Length==0)
    {
        ClipNames = new string[] { "Idle", "Talking1", "Idle", "Talking1", "Idle", "Talking1", "Idle", "Walking", "Idle" };//Talking2 Talking3
    }
    string josnString = String.Join(" ", ClipNames);
    Debug.LogError(clips.Length + " " + josnString);
   // FixAnimationClipSettings(controller);

}

private string[] GetClipNames()
{
    return statesNames.ToArray();
}

public void PlayAnimator(Animator animator)
{
    //GetCurrentClipLength 执行這个函数后执行
    animator.runtimeAnimatorController = controller;
    //animator.CrossFade("Walking",0.2f,0,0);
    Debug.LogError("playing "+ clipName);
    //animator.Play(clipName); //Walking Idle
    animator.CrossFade(clipName, 0.2f, 0, 0);
}

public float GetCurrentClipLength()
{
    if (controller != null&& ClipNames!=null&& ClipNames.Count()>0)
    {
        clipName = ClipNames[Random.Range(0, ClipNames.Length)];
        var clips = Clips.Where(p => p.name == clipName).FirstOrDefault();
        if (clips != null)
        {
            return clips.length;
        }
    }
    return 0;
}
public List<string> statesNames = new List<string>();

//private string[] GetClipNames(RuntimeAnimatorController controller)
//{
//    AnimatorOverrideController overrideController = controller as AnimatorOverrideController;
//    Debug.LogError($"{overrideController}");
//    List<string> clipNames = new List<string>();
//    foreach (AnimationClip clip in controller.animationClips)
//    {
//        // 如果有修改后的别名,则使用别名,否则使用原始名称
//        string clipName = clip.name;

//        if (overrideController != null)
//        {
//            clipName = overrideController[clip].name;
//        }
//        clipNames.Add(clipName);
//    }
//    return clipNames.ToArray();
//}

}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值