当前位置: 首页 > news >正文

Unity DOTS《群体战斗弹幕游戏》核心技术分析之3D角色动画

  最近DOTS发布了正式的版本, 我们来分享现在流行基于群体战斗的弹幕类游戏,实现的核心原理。今天给大家介绍大规模战斗群体3D角色的动画如何来实现。

DOTS 对角色动画支持的局限性

  截止到Unity DOTS发布的版本1.0.16,目前还是无法很好的支持3D角色动画。在DOTS 的baker过程种,不支持常见的动画组件,包括: Animation组件,基于状态机的Animator, 以及人形动画。同时DOTS在节点Baker成Entity的过程种只支持MeshRenderer组件,不支持SkinnedMeshRenderer组件(SkinnedMeshRenderer组件很多转换过来后显示效果不正确)。所以DOTS要支持3D角色动画就变得非常的麻烦。目前主流的方案就两个:

  1. 3D帧动画模式: 角色创作的时候使用MeshRender+材质不带动画,然后将动画组件每帧每个顶点的采样数据Bake到一张动画纹理,将这个纹理关联到材质里面。这样当物体Baker的时候,就可以正常地将MeshRender+材质转成Entity。在Shader中从动画纹理里读取动画每一帧,每个节点的模型坐标,再传递给渲染流程,把动画渲染出来。这样Entity就可以支持动画了。

  2. 将SkinnedMeshRender +动画做成ECS模式,然后Baker出来,这种Unity目前没有直接开放出来,有一些第三方的插件可以支持。

  总之,如果要用DOTS基于ECS来播放3D角色动画,目前Unity DOTS版本(1.0.16)是不直接支持的。

《群体战斗弹幕游戏》应该使用哪种动画系统

  《群体战斗弹幕游戏》这类游戏应该使用哪种动画系统会比较好呢?我们来分析一下项目需求,群体战斗有大量的战斗单元在一个屏幕,这些战斗单元对单个的渲染质量要求不高,但是数量巨大导致非常消耗性能。渲染质量要求不高,这样我们的战斗单元的模型的面数可以尽量的低,这样顶点数不会特别多,同时动画也不会很复杂,帧数也可以比较少。总结一下需求:单个模型顶点面数少,动画简单不复杂,节点的数目很多。

  按照以上的需求,我们在群体战斗的游戏中选择《3D帧动画》模式来做大规模的角色动画。这个方式有几个好处,动画预先被计算生成到纹理里面,这样代替原来的动画采样计算,空间换时间节省了性能,同时面数少,动画简单,这样动画纹理的内存占用可以接受。针对《弹幕类游戏》有大量的同一种类型的物体,使用MeshRenderer+材质+动画纹理的模式,能最大限度地使用GPU Instancing合批,降低节约DrawCall。

基于帧动画的3D角色动画如何实现

  基于帧动画的3D角色动画如何实现呢?结合弹幕游戏的3D角色动画简单的特点,分成以下步骤来具体实现:

(1)基于URP来编写一个最简单的Diffuse Shader,渲染没有光照计算,阴影计算,直接将模型纹理贴到模型表面;

HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag// Includes
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"struct appdata
{float2 uv : TEXCOORD0;float4 pos : POSITION;UNITY_VERTEX_INPUT_INSTANCE_ID
};struct v2f
{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;UNITY_VERTEX_INPUT_INSTANCE_ID
};CBUFFER_START(UnityPerMaterial)sampler2D _MainTex;float4 _MainTex_ST;// float _AnimLen;// sampler2D _AnimMap;// float4 _AnimMap_TexelSize;//x == 1/width
CBUFFER_ENDfloat4 ObjectToClipPos(float3 pos)
{return mul(UNITY_MATRIX_VP, mul(UNITY_MATRIX_M, float4 (pos,1)));
}v2f vert(appdata v, uint vid : SV_VertexID)
{UNITY_SETUP_INSTANCE_ID(v);v2f o;o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.vertex = ObjectToClipPos(v.pos);return o;
}float4 frag(v2f i) : SV_Target
{float4 col = tex2D(_MainTex, i.uv);return col;
}
ENDHLSL

