Unity(四) 基于关键帧的动画与骨骼动画

这篇具有很好参考价值的文章主要介绍了Unity(四) 基于关键帧的动画与骨骼动画。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Unity中有两种类型的动画:基于关键帧的动画和骨骼动画

基于关键帧的动画是最常见的动画形式,也称为帧动画。它将每一帧的动画存储为一个离散的关键帧,然后通过计算每一帧之间的差异来创建动画。这种类型的动画适用于不需要太多交互或程序控制的简单动画。在Unity中,使用Animator来创建基于关键帧的动画。

骨骼动画是通过修改骨骼层次结构中的骨头来实现的。这种类型的动画适用于需要更高程度的交互和程序控制的复杂动画,例如游戏中的角色动画。在Unity中,使用Animation和Animator来创建骨骼动画。

一、基于关键帧的动画

动画中的特定姿势由其关键帧定义。在传统的手绘动画中,关键帧是引导动画师绘制的姿势,是定义动画序列的重要(或关键)图纸。

Unity中有几种方式来制作基于关键帧的动画:

1. 使用Animation

Animation一般用于快速创建简单的动画场景,通过设置若干个关键帧,即可完成。

方法如下 (有点类似于Flash动画制作):

a. 选中目标动画物体,在Inspector面板中点击Add Component按钮,选择Animation组件

b. 在Project面板中创建Animation Clip

c. 在Animation面板中将动画剪辑拖拽到物体的Animation组件上

d. 点击Record按钮开始录制,可调整物体的属性,如位置、旋转、缩放等

e. 点击Stop按钮结束录制

2. 使用Animator Controller

Animator Controller一般用于更复杂的动画制作,它可以创建并维护状态机,并串联起多个Animation,达成复杂动画的制作,这个也可以用于后面骨骼动画的制作

动画状态机(Animation State Machine),需要考虑以下几个方面:

  • 动画状态:定义动画剪辑和动画状态之间的映射关系。
  • 过渡条件:定义两个动画状态之间的转换条件。
  • 过渡时间:定义两个动画状态之间的过渡时间。
  • 动画层:定义动画状态所在的层级,以及层级之间的权重关系。
  • 动画事件:定义动画状态播放过程中触发的事件

unity 摄像机关键帧,3D开发,unity,游戏引擎,动画,骨骼绑定

如图所示,可在Controller上设定动画的状态,entry入口,exit退出等状态,并根据需要配置各个状态的物体的参数,最后可设置他们进入各个状态的条件

unity 摄像机关键帧,3D开发,unity,游戏引擎,动画,骨骼绑定

3. 使用DoTween插件

DoTween 是由 Demigiant 开发的,被广泛应用于 Unity 游戏开发中。它是一个流行的动画插件,被许多开发者用于创建流畅、高效的动画效果,提升游戏体验。

这里推荐使用DoTweenPro,可以使用可视化的方式,很方便的完成动画制作,而不需要编写代码。它有两种形式可创建动画,DoTweenAnimation和DoTweenPath。

个人理解DoTweenAnimation一般用于对单一物体的状态改变动画制作,而DoTweenPath用于路径动画的快速制作,例如摄像机飞行等。

unity 摄像机关键帧,3D开发,unity,游戏引擎,动画,骨骼绑定

Animation的配置一览,可快速通过可视化的方式配置各种效果,例如旋转、放大等,并配置延迟模式,时长,缓动,循环,各种事件等

unity 摄像机关键帧,3D开发,unity,游戏引擎,动画,骨骼绑定

Path配置一览,可以配置固定的物理行动路线以及各个节点的状态。配置与Animation大同小异。

unity 摄像机关键帧,3D开发,unity,游戏引擎,动画,骨骼绑定

缓动配置一览,这个也很重要

二、骨骼动画

1. 概念

骨骼动画的制作方式与关键帧动画是一样的,但需要注意的是其底层逻辑完全不同,制作前我们最好是了解一下骨骼动画的制作过程。

