Unity 动画系统

动画系统包含:

  • 动画片段 Animation Clip,记录物体变化的信息,可以是角色的闪转腾挪,也可以是一扇门的开闭
  • 动画状态机 Animator Controller,根据设置切换动画片段
  • 动画组件 Animator,Animation
  • 替身 Avatar,对人形动画进行复用

动画复用

把一个 .anim 的动画文件作为文本打开
在这里插入图片描述
里面有个path属性记录动画要操作的对象的路径,如果根据path找不到对象,这个动画就会失效

在这里插入图片描述
其他物体要使用这个动画就必须包含路径一致的对象,否则Animation窗口里就会显示Missing

在这里插入图片描述
对于人形动画的fbx文件,选中动画按Ctrl + D就可以把动画复制出来,同样作为文本打开

在这里插入图片描述
这里path为空,而attribute记录Avatar中对应的骨骼节点和进行什么操作

Avatar 替身系统

在这里插入图片描述
在mixamo上下载一个动画文件

在这里插入图片描述
不同DCC软件制作的骨骼节点的名称可能不一样的,不能直接使用该动画,这时候需要借助Avatar建立骨骼和Unity肌肉系统的映射关系

假设A,B两个模型的骨骼名称不同,要把A模型的动画片段A复用到B模型上
在这里插入图片描述
步骤:
1.创建AAvatar,AAvatar中保存模型A骨骼和Unity肌肉结构的对应关系,骨骼信息也被保存到Avatar文件中
2.创建BAvatar,BAvatar中保存模型B骨骼和Unity肌肉结构的对应关系
3.通过AAvatar,把动画片段A从描述A的骨骼变化翻译为描述unity肌肉拉伸
4.模型B使用动画片段A,通过BAvatar把动画文件中对Unity肌肉结构的描述翻译为对B模型骨骼变化的描述

具体操作
在这里插入图片描述
在模型的Rig面板中选择人形动画,点击Apply

Avatar DefinitionCreate From This Model 从这个模型本身创建Avatar,把当前模型的骨骼与Unity肌肉结构建立对应关系
Copy from OtherAvatar 从其他Avatar中复制骨骼层次结构、绑定信息等,需要确保两者具有相似的骨骼层次结构和绑定信息,模型不会创建新的Avatar,只会导入动画
Skin Weights蒙皮或者mesh上的节点可以被几个骨骼所影响
Strip Bones勾选后,Unity会自动删除所有不必要的骨骼,并将相邻的骨骼合并为一个单独的骨骼。这样可以减少骨骼数量和顶点权重数量,从而提高游戏性能
Optimize Game Objects勾选后会删除模型上的骨骼,从Avatar中读取骨骼信息

在这里插入图片描述
模型中会出现Avatar,点击Inspector界面上的Configure Avatar进入配置界面
在这里插入图片描述
这里可以看到骨骼和Unity肌肉的映射关系,这些Unity基本已经配置好了,一般不需要修改
在这里插入图片描述
动画的Rig面板中选择Copy From Other Avatar,并选择来源模型的Avatar,点击Apply
在模型的Animator组件中选择各自的Avatar文件,这时动画就可以复用了

Animator

在这里插入图片描述

Apply Root Motion有的动画片段自带位移,勾选后就会把位移应用到对象上,如果通过脚本控制位移就不勾选
Update ModeNormal 与Monobehaviour的Update同步
Animate Physics 与FixedUpdate同步,如果角色动画需要与物理系统交互,选这个
Unscaled Time 与Update同步,忽略TimeScale
Culling ModeAlways Animate 不剔除,始终运行动画
Cull Update Transforms 不可见时会禁用重定向,ik,Transform变化
Cull Completely 不可见时停止模拟,再次出现时,从停止的状态继续模拟

运行时最下面还会显示动画片段相关信息

在这里插入图片描述
在Animator中动画状态分为3种:单独的动画片段,多个片段组成的混合树,另一个状态机

在这里插入图片描述
在Animator窗口右上角有个Auto Live Link,选中后会在窗口内聚焦当前播放的动画状态
在这里插入图片描述

动画片段(AnimationClip)

在这里插入图片描述

