文章目录
使用导入的 3D 动画:
(一)状态设置相关参数
我们可以选中状态机窗口中的某一个状态为其设置相关参数,我们可以称之为动画状态设置
主要设置的是当前状态的播放速度等等细节
在 Animator 窗口中选择其中一个状态,可以看见 Inspector 窗口中如下参数:
Motion:分配给此状态的动画剪辑
Speed:动画的默认速度
Multiplier:控制速度的乘数,如果要使用需要勾选的 Parameter 选中配合的参数 float 类型
Motion Time:运动的时间,如果要使用需要勾选的 Parameter 选中配合的参数 float 类型
Mirror:是否为状态生成镜像,仅适用于人形动画,如果要配合参数使用选中旁边的 Parameter 关联参数,参数是 bool 类型
Cycle Offset:循环偏移时间,如果要配合参数使用选中旁边的 Parameter 关联参数,参数是 float 类型
Foot IK:是否遵循 Foot IK,适用于人形人形动画
Write Defaults:AnimatorStates 是否为其运动执行未动画化的属性写回默认值。
Solo / Mute:仅播放该过渡 / 禁用过渡
Solo 和 Mute 如果一起选择,Mute 优先执行
Add Behaviour:添加状态机行为脚本,见 八、状态机行为脚本
(二)连线设置相关参数
我们可以选中状态机窗口中的某一条箭头为其设置相关参数,我们可以称之为动画过渡设置
主要设置的是从一个状态切换到另一个状态时 的表现效果和切换条件
动作和动作之间的连线:
Has Exit Time:是否有退出时间,如果勾选,当切换动画时,动画一定是播放到下方的 Exit Time(百分比)的时间时才过渡到下一个动画
Exit Time:退出时间
当选择上方的 Has Exit Time 时,该值决定了过渡生效的确切时间,该值可以大于 1
如果小于 1,比如 0.85,表示当动画播放到了 85% 的动画时,就会过渡。
如果大于 1,比如 4.5,那么动画将循环 4.5 次后过渡到下一个动画
Fixed Duration:选中后,下方的 Trnaition Duration 过渡持续时间将以秒为单位解读过渡时间,如果不选中,则以百分比解读过渡时间
Transition Duration(s / %):过渡持续时间,相当于从该状态切换到下一状态的过渡动画持续的时间,对应下方两个蓝色箭头包裹区域
Transition Offset:过渡到目标状态的起始播放的时间偏移。如果是 0 则从目标状态开头开始播放,如果是 0.5 则从目标状态的一半开始播放
你可以理解为切入下一个状态的切入点
Interruption Source:该过渡中断的情况
Ordered Interruption:当前过渡是否可在不考虑顺序的情况下被其它过渡中断
选中时,找到有效过渡或当前过渡时,会中断
不选中时,找到有效过渡,会中断
Conditions:过渡条件
如果没有过渡条件,只会考虑 Exit Time
AnyState 和动作之间的连线:
多出如下参数:
Can Transition To self:是否可以过渡到自己
Preview source state:预览各种过渡状态
可以查看从任意状态切换到当前状态的过渡效果
注意点:
Has Exit Time 是否启用。
如果希望瞬间切换动画不需过多等待,取消该选项
Can Transition To self 是否启用。
如果希望自己不要打断自己,取消该选项
动画分层的作用:
游戏中会有这样的需求,人物健康状态时播放正常动画、人物非健康状态时播放特殊动画
比如血量低于一定界限,人物的大部分动作将表现为虚弱状态。我们可以利用动画分层来快速实现这样的功能
动画分层和动画遮罩结合使用:
3D 游戏中我们常常会面对这样的需求,人物站立时会有开枪动作、人物跑动时会有开枪动作、人物蹲下时会有开枪动作
从表现上来看光是开枪动作可能就有 3 种,如果要让美术同学做 3 种开枪动作费时又费资源
我们是否可以这样做,比如开枪动画只影响上半身,下半身根据实际情况播放站立,跑动,蹲下动作,通过上下半身播放不同的动画就可以达到动画的组合播放
动画分层的主要就是达到这两个目的:
(一)如何使用动画分层
在 Animator 窗口的 Layer 面板中创建一个新的层级。新层级与之前的层级共同控制动画的播放。
Weight:权重
当动画同时播放时,如果选择的是叠加状态,会根据权重决叠加的比例
Mask:动画遮罩,该层所有动画都只会作用在遮罩上,遮罩外面的部分不受该层动画影响
创建 Avatar 遮罩:
选择遮罩部分:
其中绿色表示该层将动画应用于此区域,红色部分不会受该层动画的影响
Blending:混合方式
Sync:是否同步其他层
主要用于直接从另一个层复制状态过来,在该层中进行修改,另一个层的设置信息都将保留,我们只需要替换状态对应的动画即可
适用于比如正常状态下有待机走路跑步等动作,但是受伤状态下动作会改变,可以利用同步层方便我们进行编辑
选择后会多一个 Source Layer 表示你要复制哪一层的状态
创建后,New Layer 的状态和状态之间的转换条件将和 MyLayer1 完全相同,只是该层每个状态对应的动画都为 None,自己对应替换需要设置的新状态即可:
Timing:当选中 Sync 同步其他层时,该参数激活
选中,会采用折中方案调整同步层上的动画时长(基于权重计算)
不选中,动画时长将使用原始层作为模板
IK Pass:反向动力学,之后讲解 IK 的时候再讲
代码控制:
private Animator animator;
animator = this.GetComponent<Animator>();
animator.SetLayerWeight(animator.GetLayerIndex("MyLayer2"), 1);
游戏动画中常见的功能就是在两个或者多个相似运动之间进行混合,比如:
根据角色的速度来混合行走和奔跑动画
根据角色的转向来混合向左或向右倾斜的动作
你可以理解是高级版的动画过渡
之前我们学习的动画过渡是处理两个不同类型动作之间切换的过渡效果,而动画混合是允许合并多个动画来使动画平滑混合
在 Animator Controller 窗口,右键 -> Create State -> From New Blend Tree
创建好后,双击 Blend Tree 进入混合树,点击后显示右侧的 Inspector 面板。
这里需要在 Motion 列表中点击 + 号添加至少两个动作字段才有如下的参数界面,混合树 Blend Tree 也可以包含混合树:
Parameter:参数,用于控制混合的参数,在参数列表中的参数
蓝色图像:可以在这里控制 n 个动画的阈值
Motion:关联的动画列表,可以用鼠标改变顺序
Threshold:对应动作的临界阈值 当等于这个值时动作权重最大(完全播放该动作)
这个值可以完全自由控制,数值范围不定
:控制动作的播放速度
一般默认为 1,做好的动作速度一般不需要修改
:是否镜像动作
Automate Thresholds:是否自动设置阈值,它会在取值范围内平均分
一般可以取消勾选我们手动控制更准确
Compute Thresholds:计算阈值的方式
会从动画剪辑的根运动中获去数据
举例:
比如你的动画剪辑行走动画时 Speed 速度是 1.5 个单位每秒,慢跑是 2.3 个单位每秒,快跑是 4 个单位每秒,阈值就会根据这些值来进行设置进行混合
Adjust Time Scale:调整时间刻度
1D 混合就是通过一个参数来混合子运动
注意:往混合树里面加入动作时需要找到动画文件进行关联
1D 混合是用一个参数控制动画的混合,之所以叫 1D 是因为一个参数可以看做是 1 维线性的
2D 混合可以简单理解是用两个参数控制动画的混合,之所以叫 2D 是因为两个参数可以看做是 2 维平面 xy 轴的感觉
在之前的 Inspector 窗口中下拉 Blend Type 列表,可以看到有多种不同的混合类型:
2D Simple Directional:2D 简单定向模式。运动表示不同方向时使用,比如向前、后、左、右走
2D Freeform Directional:2D 自由形式定向模式。同上 运动表示不同方向时使用,但是可以在同一方向上有多个运动,比如向前跑和走
2D Freeform Cartesian:2D 自由形式笛卡尔坐标模式。运动不表示不同方向时使用,比如向前走不拐弯、向前跑不拐弯、向前走右转、向前跑右转
Direct:直接模式。自由控制每个节点权重,一般做表情动作等
在 Animator 的 Parameters 中创建两个 Float 变量,并在 Blend Tree 中进行关联
我们设置的 x、y 变量对应于 PosX、PosY,相当于二维平面内的坐标。红色点表示当前 x、y 的值对应的坐标,调整红色点的位置可以在下方窗口预览当前对应的动画:
前三种方式只是针对动作的不同采用不同的算法来进行混合的,第四种可以用多个参数进行融合
混合树中还可以再嵌入混合树,使用上是一致的,根据实际情况选择性使用
子状态机顾名思义就是在状态机里还有一个状态机,它的主要作用就是某一个状态是由多个动作状态组合而成的复杂状态
比如某一个技能它是由 3 段动作组合而成的,跳起,攻击,落下
当我们释放这个技能时会连续播放这 3 个动作,那么我们完全可以把他们放到一个子状态机中
在 Animator Controller 窗口中,右键 -> Create Sub-State Machine
创建出来后,是个类似菱形的图标,我们双击进入子状态机
子状态机的界面和状态机类似。不同的是有一个上层的图标(Up Base Layer),通过连接该状态来转移到上层状态机的某个状态
在这里选择上一层的某个状态
在这里选择回到哪一层,将播放该层的默认动画
在状态机的层级设置中,开启 IK 通道
继承 MonoBehavior 的类中,Unity 定义了一个 IK 回调函数:OnAnimatorIK
我们可以在该函数中调用 Unity 提供的 IK 相关 API 来控制 IK
Animator 中的 IK 相关 API:
private Animator animator;
public Transform pos;
public Transform pos2;
private void OnAnimatorIK(int layerIndex)
{
// 头部 IK 相关
// weight: LookAt全局权重 0 ~ 1
// bodyWeight: LookAt 时身体的权重 0 ~ 1
// headWeight: LookAt 时头部的权重 0 ~ 1
// eyesWeight: LookAt 时眼镜的权重 0 ~ 1
// clampWeight: 0 表示角色运动时不受限制,1 表示角色完全固定无法执行 LookAt,0.5 表示只能够移动范围的一半
animator.SetLookAtWeight(1, 1f, 1f);
animator.SetLookAtPosition(pos.position);
// animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1);
// animator.SetIKPosition(AvatarIKGoal.RightFoot, pos2.position);
animator.SetIKRotation(AvatarIKGoal.RightFoot, pos2.rotation);
}
private void OnAnimatorMove()
{
// 如果动画本身有移动,还需要自己添加代码移动,建议在这里添加
}
IK 在游戏开发中的应用
关于 OnAnimatorIK 和 OnAnimatorMove 两个函数的理解:
我们可以简单理解这两个函数是两个和动画相关的特殊生命周期函数,他们在 Update 之后 LateUpdate 之前调用
他们会在每帧的状态机和动画处理完后调用,OnAnimatorIK 在 OnAnimatorMove 之前调用
OnAnimatorIK 中主要处理 IK 运动相关逻辑
OnAnimatorMove 主要处理动画移动以修改根运动的回调逻辑
他们存在的目的只是多了一个调用时机,当每帧的动画和状态机逻辑处理完后再调用
动画目标匹配主要指的是:当游戏中角色要以某种动作移动,该动作播放完毕后,人物的手或者脚必须落在某一个地方
比如:角色需要跳过踏脚石或者跳跃并抓住房梁,那么这时我们就需要动作目标匹配来达到想要的效果
Unity 中的 Animator 提供了对应的函数来完成该功能,使用步骤是
找到动作关键点位置信息(比如起跳点,落地点,简单理解就是真正可能产生位移的动画表现部分)
将关键信息传入 MatchTargetAPI 中
private void MatchTarget()
{
// 参数一:目标位置
// 参数二:目标角度
// 参数三:匹配的骨骼位置
// 参数四:位置角度权重
// 参数五:开始位移动作的百分比
// 参数六:结束位移动作的百分比
animator.MatchTarget(targetPos.position, targetPos.rotation, AvatarTarget.RightFoot, new MatchTargetWeightMask(Vector3.one, 1), 0.4f, 0.64f);
}
其中,位移动作百分比在这里查看:
调用匹配动画的时机有一些限制:
必须保证动画已经切换到了目标动画上
必须保证调用时动画并不是处于过度阶段而真正在播放目标动画:
如果发现匹配不正确,往往都是这两个原因造成的
需要开启 Apply Root Motion
通常的做法是,为动画添加事件进行触发,事件选在播放动画后的某一点添加
状态机行为脚本时一类特殊的脚本,继承指定的基类,它主要用于关联到状态机中的状态矩形上
我们可以按照一定规则编写脚本,当进入、退出、保持在某一个特定状态时我们可以进行一些逻辑处理
简单解释就是为 Animator Controller 状态机窗口中的某一个状态添加一个脚本,利用这个脚本我们可以做一些特殊功能。比如:
进入或退出某一状态时播放声音
仅在某些状态下检测一些逻辑,比如是否接触地面等等
激活和控制某些状态相关的特效
新建一个脚本继承 StateMachineBehaviour 基类
实现其中的特定方法进行状态行为监听
处理对应逻辑
public class Lesson57_StateMachineBehaviour : StateMachineBehaviour
{
public string stateName; // 可以配置字段实现脚本的通用性
public string musicName;
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
if (stateInfo.IsName(stateName))
Debug.Log("进入HumanoidIdle状态");
}
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
if (stateInfo.IsName("HumanoidIdle"))
Debug.Log("退出HumanoidIdle状态");
}
public override void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
base.OnStateIK(animator, stateInfo, layerIndex);
}
public override void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
base.OnStateMove(animator, stateInfo, layerIndex);
}
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
base.OnStateUpdate(animator, stateInfo, layerIndex);
if (stateInfo.IsName("HumanoidIdle"))
Debug.Log("处于HumanoidIdle状态");
}
public override void OnStateMachineEnter(Animator animator, int stateMachinePathHash) {
base.OnStateMachineEnter(animator, stateMachinePathHash);
}
public override void OnStateMachineExit(Animator animator, int stateMachinePathHash) {
base.OnStateMachineExit(animator, stateMachinePathHash);
}
}
状态机行为脚本和动画事件如何选择:
游戏开发时经常遇到这样的情况:
有 n 个玩家和 n 个怪物,他们的动画状态机行为都是一致的,只是对应的动作不同而已
这时如果我们为他们每一个对象都创建一个状态机进行状态设置和过渡设置无疑是浪费时间的
所以状态机复用就是解决这一问题的方案,主要用于为不同对象使用共同的状态机行为,减少工作量,提升开发效率
在 Project 窗口,右键 Create -> Animator Override Controller
为 Animator Override Controller 文件在 Inspector 窗口关联基础的 Animator Controller 文件
关联需要的动画
角色控制器是让角色可以受制于碰撞,但是不会被刚体所牵制
如果我们对角色使用刚体判断碰撞,可能会出现一些奇怪的表现,比如:
在斜坡上往下滑动
不加约束的情况碰撞可能让自己被撞飞
等等
而角色控制器会让角色表现的更加稳定,Unity 提供了角色控制器脚本专门用于控制角色
注意:添加角色控制器后,不用再添加刚体
选中角色模型,在 Inspector 窗口中添加如下组件:
代码控制:
public class Lesson59 : MonoBehaviour
{
private CharacterController cc;
private Animator animator;
// Start is called before the first frame update
void Start() {
cc = this.GetComponent<CharacterController>();
animator = this.GetComponent<Animator>();
// 是否接触了地面
if (cc.isGrounded) print("接触地面了");
// 受重力作用的移动
cc.SimpleMove(Vector3.forward * 10 * Time.deltaTime);
// 不受重力作用的移动
cc.Move(Vector3.forward * 10 * Time.deltaTime);
}
// Update is called once per frame
void Update() {
animator.SetInteger("Speed", (int)Input.GetAxisRaw("Vertical"));
cc.Move(this.transform.forward * (80 * Time.deltaTime * Input.GetAxisRaw("Vertical")));
if (cc.isGrounded) print("接触地面了");
}
// 当角色控制器想要判断和别的碰撞器产生碰撞时,使用该函数,相当于替换了 OnCollisionEnter 函数
private void OnControllerColliderHit(ControllerColliderHit hit) {
print(hit.collider.gameObject.name);
}
// 对角色控制器没用
//private void OnCollisionEnter(Collision collision)
//{
// print("碰撞触发");
//}
//可以检测触发器
private void OnTriggerEnter(Collider other) {
print("触发器触发");
}
}
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里编辑 3.解析依赖到项目中
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?
3月26日,映宇宙(HK:03700,即“映客”)发布截至2022年12月31日的2022年度业绩财务报告。财报显示,映宇宙2022年的总营收为63.19亿元,较2021年同期的91.76亿元下降31.1%。2022年,映宇宙的经营亏损为4698.7万元,2021年同期则为净利润4.57亿元;期内亏损(净亏损)为1.68亿元,2021年同期的净利润为4.33亿元;非国际财务报告准则经调整净利润为3.88亿元,2021年同期为4.82亿元,同比下降19.6%。 映宇宙在财报中表示,收入减少主要是由于行业竞争加剧,该集团对旗下产品采取更为谨慎的运营策略以应对市场变化。不过,映宇宙的毛利率则有所提升
写在之前Shader变体、Shader属性定义技巧、自定义材质面板,这三个知识点任何一个单拿出来都是一套知识体系,不能一概而论,本文章目的在于将学习和实际工作中遇见的问题进行总结,类似于网络笔记之用,方便后续回顾查看,如有以偏概全、不祥不尽之处,还望海涵。1、Shader变体先看一段代码......Properties{ [KeywordEnum(on,off)]USL_USE_COL("IsUseColorMixTex?",int)=0 [Toggle(IS_RED_ON)]_IsRed("IsRed?",int)=0}......//中间省略,后续会有完整代码 #pragmamulti_c
三分钟集成Tap防沉迷SDK(Unity版)一、SDK介绍基于国家对上线所有游戏必须增加防沉迷功能的政策下,TapTap推出防沉迷SDK,供游戏开发者进行接入;允许未成年用户在周五、六、日以及法定节假日晚上8:00-9:00进行游戏,防沉谜时间段进入游戏会弹窗进行提示!开发环境要求:Unity2019.4或更高版本iOS10或更高版本Android5.0(APIlevel21)或更高版本🔗Unity集成Demo参考链接🔗UnityTapSDK功能体验APK下载链接二、集成前准备1.创建应用进入开发者后台,按照提示开始创建应用;2.开通服务在使用TDS实名认证和防沉迷服务之前,需要在上面创建的应