模型动画中,骨骼动画一般与线性动画对比,线性动画较为简单,一般是通过顶点位置加入关键帧让动画看起来更加平滑,骨骼动画中,模型具有互相连接的骨骼组成骨架结构,通过改变骨骼的朝向和位置来为模型生成动画,从而更加拟真。

一般骨骼动画制作过程为: 蒙皮->关键帧->关键帧之间插值/姿态调整 

蒙皮的意思其实就是将网格(mesh)和顶点(vertex)绑定到骨骼上

unity 摄像机关键帧,3D开发,unity,游戏引擎,动画,骨骼绑定

几个概念:

皮肤(Skin):Mesh

骨骼(Skeleton):骨骼上所在的mesh和vertex随着骨骼一起运动

关节(Joints):骨骼连接处,骨骼可以围绕关节运动

一言以蔽之,将骨骼与标准姿势绑定完成后,动画师通过操纵骨骼来制作其关键帧,然后通过在关键帧之间进行插入值形成整个动画。

2. 制作

那么对于普通程序员,在拿到动画师的成果后应该怎么做呢?

以个人行走举例,一般来说需要的几种骨骼动画类型为,静止(可加入一些闲置时候的动画)、行走,后退,左转,右转,跑步等。

a. 拿到各个状态的fbx模型文件

b. 创建Animator Controller,将fbx文件拖动为到state上

c. 创建变量和状态连线,并且设置条件,例如闲置->行走,行走->向右转弯等,这里配置要尽可能的全面。

d. 添加动画脚本,通过按键或鼠标控制角色,并改变变量。需要配置第一人称摄像头,以及控制角色的脚本

PlayerController

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;

public class Player : MonoBehaviour
{
    private float moveSpeed;//摄像机的移动速度
    private Animator Anim;
    private GameObject fpvCamera; // 第一人称摄像头
    void Start()
    {
        moveSpeed = -4f;
        Anim = GetComponent<Animator>();
        fpvCamera = UnityUtils.FindDeActiveObjectFirstOrDefault("CameraPlayer");
    }

    Vector3 rot = new Vector3(0, 0, 0);

    void Update()
    {
        //鼠键控制移动
        WASD();
        if (Input.anyKey)
        {
            this.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeRotation;
        }
        else
        {
            this.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
        }
    }

