【问题标题】:Optimizing animations to show dozens or even hundreds on mobile in Unity优化动画以在 Unity 中在移动设备上显示数十个甚至数百个
【发布时间】:2016-12-11 09:10:21
【问题描述】:

最近我一直致力于在 Unity 中制作城堡战斗游戏。我得到了一些动画士兵模型,并计划在场景中有几百个。问题是,在移动设备上,如果 FPS 低于 20,我什至无法一次显示 50。我已经在 Unity 的论坛上问过这个问题,但没有回复:(

这里是链接,您可以看到到目前为止我为优化它们所做的工作:https://forum.unity3d.com/threads/playing-hundreds-of-animations-on-mobile.444599/

我从未见过有几十个动画在移动设备上的游戏。我见过的最接近的是Fifa Mobile,但那只有20-30左右。

您认为有可能比我优化更多的动画(如链接所示),还是无法在移动设备上拥有数百个动画?

感谢您分享您的知识!

【问题讨论】:

  • 要提高渲染速度,您需要为您的游戏量身定制优化代码。为此,您需要使用 Java 等编译语言从头开始编写游戏。
  • @Blindman67 用 Ja​​va 创建游戏真的不是我的事。蒙皮网格渲染器在移动设备上如此困难,我感到非常惊讶和失望,但我想它们有点复杂。我想我得试试另一个项目。
  • Gee 蒙皮网格。有很多问题要问,尝试使用静态构成的网格。应该能够拍摄蒙皮网格的快照,然后按顺序渲染它们以制作动画。您还应该测试设备的限制,您想要的帧速率下的最大多边形数是多少,可以使用多少空闲 GPU RAM,瓶颈在哪里(GPU / CPU)。了解这些信息将帮助您弄清楚如何克服它们。不要失望,我开始玩游戏时,家用 PC 很难绘制 4 个两种颜色的精灵,但通过一些技巧,整支军队都可以在屏幕上前进。总有办法。
  • 在 Unity 的“添加组件”菜单中没有静态姿势网格这样的想法,但这听起来正是我需要的:(
  • 我不知道他们会怎么称呼它。但它只是一个没有动画的网格,就像一个风景对象。如果您无法通过 unity 获取快照,请在其他 3D 编辑器上进行。

标签: animation optimization mobile unity3d


【解决方案1】:

感谢@Blindman67 为我提供了一般的窍门。在他的帮助下,我能够创建这个脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class AnimationConverter : MonoBehaviour {

//For example: Assets/_@MYSTUFF/StaticAnimations/
public string SaveLocation;
//Shows progress in inspector, useful if your animation is long
public string Progress;
public Animator MyAnimator;
//anim MUST be component of this.gameObject
public Animation anim;
public SkinnedMeshRenderer SkinMeshRender;
private Mesh[] NewStaticMesh;
//length of animation clip
private float ClipLenth;
//current animator int
private int CurrentAnimatorInt;
//just to make sure we run the code in Update ONCE
private bool AllowUpdate;
//how many frames do you want to make?
public int numberOfFrames;
//time between frame captures
private float WaitAmount;
//How many frames done
public int AmountSoFar;

private void Start()
{
    anim = this.gameObject.GetComponent<Animation>();
    AllowUpdate = true;
}

private void Update()
{
    //I'm getting an animation from my animator's current state
    CurrentAnimatorInt = MyAnimator.GetInteger("SoldierState");
    //checking to make sure we don't run more than once
    if (AllowUpdate == true)
    {
        if (CurrentAnimatorInt == 1)
        {
            //don't run this again
            AllowUpdate = false;
            //the magic begins!
            Debug.Log("Exporting static meshes from skinned mesh...");
            ExportMeshes();
        }
    }
}

void ExportMeshes()
{
    NewStaticMesh = new Mesh[numberOfFrames];
    ClipLenth = anim.clip.length;
    WaitAmount = anim.clip.length / numberOfFrames;
    //now let's start waiting for the animation to play
    StartCoroutine(WaitForNextMesh());
}

//IMPORTANT: We're using a coroutine because if we don't, we'll create
//the same static meshes because the animation won't change in 1 frame.
//The purpose is to wait as the animation is playing, then make a static mesh at the correct time.

IEnumerator WaitForNextMesh()
{
    yield return new WaitForSeconds(WaitAmount);
    AmountSoFar++;
    //wait done! Let's make the static mesh!
    Mesh mesh = new Mesh();
    SkinMeshRender.BakeMesh(mesh);
    //show progress in inspector
    Progress = "Working... " + (AmountSoFar * 100 / numberOfFrames).ToString() + "%";
    AssetDatabase.CreateAsset(mesh, SaveLocation + AmountSoFar.ToString() + anim.clip.name + "_StaticFromSkinned" + ".asset");
    //do it again!
    if (AmountSoFar < numberOfFrames)
    {
        //do it again, we have more meshes to make!
        StartCoroutine(WaitForNextMesh());
    }

    else
    {
        //created all meshes, we're done!
        Progress = "All done! :)";
        //spam the console in fancy ways
        Debug.Log("<color=green><b>All meshes created! You'll find them here: </b></color>" + SaveLocation);
        Debug.Log("<color=red><i>Don't forget to disable/change this script, or you'll do what you just did again!</i></color>");
    }
}
}

它将蒙皮网格转换为一系列静态网格。然后,我有这个脚本循环通过这些静态网格来制作动画:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CharachterAnimator : MonoBehaviour {

public GameObject[] Frames;
public int CurrentFrame;
public float TimeBetweenFrames;
// Use this for initialization
void Start ()
{
    StartCoroutine(GoToFrame());
}

IEnumerator GoToFrame()
{
    var wait = new WaitForSeconds(TimeBetweenFrames);
    while (true)
    {
        Frames[CurrentFrame].SetActive(true);
        yield return wait;
        Frames[CurrentFrame].SetActive(false);
        CurrentFrame++;
        if (CurrentFrame < Frames.Length)
        {
            Frames[CurrentFrame].SetActive(true);
        }

        else
        {
            CurrentFrame = 0;
            Frames[0].SetActive(true);
        }
    }
}
}

我在我的场景中添加了数百名士兵,Camera.Render 占用了 Profiler 中的大部分资源,所以我可以自信地说,虽然这种方法使动画看起来很生涩,但毕竟我的目标是 Android 设备(有些其中比土豆慢)。性能提升是巨大的,如果我优化 Camera.Render(Unity 中的光照、阴影等),我应该能够让数百个这样的角色运行。

再次感谢@Blindman67 让我能够执行的想法。

【讨论】:

    猜你喜欢
    • 2020-06-14
    • 1970-01-01
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 1970-01-01
    相关资源
    最近更新 更多