上一期中,我们完成了角色在没有任何输入的情况下实现了站立平衡,这期,我们就来聊一下角色的运动吧。

玄夜smile:如何用unity 物理系统 实现Stickfight中火柴人的布娃娃效果(一) ,还没看过第一期的小伙伴们,可以先看下第一期的内容。

在做角色的运动之前,其实还存在一个细节需要处理

大家请看第一期的最后一个演示视频,玩家在自由下落之后,如果没有任何外力的驱动,朝向会一直和初始方向一致(现在就是朝向屏幕),显然,我们是不希望出现这样的情况的,我们希望角色在接收到向左运动的指令之后,就会面朝左方,接收到向右运动的指令之后,就会面朝右方,并且,当角色从面朝左方更改为面朝右方的时候,是有转身过程的,而不是直接更新朝向,看到这里,大家可以先行思考一下这个问题,该怎么解决。

先分析一下,角色各个部件之间是用关节相连的,事实上,在运动过程中,各个刚体之间的相对位置和角度,时刻都处于不稳定的变化中,如果去对每个身体部位去做相关旋转的操作,显然是不合理的。所以,我们需要去操作一个部位,然后让它带动身体的其他部位一起转动,那选哪个部位合适呢,head?还是hip?古人有云,气运丹田,丹田,不就是我们hip的位置嘛,emm~就选hip了。

好了,言归正传,我们认真分析一下,对于head,我们在之前其实已经设计了一个上拉变力m_StandUpForce用于实时作用在上面了,若此时,再在head上添加旋转力,很容易就会让其陷入不稳定的状态,其次,head处于身体的最顶端,依靠head的转动,通过关节,去驱动全身组件转动,其实也不是一个合理的设计,恰恰相反,我们之前设计的hip,身上所有的关节连接,最终都是指向hip的,转动的时候也可以上下兼顾,正好完美的符合条件,所以综合这两点考虑,我选择了hip作为驱动点,来带动身体其他部位的转动。

接下来,就是如何让hip这个部位转动的问题了,我这里使用的是unity提供的物理接口Rigidbody.AddTorque(Vector3 torque,ForceMode mode)。

这个接口什么意思呢,也就是给刚体添加扭矩。学过物理的同学都知道右手定则,而这个接口是基于左手定则,在这个定则的手势下,将你的左手大拇指指向torque向量的方向,这样,刚体将会顺着你的其余手指旋向转动,ok,理解了这个接口的意义之后,我们就可以顺下去继续分析了

如上图,hip.forword代表的是hip刚体的前方,也就是角色的朝向,此时当输入向左指令后,我们希望hip.forword->left,结合刚刚对扭矩接口的分析,我们很容易得到,torque=a*vector3.up,torque就代表长度为a,方向为vector3.up(在这里,是垂直于屏幕向外)的向量,torque作用于刚体时,hip就会顺着torque扭矩向left转动,但是,我们并不希望hip绕着这个方向一直转动,而是到了left,停下来,所以,我们需要实时获取left和hip.forword的角度angle,令a=angle,这样,当角色朝向和left相同时,torque就会被置0,角色的转动就停止啦。

到这里,这个问题也就解决了,为此,我在character父节点下,建立了一个TargetRotation空节点作为辅助节点,如下图

TargetRotation的朝向始终指向input的朝向,这样,就能在update中实时获取angle,在刚体上施加正确的扭矩了。下面就直接上代码,创建BalanceRotation脚本,并挂在character父节点下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//控制人物  左右 旋转
public class BalanceRotation : MonoBehaviour {player mplayer;private Transform mtarget;                           //世界中作为角色转向的标杆public Transform mTarget{get{if(!mtarget){mtarget = transform.Find("TargetRotation");}return mtarget;}}private Rigidbody mhip;private Vector3 mAngle_direction;                //叉乘向量private float mAngle;                            //夹角public int TorqueForce = 30;JointAnimationMgr _jointAnimationMgr;void Start(){mplayer = GetComponent<player>();_jointAnimationMgr = mplayer.m_JointAnimationMgr;mhip = _jointAnimationMgr.m_hip;}private void Update(){if (Input.GetKey(KeyCode.A)){mtarget.rotation = Quaternion.Euler(0, -90, 0);}else if (Input.GetKey(KeyCode.D)){mtarget.rotation = Quaternion.Euler(0, 90, 0);}}void FixedUpdate(){mAngle = Vector3.Angle(mhip.transform.forward, mTarget.forward);                //实时获取TargetRotation与hip的角度差mAngle_direction = Vector3.Cross(mhip.transform.forward, mtarget.forward);AddTorqueWithHip();}/// <summary>/// 根据target点和角色旋转的角度差给对应方向,对应大小力的扭矩/// </summary>void AddTorqueWithHip(){if (mAngle_direction.y>0){mhip.AddTorque(Vector3.up * mAngle* TorqueForce, ForceMode.Acceleration);}else{mhip.AddTorque(-Vector3.up * mAngle * TorqueForce, ForceMode.Acceleration);}}
}