    /// <summary>
    /// 鼠键控制player移动
    /// </summary>
    void WASD()
    {
        if (Input.GetMouseButton(1))
        {
            if (Input.GetAxis("Mouse X") != 0)
            {
                if (Input.GetAxis("Mouse X") < 0.1f && Input.GetAxis("Mouse X") > -0.1f)
                {
                    return;
                }
                this.fpvCamera.transform.Rotate(new Vector3(0, Input.GetAxis("Mouse X") * Time.fixedDeltaTime * 200, 0));
                //clearArrow(false);
            }
            if (Input.GetAxis("Mouse Y") != 0)
            {
                if (Input.GetAxis("Mouse Y") < 0.1f && Input.GetAxis("Mouse Y") > -0.1f)
                {
                    return;
                }
                this.fpvCamera.transform.Rotate(new Vector3(Input.GetAxis("Mouse Y") * Time.fixedDeltaTime * -200, 0, 0));//摄像机的旋转速度
            }
        }

        if (Input.GetKey(KeyCode.W))
        {
            // this.fpvCamera.transform.Translate(-Vector3.forward * Time.deltaTime * moveSpeed);//移动
        }
        if (Input.GetKeyDown(KeyCode.W))
        {
            Anim.SetBool("Walk", true);
        }
        if (Input.GetKeyUp(KeyCode.W))
        {
            Anim.SetBool("Walk", false);
        }
        if (Input.GetKey(KeyCode.S))
        {
            //gameObject.transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed);//向后。
            // this.fpvCamera.transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed);//向后。
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            Anim.SetBool("Back", true);
        }
        if (Input.GetKeyUp(KeyCode.S))
        {
            Anim.SetBool("Back", false);
        }
        if (Input.GetKey(KeyCode.A))
        {
            transform.RotateAround(transform.position, Vector3.up, 45f * Time.deltaTime * moveSpeed);//旋转。
            this.fpvCamera.transform.RotateAround(transform.position, Vector3.up, 30f * Time.deltaTime * moveSpeed);
        }
        //if (Input.GetKeyDown(KeyCode.A))
        //{
        //    Anim.SetBool("Left", true);
        //}
        //if (Input.GetKeyUp(KeyCode.A))
        //{
        //    Anim.SetBool("Left", false);
        //}
        if (Input.GetKey(KeyCode.D))
        {
            transform.RotateAround(transform.position, Vector3.up, -45f * Time.deltaTime * moveSpeed);//旋转。
            fpvCamera.transform.RotateAround(transform.position, Vector3.up, -30f * Time.deltaTime * moveSpeed);
        }
        //if (Input.GetKeyDown(KeyCode.D))
        //{
        //    Anim.SetBool("Right", true);
        //}
        //if (Input.GetKeyUp(KeyCode.D))
        //{
        //    Anim.SetBool("Right", false);
        //}
        if (Input.GetKeyUp(KeyCode.R))
        {
            Anim.SetBool("Run", false);
        }
        if (Input.GetKeyDown(KeyCode.R))
        {
            Anim.SetBool("Run", true);
        }
        if (Input.GetKey(KeyCode.R))
        {
            gameObject.transform.Translate(Vector3.forward * Time.deltaTime * 8);//移动
        }
        if (Input.GetKeyUp(KeyCode.F))
        {
            Anim.SetBool("Magic", false);
        }
        if (Input.GetKeyDown(KeyCode.F))
        {
            Anim.SetBool("Magic", true);
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            transform.position += new Vector3(0, 1, 0);//跳过障碍物
        }
    }
}

FPCamera:从默认摄像机转为第一人称摄像机。

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

public class FPS : MonoBehaviour
{
    private GameObject fpvCamera; // 第一人称摄像头
    // Start is called before the first frame update
    void Start()
    {
        fpvCamera = UnityUtils.FindDeActiveObjectFirstOrDefault("CameraPlayer");
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void FPSStart()
    {
        Camera2.enableMainView = !Camera2.enableMainView;
        if (Camera2.enableMainView)
        {
            fpvCamera.SetActive(false);
        }
        else
        {
            fpvCamera.SetActive(true);
        }
    }
}

代码很简单,做动画最重要需要尝试

3. CPU Instancing & GPU Instancing

扩展一点内容,以上我们制作的都是CPU Instancing的方式,针对大型游戏等场景,Unity提供了GPU Instancing的方式来提升动画性能(在Web上不可用),其作用如下:

有两种 GPU 加速模式:

1. 缓存每一帧顶点坐标,顶点着色器根据帧数和顶点编号获取顶点数据进行渲染,此为方案 A;

2. 缓存每一帧骨骼变换矩阵,顶点着色器计算蒙皮,此为方案 B;

处理大规模角色,同时不要求动画效果很精细,内存够用的情况,可以采用方案A。

处理逻辑压力大、CPU消耗多并且渲染压力小的情况,可以选择方案B。

插件:GPU Animation Baker Pro

个人也没有相关的制作经验,仅做了了解。如需深入,可以参考文章:

Unity - Manual: GPU instancing文章来源地址https://www.toymoban.com/news/detail-777218.html

到了这里,关于Unity(四) 基于关键帧的动画与骨骼动画的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • unity实现简单的摄像机震动效果(包括普通摄像机和虚拟摄像机)

    用代码实现摄像机简单的震动效果

    2024年02月12日
    浏览(42)
  • unity摄像机跟随鼠标旋转