Tag给动画加标签,在代码中就可以根据动画的标签执行不同的逻辑
Motion这个动画状态管理的动画片段,如果是混合树就显示管理的混合树
Speed动画播放速度,负值就是倒放,脚本无法修改Speed数值
Multiplier勾选右边的Parameter激活,选择Parameters中的一个浮点型参数关联,动画的速度就等于 Speed * Multiplier
Motion Time范围0~1f,修改后会使动画停在特定时间点,0是开始,1是结束
Mirror镜像动画
Cycle Offset播放时的偏移值,0表示不偏移,0.5表示从中间开始播放,偏移不是切割,动画还是会完整播放,只是动画的起始点改变
Foot IK使用IK矫正,把脚步实际位置向IK Goal位置拉近一点,需要设置IK Goal权重
Write DefaultsAnimator触发OnEable时,将遍历AnimatorController中的所有片段,收集所有片段的属性值。如果某个片段中没有描述某些属性的变化,是否为其写入默认值

正向动力学(Forward Kinematics):常见的动画一般是由骨骼根节点(人形动画是屁股)到末梢骨骼节点依次计算旋转位移缩放来决定每个骨骼的最终位置
反向动力学(Inverse Kinematics):末梢骨骼位置确定,反向计算各个父节点骨骼的旋转位移缩放,比如脚放在台阶上,反向计算其各个父骨骼

在这里插入图片描述
使用Avatar把骨骼系统转为肌肉系统后,双手,双脚位置可能出现一些偏移,Unity会保存转换前骨骼系统下手脚的正确位置,并把这些位置放在IK Goal(目标位置)上,也就是上图中双手,双脚位置的红球,手肘处的红球和膝盖处的红球是IK Hint(辅助位置),通过它防止肘部关节出现奇怪的扭曲,Foot Ik参考的是IK Goal的初始位置
在这里插入图片描述
使用IK需要在Layer上激活IK Pass,这样就可以在脚本中调用IK相关方法

public class AnimatorTest : MonoBehaviour
{[Range(0, 1)]public float weight;private Animator animator;//动画状态private AnimatorStateInfo stateInfo;//关联Multiplier参数private float animationMultiplier = 1;//Multiplier映射的hash值private int multiplierHash;void Start(){animator = GetComponent<Animator>();multiplierHash = Animator.StringToHash("Multiplier");animator.SetFloat(multiplierHash, animationMultiplier);//获取当前动画状态,0表示base layerstateInfo = animator.GetCurrentAnimatorStateInfo(0);//判断动画的Tag是否为Animif (stateInfo.IsTag("Anim")){//do something}}void Update(){if(Input.GetKeyDown(KeyCode.W)){animationMultiplier += 0.1f;animator.SetFloat(multiplierHash, animationMultiplier);}}/// <summary>/// layer上开启IK Pass/// </summary>private void OnAnimatorIK(int layerIndex){//设置右脚IKGoal的位置animator.SetIKPosition(AvatarIKGoal.RightFoot, new Vector3(1,0,0));//权重越高,右脚越靠近设置的位置animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, weight);}
}

调用时机
在这里插入图片描述
在这里插入图片描述
当Animator的Update Mode为Nomal或Unscaled Time,OnAnimatorMove和OnAnimatorIk方法与Update同步,当Update Mode为Animate Physics时,与FixedUpdate同步

状态转换(Transition)

在这里插入图片描述
两个状态之间可以添加多个转换,这样会变成三个箭头,选中右侧的某个转换就可以为其单独设置转换条件,比如条件1和条件2都会触发 idle -> walk 这个转换,分别设置转换条件即可,它们之间是 “或” 的关系

转换的优先级:
1.如果有勾选了Solo,只执行勾选的转换,不考虑其他的
2.勾选的Solo的转换中,哪个条件先满足就执行哪个转换
3.如果条件同时满足,优先执行上面的转换
4.勾选Mute的转换不会执行

在这里插入图片描述
上方可以修改转换名称

Has Exit Time勾选表示条件满足也要播放到某个时间点才执行转换,不勾选需要设置Conditions
Exit Time比例值,0表示从第一帧转换,0.5表示从中间帧开始
Fixed Duration勾选表示转换持续时间按秒计算,否则按百分比计算
Transition Duration转换持续时间
Transition Offset0表示下一个动画状态从第一帧开始播放,0.5表示下一个动画状态从中间一帧开始播放
Transition Duration转换持续时间
Interruption SourceNone 转换不能被打断
Current State 可以被其他相同起始状态的转换打断,设置Ordered Interruption需要优先级更高
Next State 可以被其他相同目标状态的转换打断
Current State Then Next State 有相同状态的转换都可以打断,但起始状态一样的优先级更高
Next State Then Current State 有相同状态的转换都可以打断,但目标状态一样的优先级更高
Ordered Interruption勾选表示转换按照优先级排序,优先级更高的状态才能打断
Conditions转换条件