下面是运行之后的效果

ok,到这里,角色转身的问题已经搞定啦~

在角色运动的时候,还有一个细节需要处理,由于角色的所有动作都是由力来驱动的,虽然我把角色身体内各个部件之间的相互碰撞取消了,但角色和场景本身,以及和场景的各个元素之间,将来会发生各种碰撞,导致角色的运动方向和我们预设的方向发生偏差,比如玩家输入右指令,角色在力的驱动下,会向右移动,但有可能碰到一个box,或者其他场景元素,角色会被撞向屏幕内或者屏幕外。为了防止出现这种情况,我们需要单独勾选hip的rigidbody中的z轴限制,如下图,这样,角色就相当于被固定在xoy平面内运动。

现在开始处理角色的运动,新建脚本C_Movement,挂在父节点character下,要让角色动起来,很简单,加力就完事了,直接上代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;角色 行走 跳跃 跑墙 控制public class C_Movement : MonoBehaviour
{public float stepEmptyTime = 0.15f;public float m_HorizonralexternalForce = 45;                                           //控制物体水平移动的外力public float m_Up_Horizon = 100;                                                        //控制物体斜跳的水平力public float m_VerticalexternalForce = 200;                                             //向下的力public float m_jumpForce = 30;                                                         //控制物体跳起的外力public float m_HorizonalWalkForce = 10;                                                //控制物体左走的外力public float m_jumpForceMultiplier = 25;                                              //弹跳系数public float m_torsoForce = 0;                                                        //支撑脖子的力public float m_Down_Vertical = 80;                                                     //控制物体匍匐前进的下压力public Face m_face;     //朝向private BodyDetect m_bodydect;  //检测头部和地面的高度类脚本引用private BalanceRotation m_balanceRotation;private Rigidbody[] m_rigidbodys;private x_PunchForce[] m_collisionForGround;private Vector3 m_wallnormal;        //身体碰撞到墙壁之后得到的碰撞点的法线向量private float m_jumptimer;                                        //跳跃的计时器private float m_jumptime = 0.3f;                                  //跳跃的时间间隔void Start(){m_player = GetComponent<player>();m_jointAnimationMgr = m_player.m_JointAnimationMgr;m_rigidbodys = m_jointAnimationMgr.m_rigids;m_collisionForGround = GetComponentsInChildren<x_PunchForce>();m_bodydect = GetComponent<BodyDetect>();m_balanceRotation = GetComponent<BalanceRotation>();m_jumptimer = 0;}void Update(){m_jumptimer += Time.deltaTime;}private void FixedUpdate(){OnMove();}private void OnMove(){if (Input.GetKey(KeyCode.A) && Input.GetKey(KeyCode.S)){Down_Left();}else if (Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.D)){Down_Right();}else if (Input.GetKey(KeyCode.A) && Input.GetKeyDown(KeyCode.W)){UP_Left();}else if (Input.GetKey(KeyCode.D) && Input.GetKeyDown(KeyCode.W)){UP_Right();}else if (Input.GetKey(KeyCode.D)){MoveRight();}else if (Input.GetKey(KeyCode.A)){MoveLeft();}else if (Input.GetKeyDown(KeyCode.W)){Jump();return;}else if (Input.GetKey(KeyCode.S)){Down();return;}}/// <summary>/// 右跑/// </summary>public void MoveRight(){m_face = Face.right;m_balanceRotation.mTarget.rotation= Quaternion.AngleAxis(90, Vector3.up);for (int i = 0; i < m_rigidbodys.Length; i++){m_rigidbodys[i].AddForce(Vector3.right * m_HorizonralexternalForce*Time.fixedDeltaTime, ForceMode.Acceleration);}m_torso.AddForce(-Vector3.right * m_torsoForce, ForceMode.Force);}/// <summary>/// 左跑/// </summary>public void MoveLeft(){m_face = Face.left;m_balanceRotation.mTarget.rotation = Quaternion.AngleAxis(270, Vector3.up);for (int i = 0; i < m_rigidbodys.Length; i++){m_rigidbodys[i].AddForce(-Vector3.right * m_HorizonralexternalForce* Time.fixedDeltaTime, ForceMode.Acceleration);}m_torso.AddForce(Vector3.right * m_torsoForce, ForceMode.Force);}//左走public void WalkLeft(){m_face = Face.left;m_balanceRotation.mTarget.rotation = Quaternion.AngleAxis(270, Vector3.up);for (int i = 0; i < m_rigidbodys.Length; i++){m_rigidbodys[i].AddForce(-Vector3.right * m_HorizonalWalkForce * Time.fixedDeltaTime, ForceMode.Acceleration);}m_torso.AddForce(Vector3.right * m_torsoForce, ForceMode.Force);}//右走public void WalkRight(){m_face = Face.right;m_balanceRotation.mTarget.rotation = Quaternion.AngleAxis(90, Vector3.up);for (int i = 0; i < m_rigidbodys.Length; i++){m_rigidbodys[i].AddForce(Vector3.right * m_HorizonalWalkForce * Time.fixedDeltaTime, ForceMode.Acceleration);}m_torso.AddForce(-Vector3.right * m_torsoForce, ForceMode.Force);}/// <summary>/// 跳跃/// </summary>public bool Jump(){if (m_jumptimer < m_jumptime){return false;}if ( m_bodydect.IsBodyGround()){PlayJumpEffect();for (int i = 0; i < m_rigidbodys.Length; i++){m_rigidbodys[i].AddForce(Vector3.up * m_jumpForce * Time.fixedDeltaTime, ForceMode.VelocityChange);m_jumptimer = 0;}m_standing.m_gravityFactor = 0;}return true;}void PlayJumpEffect(){float x = m_hip.position.x;float y = (m_rightLeg.position.y + m_leftLeg.position.y) / 2;float z = m_hip.position.z;Vector3 pos = new Vector3(x, y, z);GameObject go = xingnengMgr.getMe().createTexiaoJump(pos, Quaternion.identity);if (go == null)return;go.transform.position = pos;go.transform.rotation = Quaternion.LookRotation(Vector3.up);Destroy(go, 0.5f);}/// <summary>/// 判断是否能爬墙/// </summary>/// <returns></returns>bool Do_WallJump(){for (int i = 0; i < m_collisionForGround.Length; i++){if ( m_collisionForGround[i].IsCollisionWall){this.m_wallnormal = m_collisionForGround[i].wallnormal;return true;}}return false;}/// <summary>/// 下蹲/// </summary>public void Down(){for (int i = 0; i < m_rigidbodys.Length; i++){m_standing.m_StandUpMultiForce = 0;m_rigidbodys[i].AddForce(Vector3.down * m_VerticalexternalForce * Time.fixedDeltaTime, ForceMode.Acceleration);}}/// <summary>/// 左上跳/// </summary>public void UP_Left(){m_balanceRotation.mTarget.rotation = Quaternion.AngleAxis(270, Vector3.up);Jump();for (int i = 0; i < m_rigidbodys.Length; i++){m_rigidbodys[i].AddForce(-Vector3.right * m_Up_Horizon * Time.fixedDeltaTime, ForceMode.Acceleration);}m_face = Face.left;}/// <summary>/// 右上方跳/// </summary>public void UP_Right(){m_balanceRotation.mTarget.rotation = Quaternion.AngleAxis(90, Vector3.up);Jump();for (int i = 0; i < m_rigidbodys.Length; i++){m_rigidbodys[i].AddForce(Vector3.right * m_Up_Horizon * Time.fixedDeltaTime, ForceMode.Acceleration);}m_face = Face.right;}/// <summary>/// 右匍匐前进/// </summary>public void Down_Right(){for (int i = 0; i < m_rigidbodys.Length; i++){m_standing.m_StandUpMultiForce = 0;m_rigidbodys[i].AddForce(Vector3.down * m_Down_Vertical * Time.fixedDeltaTime, ForceMode.Acceleration);}MoveRight();m_face = Face.right;}/// <summary>/// 左匍匐前进/// </summary>public void Down_Left(){for (int i = 0; i < m_rigidbodys.Length; i++){m_standing.m_StandUpMultiForce = 0;m_rigidbodys[i].AddForce(Vector3.down * m_Down_Vertical * Time.fixedDeltaTime, ForceMode.Acceleration);}MoveLeft();m_face = Face.left;}}

这里需要注意的一点是 角色身体的各个身体部位,质量都不一样,所以给每个部位添加相同力的时候,要想各个部位能保持相对位置不变运动,要使用ForceMode.Acceleration 这个模式,可以忽略掉质量。

下面是运行时效果:

看完是不是感觉很软~

终于,到了比较关键的跑步环节,这个环节需要处理角色四肢的摆动问题,先来分析一下

在人物的跑动过程中,我们需要身体上半身躯干甩动方向和人物的运动方向一致,即与hip.velocity的方向一致,所以处理也相对比较简单,直接给上半身躯干加力就可以了,力的方向就是hip.velocity。但这样处理,很容易会使身体的上半部分躯干显得过于硬直,我们更希望上躯干在运动的时候能的处于如下状态

所以,比较简单的处理就是只给elbow和hand加力,然后通过两者的拉力去提起arm,这样就能达到我们要的效果。

对于身体下半身而言,我们希望双腿交替摆动,ok,先拆分逻辑,我们来看一下一只腿交替摆动的效果,在场景中新建一个cube,然后给这个cube加上character joint

connected body指定null就行了,这样,刚体就会默认和世界中的一个空节点连接,空节点相对刚体的位置就是下面配置的anchor。然后我们在update里面每隔0.3s给cube添加相反的力,代码如下:

 private void Update(){timer -= Time.deltaTime;if (timer<=0){timer = 0.3f;flag = !flag;}if (Input.GetKey(KeyCode.P)){if (flag){rigidbody.AddForce(Vector3.right * Time.deltaTime * 50000, ForceMode.Acceleration);}else{rigidbody.AddForce(-Vector3.right * Time.deltaTime * 50000, ForceMode.Acceleration);}}}

运行游戏,效果如下:

怎么感觉有点摆动有点生硬呢。

换个思路,把力改成扭矩来驱动转动,将上面的代码改成如下:

    if (flag){rigidbody.AddForce(Vector3.right * Time.deltaTime * 50000, ForceMode.Acceleration);}else{rigidbody.AddForce(-Vector3.right * Time.deltaTime * 50000, ForceMode.Acceleration);}

运行效果如下:

很明显,看上去更柔和,效果更佳,ok,经过比较,身体下部分躯干我们摒弃用力,换做扭矩去实现。

下面就是思路的问题了,我们新建一个类JointAnimationMgr ,挂于character 父节点下,用它单独来管理角色跑步表演动画,再新建类C_JointAnimation,挂在我们需要表演动画的身体部位 rightelbow,righthand,leftelbow,lefthand,rightleg,leftleg上

另外,C_JointAnimation中我们还需要一个内部配置类用来给这些部位配置动作数据,

//角色动画数据
//u3d面板 配置
/// <summary>
/// 配置角色的Animation信息
/// </summary>
[Serializable]
public class JointAnimationsInfo  {public bool IsBodyLeftSide;                         //是否是身体部位的左侧,在外部配置好的参数public AnimationsType animationsType;               //动画模式public BodyDirection bodyDirection;                 //身体部位public float forwardForceMultiplier;                //向前方向的扭矩参数public float backForceMultiplier;                   //向后方向的扭矩参数public enum AnimationsType{Torque,Force}public enum BodyDirection{MainBodyVelocity,    //和身体运动方向(hip)一致Swing,               //摆动  }
}

ok,现在,我们还需要一个外部参数m_IsleftSideForward布尔变量,用来控制摆动方向,m_IsleftSideForward的值,则是在JointAnimationMgr 管理类进行更新,然后传给各个子部件去更新摆动动画。上代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//处理下肢跑步的动画
public class C_JointAnimation : MonoBehaviour {public JointAnimationsInfo animatioinInfo;private Rigidbody rig;private Rigidbody hip;void Start(){rig = GetComponent<Rigidbody>();hip = transform.root.GetComponentInChildren<Hip>().GetComponent<Rigidbody>();}/// <summary>/// 控制角色跑步身体关节的运动/// </summary>/// <param name="leftForward"></param>public void JointAnimate(bool leftForward){Vector3 dir = Vector3.zero;if (animatioinInfo.bodyDirection== JointAnimationsInfo.BodyDirection.Swing){dir = transform.right;}if (animatioinInfo.bodyDirection==JointAnimationsInfo.BodyDirection.MainBodyVelocity){dir = this.hip.velocity.normalized;}if (animatioinInfo.animationsType==JointAnimationsInfo.AnimationsType.Torque){if ((leftForward && animatioinInfo.IsBodyLeftSide) || (!leftForward && !animatioinInfo.IsBodyLeftSide)){this.rig.AddTorque(dir * Time.deltaTime * -animatioinInfo.backForceMultiplier, ForceMode.Acceleration);}else{this.rig.AddTorque(dir * Time.deltaTime * -animatioinInfo.forwardForceMultiplier, ForceMode.Acceleration);}}if (animatioinInfo.animationsType == JointAnimationsInfo.AnimationsType.Force){if ((leftForward && animatioinInfo.IsBodyLeftSide) || (!leftForward && !animatioinInfo.IsBodyLeftSide)){this.rig.AddForce(dir * Time.deltaTime * -animatioinInfo.backForceMultiplier, ForceMode.Acceleration);}else{this.rig.AddForce(dir * Time.deltaTime * -animatioinInfo.forwardForceMultiplier, ForceMode.Acceleration);}}}
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 关节管理类
/// </summary>
public class JointAnimationMgr : MonoBehaviour {[HideInInspector]public Rigidbody m_leftLeg;[HideInInspector]public Rigidbody m_rightLeg;[HideInInspector]public bool m_IsleftSideForward = false;          //身体的左侧是否在前方[HideInInspector]public bool m_CanStepCross = false;                                               //跑步的时候双腿是否可以交叉C_JointAnimation[] m_jointAnimations;player m_player;public float m_LegAngle = 90;                                                  //双腿之间的夹角public float m_switchTime = 0.2f;                                                //双腿交替的频率private float m_counter;                                                  //计数器void Start(){m_leftLeg = GetComponentInChildren<LeftLeg>().GetComponent<Rigidbody>();m_rightLeg = GetComponentInChildren<RightLeg>().GetComponent<Rigidbody>();m_player = GetComponent<player>();m_jointAnimations = GetComponentsInChildren<C_JointAnimation>();}/// <summary>/// 控制跑步时候腿的交叉/// </summary>void Update(){m_counter += Time.deltaTime;if (m_leftLeg && m_rightLeg && this.m_counter > this.m_switchTime && Vector3.Angle(this.m_leftLeg.transform.up, this.m_rightLeg.transform.up) > m_LegAngle && m_CanStepCross){m_IsleftSideForward =!m_IsleftSideForward;m_counter = 0;}}/// <summary>/// 控制人物的跑步/// </summary>public void RunAnimation(){for (int i = 0; i < m_jointAnimations.Length; i++){m_jointAnimations[i].JointAnimate(this.m_IsleftSideForward);}}
}

看下现在的运行效果:

看起来还不错~,ok,到现在为止,我们已经解决了角色的平衡,角色的转身,角色的基础运动啦,剩下的爬墙,攻击,和渲染,我将在下期为大家讲解。觉得不错的小伙伴记得点个赞哦。

unity 计时器_如何用unity 物理系统 实现Stickfight中火柴人的布娃娃效果(二)相关推荐

  1. freemarker中运算符_如何在Web应用系统表示层开发中应用Velocity模板技术

    软件项目实训及课程设计指导--如何在Web应用系统表示层开发实现中应用Velocity模板技术 1.分离Web表示层的数据处理和展现逻辑的常见的应用技术 分离Web表示层的数据处理和展现逻辑是目前企业 ...

  2. javac 命令的作用_机加工行业MES系统在生产调度中的重要作用

    MES系统的全称是制造执行系统,主要面向车间层次进行信息管理,介于车间内的上层计划管理的系统和下层工业控制执行之间. MES系统作为企业的执行层次,针对企业的生产过程进行优化管理,并加入一定的基层工业 ...

  3. unity的vr场景怎么做_如何用Unity快速创建一个VR体验

    文章相关引用及参考:uxdesign 不断试验Unity3D,探索Asset Store,并尝试创建出令人称奇的体验. (映维网 2017年08月25日)我(Andrew Coyle)一直希望为虚拟现 ...

  4. audio unity 加速_浅谈Unity中Android、iOS音频延迟

    在Unity上面做音游,当在移动端实机运行起来,会发现,音频的发出会有一定的延迟,无论是长音效还是短音效,Unity内置的Audio内部使用的是FMOD,有以下手段改善 通过设置稍微改善其延迟的问题 ...

  5. unity多人游戏_如何使用Unity 2D和镜像构建多人纸牌游戏(更新)

    unity多人游戏 Working with the canvas in Unity 2D can feel complicated at first, particularly if you're ...

  6. python中if语句求最大值_如何用if语句向量化numpy数组中的最大值?

    我的设置:Python 2.7.4.1.numpymkl 1.7.1.windows7x64.WinPython 上下文: 我尝试实现序列最小优化算法来求解支持向量机.我使用最大违反对方法.在 问题是 ...

  7. mysql导出七张表成dtf文件_如何用Java实现把excel表中的数据导入到mysql数据库已有的表中?...

    展开全部 java 读excel 还是比较方便简单的,原理就是,先用java 读取excel,然后,一行行的写入数据库,字段的话32313133353236313431303231363533e4b8 ...

  8. python三个箭头怎么打出来_如何用箭头键在Python 3中移动海龟

    我有解决办法给你.代码并不理想,但它可以工作,您可以对其进行处理.你必须意识到,乌龟的位置不好,你必须调整它.这就是为什么我在设置方法我的乌龟抬头. 现在,您必须记住,right(deg)和left( ...

  9. word中填充效果锁定纵横比_【文艺范】Word文档中的首字下沉效果

    在Word写文档中,有一种很有逼格的文艺范效果,就是首字下沉,我们看下下图. 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 这种效果是如何制作出来的呢? 在插入菜单这里就有首字下沉 ...

最新文章

  1. vim 成“神“之路 (一)
  2. Tony Qu的《WPF揭秘》情节
  3. keras系列︱迁移学习:利用InceptionV3进行fine-tuning及预测、完美案例(五)
  4. weblogic cluster error-----Could not= open connection with host: 127.0.0.1
  5. 魔兽争霸Ⅲ运行时不能初始化directX的错误解决
  6. Linux console on LCD
  7. 为什么高手离不了Linux系统?我想这就是理由!
  8. 手把手教你使用Python网络爬虫获取招聘信息
  9. 微信小程序实现多视频video采坑,上下滑动视频
  10. 计算机文档怎么字符加宽间距,Word2013设置字符间距,如何设置两个字符之间的距离 -电脑资料...
  11. 计算机408考试题库百度云,2017年计算机408考研真题.pdf
  12. python显示.arw相机原始数据,并保存为jpg
  13. 已知随机变量X的协方差矩阵求去X的特征值 特征向量 PCA投影矩阵
  14. Axure原型设计相关资源网站(不断更新中……)
  15. wordpress 安全保密hacks
  16. quartz定时器时间设置规则
  17. Python爬虫帮你抢秒杀
  18. 我与C++一起走过的日子
  19. 防火墙的工作原理!!详解
  20. Android常用实用功能代码片大全

热门文章

  1. Elasticsearch Scripted Metric Aggregation 自定义聚合
  2. 查看磁盘的厂家及详细信息
  3. 闾丘露薇:我的婚姻错在哪
  4. MATLAB-GUI-CALLBACK用法大全
  5. centos7 常用命令
  6. 怎么更改计算机物理地址,win7如何改物理地址_win7电脑怎么更改物理地址
  7. 字符串转16进制和16进制数字解码成字符串的方法 ,适用于所有字符(包括中文)
  8. 杭电5597GTW likes function
  9. K210裸机点灯之旅(1)点亮SSD1306【c开发i2c】
  10. NestJS 7.x 折腾记: (5) 管道,一个好玩的东西!比如入参校验!