     float vertical = Input.GetAxis(\\\"Mouse X\\\") float horizontal = Input.GetAxis(\\\"Mouse Y\\\") 第二种 通过 计算坐标时只需要通过 Quaternion.Euler 来取得旋转四元数,以玩家为原点衍生一条(0,0,-1)的向量并乘上四元数以旋转至 Player 指向摄像机的方向,最后乘上 Distance ,即可得到摄像机相对玩家的偏移

    2024年02月11日
    浏览(63)
  • unity摄像机平滑移动旋转

    Unity中使用Vector3.SmoothDamp(平滑阻尼)方法进行跟随移动,可以使跟随看起来很平滑,而不显得突兀,最典型的示例就是相机平滑跟随角色移动。 SmoothDamp (current : Vector3, target : Vector3, ref currentVelocity : Vector3, smoothTime )  

    2024年02月11日
    浏览(51)
  • unity Camera(摄像机)介绍

    目录 一.摄像机类型 1.Perspective (透视摄像机) 2.Orthographic(正交摄像机) 二.摄像机属性 1.Clear Flags 2.Background 背景色 3.Culling Mask 剔除遮罩 4.Projection 投影 5.Field Of View   视野范围 6.Size 大小 7.Clipping Planes 裁剪屏幕 8.Viewport Rect 标准视图矩形 9.Depth 深度 10.Rendering Path 渲染路径

    2024年02月01日
    浏览(41)
  • 第三十一章 Unity骨骼动画

    关于骨骼动画的原理,我们这里不再详细介绍,有不清楚的可以回去看DirectX课程和3dsMAX课程。接下来,我们来讲解一下Unity的骨骼动画系统。Unity 的动画系统基于动画剪辑(Animation Clip)的概念,它的本质就是一小段动画,代表了一个游戏角色的动作,例如:走路,跑步,攻

    2024年02月08日
    浏览(60)
  • 【Unity入门】Audio和摄像机

        大家好,我是Lampard~~     欢迎来到Unity入门系列博客,所学知识来自B站阿发老师~感谢     要说一款游戏最重要的是什么,那无疑是它的视听系统了。画面精美,音乐音效好听才能吸引住玩家,那么今天就来学习了解 最重要的组件Audio和摄像机组件 ,之后我们就会正式

    2023年04月08日
    浏览(38)
  • Unity物体始终朝向摄像机方向

    在上面的代码中,首先定义了一个cameraTransform变量,用于存储摄像机的Transform组件。 使用 Camera.main 方法来获取场景中的主摄像机,然后获取其Transform组件并将其赋值给 cameraTransform 变量。 然后,在Update方法中,我们计算出摄像机位置和物体位置之间的向量差,并将其存储在

    2024年02月15日
    浏览(51)
  • Unity三种摄像机旋转方式

    1.按下鼠标右键可以实现摄像机上下左右旋转 2.按下鼠标右键可以实现摄像机围绕某个物体上下左右旋转 3.摄像头始终跟随在某个物体的正后方

    2024年02月13日
    浏览(44)
  • Unity摄像机旋转与移动脚本实现

            最近做项目经常用到需要控制摄像机的地方,查阅了网上的方法后,以自己的需要写了一个这样的功能。希望对码友有所帮助        (本脚本放在摄像机上)         摄像机脚本功能:           1、通过键盘的WASD键控制摄像机的前后左右移动           2、通过

    2024年02月13日
    浏览(42)
  • Unity摄像机对象锁定旋转运镜模拟

    问题简述        在3D模式下如何模拟实现Unity摄像机对象锁定旋转运镜,可以分为两个部分,第一是实现对象锁定,第二是实现旋转运镜。对象锁定就是无论摄像机如何运动,始终保持对象位于摄像机成像区域的固定位置,旋转运镜就是使得摄像机围绕对象进行旋转运动。

    2024年02月04日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包