状态机里只有四个状态,从A到D。当中的所有转换由相应的触发器变量(trigger)来控制
在这里插入图片描述
与A相关的转换有三个
在这里插入图片描述

选中A到B的转换,把Interruption Source设置为Current State且Ordered Interruption勾选
当激活触发器来启动A->B的转换时,从A到B的转换就可以被某些同样从A出发的转换所打断了,因为勾选Ordered Interruption,转换只能被优先级更高的A到C的转换打断

在这里插入图片描述
Trigger类型的参数只要激活就会触发转换,如果与Trigger相关的动画转换并没有被执行,Trigger会一直处于激活状态,直到转换被执行
Conditions可以设置多条,它们之间是 “与” 的关系,必须同时满足才能触发转换,注意如果勾选Has Exit Time,即使条件满足也得等动画播放到Exit Time才能触发转换

Root Motion动画

Root Motion动画自带根位移,会把动画上的位移应用到对象上,有效避免角色动画和实际位移不同步产生的滑步现象。动画文件会在每一帧里直接修改对象的坐标值和角度值(绝对值),而Root Motion则通过相对位移和转角来移动游戏对象

Animator勾选Apply Root Motion后,Unity会让游戏对象会乘以缩放矩阵,旋转矩阵,平移矩阵

public class AnimatorTest : MonoBehaviour
{private Animator animator;void Start(){animator = GetComponent<Animator>();}/// <summary>/// 使用该方法用代码替代动画修改对象位移旋转/// </summary>private void OnAnimatorMove(){//animator.deltaPosition已经考虑了缩放值transform.position += animator.deltaPosition;transform.rotation *= animator.deltaRotation;}
}

在这里插入图片描述
勾选Apply Root Motion并实现OnAnimatorMove,动画由脚本控制

在Generic动画中的使用Root Motion,只需要管理一根根骨骼Root node,实际工作中,美术一般会给模型单独制作一根根骨骼,这个骨骼的作用就是记录模型的位移旋转
在这里插入图片描述
Unity会把Generic动画对这根骨骼的操作当作对游戏对象的操作,Apply Root Motion会把根骨骼节点上的绝对坐标和绝对角度,转换为游戏对象的相对位移和相对转角

在这里插入图片描述
Root Transform Rotation(绕y轴旋转),Root Transform Position(Y)(y方向位移),Root Transform Position(XZ)(水平方向位移),这三个属性与Root Motion相关的动画
在这里插入图片描述
动画文件中的Root Q和Root T表示对游戏对象的旋转和位移,勾选Root Transform Rotation下的Bake Into Pose就不会旋转游戏对象,而是去旋转根骨骼节点,当我们不希望动画带动游戏对象旋转时,就需要勾选这个Bake Into Pose。后面的loop match是检查动画第一帧和最后一帧的吻合度,红色表示不吻合,绿色表示吻合,红色就不要勾选Bake Into Pose
Root Transform Position(Y)下的Bake Into Pose同理,勾选后动画不会影响游戏对象y方向上的位移,而是去修改根骨骼的位移

Root Transform Rotation绕y轴旋转
Bake Into Pose勾选表示旋转只影响骨骼和蒙皮(外观),并不影响游戏对象的旋转,能不能勾选参考loop match
Based Upon游戏对象开始时对准的方向
Original 动画本来的朝向,美术制作时设置的朝向,一般选这个
Root Node Rotation(Generic) 对准根骨骼节点方向,一般不准确
Body Orientation(Humanoid) 对准上半身前方,一般不准确
Offset对旋转做偏移
Root Transform Position(Y)y方向位移
Bake Into Pose勾选表示y方向位移只影响骨骼和蒙皮(外观),并不影响游戏对象的位置,能不能勾选参考loop match
Based Upon垂直方向上把模型的哪个位置对齐到游戏对象的原点
Original 美术在设置的原点,一般选这个
Root Node Rotation(Generic)将根骨骼作为原点
Center of Mass(Humanoid) 质心作为原点
Feet(Humanoid) 脚作为原点,动画复用可能导致Original不准,此时可以选这项
Offsety方向偏移量
Root Transform Position(XZ)水平方向位移
Bake Into Pose勾选表示水平方向位移只影响骨骼和蒙皮(外观),并不影响游戏对象的位置,能不能勾选参考loop match
Based Upon水平方向上把模型的哪个位置对齐到游戏对象的原点
Original 美术在设置的原点,一般选这个
Root Node Rotation(Generic)将根骨骼作为原点
Center of Mass(Humanoid) 质心作为原点