(2)扩展Diffuse Shader,添加anim功能,增加uniform 来接受动画纹理,包括动画纹理对象(sampler2D),动画的时间长度(float);

v2f vert(appdata v, uint vid : SV_VertexID)
{UNITY_SETUP_INSTANCE_ID(v);float f = _Time.y / _AnimLen;fmod(f, 1.0);float animMap_x = (vid + 0.5) * _AnimMap_TexelSize.x;float animMap_y = f;float4 pos = tex2Dlod(_AnimMap, float4(animMap_x, animMap_y, 0, 0));v2f o;o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.vertex = ObjectToClipPos(pos);return o;
}

(3)基于简单的Diffuse Shader+传统的Animation组件做好普通的预制体节点给AnimBaker工具来使用;

(4)编写一个工具,将普通3D角色动画的预制体节点中的动画进行采样,把数据保存到动画纹理,并创建角色Mesh+材质(Difuse Anim Shader + Anim纹理+Anim时间)的预制体;

(5)将生成好的预制体放到DOTS中的subscene来进行Bake,Bake成Entity,这样角色就可以带动画了。


  今天的分享就到这里,需要本篇文章完整的项目工具与源码的同学可以 + 企.鹅.裙 428 540 563


  下面是DOTS的VIP课程前18节视频,免费观看

Unity DOTS进阶与项目实战(B站18集)

第001课DOTS的环境安装与准备事项

第002课 DOTS的核心机制与概述

第003课DOTS的SubScene

第004课Component的概述与普通组件的Baker

第005课System与SystemGroup概述

第006课DOTS中的ECS核心概念总结

第007课Baking系列之Baking与Baker详解

第008课Baking系列之BakingSystem与BakingWorld详解

第009课FilterBakingOutput与PrefabsInBaking

第010课BlobAsset核心机制分析

第011课Aspect核心机制分析

第012课 StructChange核心机制详解

第013课Managed与Unmanaged Component详解与性能分析

第014课ShareComponent核心机制与性能分析

第015课CleanupComponent核心分析

第016课 Dynamic Buffer Component详解与分析

第017课Tag与Chunk Component详解与分析

第018课Enableable与Singleton组件详解与分析

http://www.lryc.cn/news/340460.html

相关文章:

  • react异步组件如何定义使用 标准使用方法
  • React + Ts + Vite + Antd 项目搭建
  • js爬虫puppeteer库 解决网页动态渲染无法爬取
  • 代码随想录:二叉树5
  • Tomcat 获取客户端真实IP X-Forwarded-For
  • 记录PS学习查漏补缺
  • Kafka 架构深入探索
  • k-means聚类算法的MATLAB实现及可视化
  • Excel文件转Asc文件
  • 【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题7
  • Webrtc 信令服务器实现
  • 【Blockchain】连接智能合约与现实世界的桥梁Chainlink
  • 解决EasyPoi导入Excel获取不到第一列的问题
  • Vue 阶段练习:记事本
  • JavaScript判断受访域名,调用不同的js文件
  • 下载软件时的Ubuntu x86_64-v2、skylake、aarch64版本分别代表什么?
  • 数字化社交的引擎:解析Facebook的影响力
  • 淘宝API商品详情数据在数据分析行业中具有不可忽视的重要性
  • 【产品】ANET智能通信管理机 物联网网关 电力监控/能耗监测/能源管理系统
  • R语言数据分析案例
  • vscode debug 配置:launch.json
  • idea工具使用Tomcat创建jsp 部署servlet到服务器
  • MyBatisPlus自定义SQL
  • 使用formio和react实现在线表单设计
  • MySQL 基础使用
  • ✌粤嵌—2024/4/3—合并K个升序链表✌
  • 企业微信主体的修改方法
  • C++的封装(十):数据和代码分离
  • 第十五届蓝桥杯大赛软件赛省赛 C/C++ 大学 B 组(基础题)
  • 模板的进阶