在这里插入图片描述
在动画预览界面点击坐标轴图标就可以显示center of mass,这个质心也被称为body transform,它的位置接近hips骨骼
红色箭头为质心在水平面的投影,我们可以把这个投影当作Root Motion的根骨骼节点,这个点被称为root Transform,代码中这样访问它的位置和方向

private Animator animator;
void Start()
{animator = GetComponent<Animator>();Vector3 bodyTransformPos = animator.bodyPosition;Quaternion bodyTransformRotation = animator.bodyRotation;Vector3 rootTransformPos = animator.rootPosition;Quaternion rootTransformRotation = animator.rootRotation;
}

Humanoid动画中的Root Motion的原理:Unity会计算处一个root transform,Root Motion会把动画文件中描述的root transform的坐标和角度值,转换为相对位移和相对转角,并以此来移动游戏对象

1D混合树

在这里插入图片描述
创建混合树,双击进入,点击 “+” 添加三个Root Motion动画
在这里插入图片描述

Parameter关联一个浮点型参数
三角形示意图横轴是Speed的值,纵轴是片段的权重,随着Speed的值增大,第一个片段权重减小,第二个片段权重增加
Threshold参数Speed为多少时,片段的权重为1
时钟符号片段播放的速度
人形符号是否要镜像动画,仅限人形动画使用
Automate Thresholds取消勾选 Automate Thresholds就可以修改Threshold的值
Compute Thresholds根据片段的一些属性重新计算Threshold,需要Root Motion动画
Speed 速度的绝对值
Velocity X/Y/Z 分别表示Root Motion在三个方向上的位移速度
Angular Speed(Rad)旋转速度,弧度每秒
Angular Speed(Deg)旋转速度,角度每秒
Adjust Time ScaleHomogeneous Speed 自动计算动画播放速度,使多个动画的移动旋转速度相等,idle动画不需要计算,可排除
Reset Time Scale 将所有片段的速度设为1

上图中Compute Thresholds选择Velocity Z,即根据前进后退方向上的速度计算Threshold,动画前进的速度大约是1.745667,后退的速度大约是-1.426688。Adjust Time Scale选择Homogeneous Speed,使得动画速度一致
在这里插入图片描述
Root Motion的速度不一定是匀速的,这里的1.745667是平均速度
在这里插入图片描述
在Animation窗口中观察z方向移动的动画曲线,曲线分成多段并不是线性的

注意:Unity动画做混合时,包含非线性插值计算,无法保证参数Speed为1时,动画速度也为1,这时可以调整播放速度来控制移动速度,把播放速度改成 1/1.745667,这样前进速度就是1

在这里插入图片描述
动画中前进后退的速度是针对原本骨骼的,使用Avatar复用动画后会根据骨骼的缩放值调整速度

public class PlayerMoveTest : MonoBehaviour
{private Animator _animator;private float _forwardSpeed = 1.745667f;private float _backwardSpeed = 1.426688f;private float _targetSpeed;private float _currentSpeed;void Start(){_animator = GetComponent<Animator>();//Root Motion会考虑物体的缩放值,humanScale记录了Avatar对骨骼的缩放//我们不希望整个animator的播放速度都受到影响,修改特定动画状态的Multiplier属性_animator.SetFloat("Multiplier",  1 / _animator.humanScale);Debug.Log("humanScale: " + _animator.humanScale);}void Update(){Move();}void Move(){_currentSpeed = Mathf.Lerp(_currentSpeed, _targetSpeed, 0.5f);_animator.SetFloat("Speed", _currentSpeed);Debug.Log("velocity.z: " + _animator.velocity.z);}public void PlayerMove(InputAction.CallbackContext callbackContext){Vector2 movement = callbackContext.ReadValue<Vector2>();_targetSpeed = movement.y > 0 ? _forwardSpeed * movement.y : _backwardSpeed * movement.y;}
}

在这里插入图片描述
这里使用了Input System

Root Motion与Rigidbody一起使用

引入Root Motion是为了避免实际位移和动画表现位移不同步,Root Motion解决的是同步问题,而不是位移,要控制位移就需要通过脚本的OnAnimatorMove方法,注意:animator的update mode改为animate physics,动画记得Bake into pose

public class PlayerMoveTest : MonoBehaviour
{private Animator _animator;private Rigidbody _rigidbody;private float _forwardSpeed = 1.745667f;private float _backwardSpeed = 1.426688f;private float _targetSpeed;private float _currentSpeed;void Start(){_animator = GetComponent<Animator>();_rigidbody = GetComponent<Rigidbody>();_animator.SetFloat("Multiplier",  1 / _animator.humanScale);}private void OnAnimatorMove(){Move();}void Move(){_currentSpeed = Mathf.Lerp(_currentSpeed, _targetSpeed, 0.5f);_animator.SetFloat("Speed", _currentSpeed);//物理引擎中会修改rigidbody在y方向上的速度Vector3 vector3 = new Vector3(_animator.velocity.x, _rigidbody.velocity.y, _animator.velocity.z);//用animator从Root Motion动画中提取值,传递给受物理引擎影响的rigidbogy_rigidbody.velocity = vector3;}public void PlayerMove(InputAction.CallbackContext callbackContext){Vector2 movement = callbackContext.ReadValue<Vector2>();_targetSpeed = movement.y > 0 ? _forwardSpeed * movement.y : _backwardSpeed * movement.y;}
}

参考

Unity动画系统详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/79951.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构基础8:二叉树oj+层序遍历。

二叉树oj层序遍历 题目一&#xff1a;二叉树的销毁&#xff1a;方法一&#xff1a;前序遍历&#xff1a;方法二&#xff1a;后序遍历&#xff1a; 题目二&#xff1a;二叉树查找值为x的节点方法一&#xff1a;方法二&#xff1a;方法三&#xff1a; 题目三&#xff1a;层序遍历…

透视俄乌网络战之二:Conti勒索软件集团(下)

透视俄乌网络战之一&#xff1a;数据擦除软件 透视俄乌网络战之二&#xff1a;Conti勒索软件集团&#xff08;上&#xff09; Conti勒索软件集团&#xff08;下&#xff09; 1. 管理面板源代码2. Pony凭证窃取恶意软件3. TTPs4. Conti Locker v2源代码5. Conti团伙培训材料6. T…

【Linux从入门到精通】多线程 | 线程互斥(互斥锁)

上篇文章我们对线程 | 线程介绍&线程控制介绍后&#xff0c;本篇文章将会对多线程中的线程互斥与互斥锁的概念进行详解。同时结合实际例子解释了可重入与不被重入函数、临界资源与临界区和原子性的概念。希望本篇文章会对你有所帮助。 文章目录 引入 一、重入与临界 1、1 可…

多线程|多进程|高并发网络编程

一.多进程并发服务器 多进程并发服务器是一种经典的服务器架构&#xff0c;它通过创建多个子进程来处理客户端连接&#xff0c;从而实现并发处理多个客户端请求的能力。 概念&#xff1a; 服务器启动时&#xff0c;创建主进程&#xff0c;并绑定监听端口。当有客户端连接请求…

GitLab使用的最简便方式

GitLab介绍 GitLab是一个基于Git版本控制系统的开源平台&#xff0c;用于代码托管&#xff0c;持续集成&#xff0c;以及协作开发。它提供了一套完整的工具&#xff0c;以帮助开发团队协同工作、管理和部署代码。 往往在企业内部使用gitlab管理代码&#xff0c;记录一下将本地代…

VR航天航空巡展VR科技馆航天主题科普设备沉浸遨游太空

每当飞机飞过头顶&#xff0c;我们总是忍不住抬头去仰望。从嫦娥奔月的神话传说&#xff0c;到莱特兄弟实现了上天翱翔的梦想&#xff0c;人类一直在不断探索更辽阔的天空和浩瀚的宇宙。 航空科普 寻梦而行 普乐蛙VR航天航空巡展&#xff0c;正在湖南郴州如火如荼的进行中&…

arm day2(9.15)数据操作指令,跳转指令,特殊功能寄存器指令,

作业 1.求最大公约数&#xff1a; .text .global _start _start:mov r0,#0x9mov r1,#0x15bl Loop Loop:cmp r0,r1 比较r0寄存器和r1寄存器的中的值beq stop 当两数相同时,退出程序subhi r0,r0,r1 r0>r1 r0 r0 - r1subcc r1,r1,r0 r0<r1 r1 r1 - r0mov pc,lr 恢复现…

【算法与数据结构】108、LeetCode将有序数组转换为二叉搜索树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;这道题给我们的是一个有序数组&#xff0c;并要求构成一个平衡二叉搜索树&#xff0c;二叉搜索树的很容…

CSS 之 grid 网格布局

一、简介 ​ display: grid;用于设置元素内部的布局类型为网格布局&#xff0c;其外显类型为块级元素。该类型的元素将内部分为行和列&#xff0c;划分成一个个单元格&#xff0c;并通过一系列相关属性控制单元格及其内容的布局和大小。 ​ 该属性值的主要应用场景为&#xf…

这个锂电池保护方案来自TIDA-010030

本篇博客只是作为个人记录&#xff0c;拆锂电池有危险&#xff0c;撬棒刺穿外壳可能爆炸&#xff0c;请勿模仿&#xff0c;误操作电池数据可能失效&#xff0c;请勿模仿。 1、简介 1.1、目的 得到该电池的电量计芯片型号、IIC从机地址、通信的实际波形&#xff1b; 1.2、步…

百度飞浆OCR识别表格入门python实践

1. 百度飞桨&#xff08;PaddlePaddle&#xff09; 百度飞桨&#xff08;PaddlePaddle&#xff09;是百度推出的一款深度学习平台&#xff0c;旨在为开发者提供强大的深度学习框架和工具。飞桨提供了包括OCR&#xff08;光学字符识别&#xff09;在内的多种功能&#xff0c;可…

Linux驱动IO篇——异步通知

文章目录 什么是异步通知异步通知和异步IO的区别信号含义应用层使用信号驱动如何实现异步信号驱动实例 什么是异步通知 异步通知在Linux的实现中是通过信号&#xff0c;而信号是在软件层次上对中断机制的一种模拟。这种机制和中断非常类似&#xff0c;所以可以以中断的思想来理…

重新认识交叉编译

1. 我以前对交叉编译的认知 引用正点原子的话来讲就是: 说得对&#xff0c;但是不全面&#xff0c;直到最近项目中遇到了一个例子我才重新认识什么是交叉编译。 2. build/host/target的概念 参考: Cross-Compilation (automake) 参考: Specifying Target Triplets (Autocon…

Python二级 每周练习题18

练习一: 从键盘输入任意字符串&#xff0c;按照下面要求分离字符串中的字符: 1、分别取出该字符串的第偶数位的元素(提醒注意:是按照从左往右数的方式确定字符串的位置) 2、并依次存储到一个列表中; 3、输出这个列表。 答案: ninput(请输入任意字符串:) #创建变量n存放用户…

数据结构入门 — 树的概念与结构

本文属于数据结构专栏文章&#xff0c;适合数据结构入门者学习&#xff0c;涵盖数据结构基础的知识和内容体系&#xff0c;文章在介绍数据结构时会配合上动图演示&#xff0c;方便初学者在学习数据结构时理解和学习&#xff0c;了解数据结构系列专栏点击下方链接。 博客主页&am…

外包干了2个月,技术退步明显。。。。。

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

【多线程】Thread 类 详解

Thread 类 详解 一. 创建线程1. 继承 Thread 类2. 实现 Runnable 接口3. 其他变形4. 多线程的优势-增加运行速度 二. Thread 类1. 构造方法2. 常见属性3. 启动线程-start()4. 中断线程-interrupt()5. 线程等待-join()6. 线程休眠-sleep()7. 获取当前线程引用 三. 线程的状态1. …

Buffer Pool

一.Buffer Pool的含义 Buffer Pool&#xff1a;缓冲池&#xff0c;简称BP&#xff0c;其作用是用来缓存表数据与索引数据&#xff0c;减少磁盘IO操作&#xff0c;提升效率。当Mysql执行查询的sql语句的时候&#xff0c;会先去缓存当中看是否有对应的数据&#xff0c;如果有则直…

显示器显示的画面突然偏红色如何解决

显示器显示的画面突然偏红色如何解决 1. 概述2. 解决方法结束语 1. 概述 显示器显示的画面突然偏红色 &#xff0c;使用向日葵远程电脑&#xff0c;看到的画面是正常的&#xff0c;但是显示器上的画面确还是骗红的&#xff0c;这时候就需要看一下是不是开启了系统也夜间模式&a…

四川百幕晟科技:提升店铺质量方法是什么?

抖店是抖音旗下的移动电子商务平台&#xff0c;为商家提供在线销售和促销的机会。在抖店&#xff0c;经验值是商家评价和信誉的重要指标之一。反映了平台上商户的服务质量和用户满意度。那么&#xff0c;如何查看自己在抖店手机上的体验分数呢&#xff1f; 1、如何查看抖店手机…