JU TPS研究笔记

这个模板的Cover Demo和尘白禁区一样,是自由观察和背后锁定视角可切换的TPS。这种模式比单独做自由观察或背后锁定都要复杂。在非瞄准也就是自由观察状态,鼠标控制相机转动,WASD控制人物以相机前方为前方一边移动一边平滑旋转到面对移动方向。在瞄准/背后锁定状态

这个模板武器绑定在右手,使用IK摆放右手到合适的状态。

移动

模板提供了多种移动方案,包括rigidbody.velocity、transform.Translate、动画根运动。

首先它定义了一个bool RootMotion。

在OnAnimatorMove()里执行ApplyRootMotionOnLocomotion()。 

private void OnAnimatorMove(){ApplyRootMotionOnLocomotion();}

这个函数只有RootMotion为真时才执行。但是我看到RootMotion一直为假,看来并没有用OnAnimatorMove()。那么怎么找到让人物移动的代码?

protected virtual void ApplyRootMotionOnLocomotion(){if (RootMotion && IsGrounded == true && IsJumping == false && !FiringMode && !IsDriving){if (Ragdoller != null) { if (Ragdoller.State != AdvancedRagdollController.RagdollState.Animated) return; }anim.updateMode = AnimatorUpdateMode.AnimatePhysics;RootMotionDeltaPosition = anim.deltaPosition * Time.fixedDeltaTime;RootMotionDeltaPosition.y = 0;///_______________________________________________________________________________________________________________________________________________________// >> NOTE:                                                                                                                                              |/// When decreasing the Time.timeScale, the Animator does not return the delta position correctly, preventing the character from moving in slow motion   |/// If Time Scale is different from 1, instead of rootmotion, normal motion without Root Motion base will be used so that it keeps moving in slow motion.|///_______________________________________________________________________________________________________________________________________________________|if (Time.timeScale == 1){rb.velocity = RootMotionDeltaPosition * 5000 * RootMotionSpeed + Vector3.up * rb.velocity.y;}else{if (CurvedMovement){rb.velocity = transform.forward * VelocityMultiplier * Speed + Vector3.up * rb.velocity.y;}else{rb.velocity = DirectionTransform.forward * VelocityMultiplier * Speed + Vector3.up * rb.velocity.y;}}if (RootMotionRotation){transform.Rotate(0, anim.deltaRotation.y * 160, 0);}}}

对RootMotion寻找所有引用:

找到Movement(),它在FixedUpdate()里被调用。把它注释,人物不会再移动了,说明移动的代码在这里面。再看到里面调用了两个函数:

// Default Free LocomotionDoFreeMovement(FiringMode);//Default Fire Mode LocomotionDoFireModeMovement(FiringMode);

然后把DoFreeMovement()注释,人物不瞄准时不能移动了,瞄准时可以移动。然后在这里打印FiringMode,发现没瞄准时打印false,瞄准时打印true(注意如果一个脚本在场景里有多个实例,想研究这个脚本前先只留下一个,其他的全部失活)。而且这两个函数里有渐变设置瞄准层权重的代码:

IsArmedWeight = Mathf.Lerp(IsArmedWeight, 0, 3 * Time.deltaTime);

再看DoFreeMovement(),里面有

if (IsGrounded && CanMove && !RootMotion){if (CurvedMovement == true){MoveForward(VelocityMultiplier);}else{Move(DirectionTransform, VelocityMultiplier);}}

打印发现一直在执行MoveForward()。 移动方法里根据SetRigidbodyVelocity是否为true,都有使用刚体velocity还是transform.Translate()移动两种方案。能感觉到使用刚体velocity移动时会受到墙的摩擦力。但是这个刚体运动经过处理,能上楼梯。

public virtual void Move(Vector3 Movement, float SpeedMultiplier){if (SetRigidbodyVelocity){rb.velocity = Movement * SpeedMultiplier * Speed;}else{transform.Translate(Movement * SpeedMultiplier * Speed * Time.deltaTime, Space.World);}}

定义了一个对象DirectionTransform。经过研究这个对象用来指向当前人物将要转向的方向。人物没有瞄准时移动是一边移动一边转向目标方向。不过好像也没有必要添加这个对象,使用相机的正前方就可以。

[HideInInspector] public Transform DirectionTransform;

FiringMode,自由观察移动和瞄准移动

在脚本里FiringMode用于记录人物是不是瞄准状态。

自由观察对应的前进+转弯移动模式放在Base Layer,背后锁定移动模式在Legs Motion Layer。没有瞄准时Legs Motion Layer权重为0。

背后锁定对应的8方向移动放在Legs Motion Layer。瞄准时Legs Motion Layer权重为1。

CurvedMovement的作用

在自由观察移动时,如果相机看向人物后方,按W时,true是向人物的正前方移动,false是向相机的前方移动,也就是人物做前进动画,倒着移动。

但因为人物很快就转向相机前方了,两个情况效果区别不大。

上楼梯

刚体本身不能上楼梯,这里在StepCorrectionMovement()函数做了处理。

跳跃

首先这个模板人物使用了刚体+碰撞体。

在JUCharacterController脚本里的ControllerInputs()函数里:

 //Jumpif (JUInput.GetButton(JUInput.Buttons.JumpButton) && IsJumping == false){_Jump();}//New Jump Delay_NewJumpDelay(0.2f, DecreaseSpeedOnJump);

_Jump()函数是这样的:如果人物不满跳跃的条件(不在地上、在跳跃、在滚、在开车……)就GetUp(),GetUp就是如果是趴着,就蹲,如果蹲着,就站。然后又通过名字判断状态机是否处于4种状态,分别是爬行不拿枪移动、正在趴下、爬行拿枪移动、蹲起,如果是就不跳。(我刚开始写人物动作控制时也曾通过判断当前状态名称判断能不能做某个动作,后来发现可以让动画关键帧设置一个bool字段,判断这个bool知道能不能做某个动作)然后是一些状态字段切换。然后是跳跃的核心代码rigidbody.AddForce()。然后下面那一块,SetRigidbodyVelocity==false里面是移动中跳跃时保持水平速度。如果SetRigidbodyVelocity==true,移动本身就使用刚体速度,就不用另外处理。

public virtual void _Jump(){if (IsGrounded == false || IsJumping == true || IsRolling == true || IsDriving == true || CanJump == false || IsProne || IsRagdolled){_GetUp();return;}if (anim.GetCurrentAnimatorStateInfo(0).IsName("Prone Free Locomotion BlendTree") ||anim.GetCurrentAnimatorStateInfo(0).IsName("CrouchToProne") ||anim.GetCurrentAnimatorStateInfo(0).IsName("Prone FireMode BlendTree") ||anim.GetCurrentAnimatorStateInfo(0).IsName("Prone To Crouch")) return;//Change StatesIsGrounded = false;IsJumping = true;CanJump = false;IsCrouched = false;//Add Forcerb.AddForce(transform.up * 200 * JumpForce, ForceMode.Impulse);if (SetRigidbodyVelocity == false){rb.AddForce(DirectionTransform.forward * LastVelMult * rb.mass * Speed, ForceMode.Impulse);VelocityMultiplier = 0;}//Disable IsJumping state in 0.3sInvoke(nameof(_disablejump), 0.3f);}

跳跃中的移动

跳跃中的移动由两部分组成,一个是刚体的速度,取决于跳跃瞬间的速度;一个是In Air Control Force,是跳跃中可控制的移动。

人物控制器有一个In Air Control Force字段,在脚本里叫

public float AirInfluenceControll = 0.5f;

控制人物在空中的移动速度。 

然后注意到InAirMovementControl()函数,看起来是处理跳跃中移动的。在空中时打印刚体的速度,移动中跳跃时刚体水平速度不为0,说明是通过刚体的惯性实现跳跃中移动。但是没勾选SetRigidbodyVelocity时没有用刚体velocity移动(打印刚体velocity可以证明)

public void InAirMovementControl(bool JumpInert = true){if (IsGrounded){if (JumpInert){LastX = HorizontalX;LastY = VerticalY;LastVelMult = VelocityMultiplier;CanMove = true;}}else{transform.Translate(0, -1f * Time.deltaTime, 0);//if (SetRigidbodyVelocity)//{//    if (IsMoving) rb.AddForce(DirectionTransform.forward * AirInfluenceControll * 10, ForceMode.Force);//}//else//{if (IsMoving){transform.Translate(DirectionTransform.forward * AirInfluenceControll / 2 * Time.deltaTime, Space.World);}//}}}

改变仰角

使用了一个Weapon Aim Rotation Center对象负责记录拿各种武器的IKGoal对象,它的脚本里面有两个List分别是这类武器IK位置的名字和Transform:

05996770e5554d90a7db3e3ee53b27a9.png

这个Weapon Aim Rotation Center对象没运行时是人物的子对象,开机瞄后变成根对象了。

它会随鼠标上下移动改变仰角,把各种武器的IK目标带到合适的位置旋转。

趴下时会改变Weapon Aim Rotation Center的位置和旋转。

然后查看人物脚本的IK部分:

void OnAnimatorIK(int layerIndex){if (IsDead || InverseKinematics == false) return;//Get Original Spine RotationOriginalSpineRotation = anim.GetBoneTransform(HumanBodyBones.Spine).transform.localRotation;//Firing Mode IKif (IsRolling == false && IsDriving == false){//If you have problems with the elbow ik on your left arm, uncomment the line below//LeftHandToRespectiveIKPosition(LeftHandWeightIK, LeftHandWeightIK / 1.2f);LeftHandToRespectiveIKPosition(LeftHandWeightIK, 0);RightHandToRespectiveIKPosition(RightHandWeightIK, RightHandWeightIK / 1.2f);Vector3 LookingPosition = GetLookPosition();float BodyWeight = (IsProne) ? 0.1f : 0.3f;float LookingIntensity = Vector3.Dot(transform.forward, (LookingPosition - transform.position).normalized);LookAtIK(LookingPosition, LookingIntensity * LookWeightIK, BodyWeight, 0.6f);}}

然后去查这个RightHandToRespectiveIKPosition(),里面就是设置IK的API:

public void RightHandToRespectiveIKPosition(float IKWeight, float ElbowAdjustWeight = 0){if (IKWeight == 0) return;anim.SetIKRotationWeight(AvatarIKGoal.RightHand, IKWeight);anim.SetIKPositionWeight(AvatarIKGoal.RightHand, IKWeight);anim.SetIKPosition(AvatarIKGoal.RightHand, IKPositionRightHand.position);anim.SetIKRotation(AvatarIKGoal.RightHand, IKPositionRightHand.rotation);if (ElbowAdjustWeight == 0) return;anim.SetIKHintPositionWeight(AvatarIKHint.RightElbow, ElbowAdjustWeight);Vector3 hintPos = PivotItemRotation.transform.position + PivotItemRotation.transform.right * 2 + PivotItemRotation.transform.forward * 1 - PivotItemRotation.transform.up * 3f;anim.SetIKHintPosition(AvatarIKHint.RightElbow, hintPos);}

然后去看这个IKPositionRightHand是哪来的。在Awake()里创建了左右手IK Target 和IK Position,IK Position应该是当前帧IK的位置,Target则是它要去到的位置,这是为了做平滑运动。

// Generate Inverse Kinematics Transforms
LeftHandIKPositionTarget = CreateEmptyTransform("Left Hand Target", transform.position, transform.rotation, transform, false);
RightHandIKPositionTarget = CreateEmptyTransform("Right Hand Target", transform.position, transform.rotation, transform, false);IKPositionLeftHand = CreateEmptyTransform("Left Hand IK Position", transform.position, transform.rotation, transform, true);
IKPositionRightHand = CreateEmptyTransform("Right Hand IK Position", transform.position, transform.rotation, transform, true);

创建IK Posotion时还把它们在Hierarchy隐藏了:

再去看哪里设置IK Target,在SmoothRightHandPosition(),从上面那个各类武器IK的管理脚本WeaponAimRotationCenter里取出这类武器的IK位置旋转:

//Get target transformations
Quaternion rightHandRotation = WeaponHoldingPositions.WeaponPositionTransform[HoldableItemInUseRightHand.ItemWieldPositionID].rotation;
Vector3 rightHandPosition = WeaponHoldingPositions.WeaponPositionTransform[HoldableItemInUseRightHand.ItemWieldPositionID].position;//Set Right Hand IK Target Position
SetRightHandIKPosition(rightHandPosition, rightHandRotation);

设置IK Target位置旋转还封装了一层,纯吃饱了撑的。

public void SetRightHandIKPosition(Vector3 Position, Quaternion Rotation){RightHandIKPositionTarget.position = Position;RightHandIKPositionTarget.rotation = Rotation;
}

然后看SmoothRightHandPosition()在哪里调用了,在WieldingIKWeightController()里调用了:

private void WieldingIKWeightController(){//Disable FireMode IK when isn't in FireModeif (FiringMode == false) FiringModeIK = false;// Hands IKif (IsItemEquiped){SmoothLeftHandPosition(25);SmoothRightHandPosition(25);

 WieldingIKWeightController()在Update()里调用了:

void Update(){if (JUPauseGame.IsPaused) return;FootPlacementIKController();GroundCheck();HealthCheck();SetAnimatorParameters();SetupDefaultLayersWeights();if (IsDead) return;DrivingCheck();WallAHeadCheck();if (DisableAllMove == false){ControllerInputs();StepCorrectionCalculation();Rotate(HorizontalX, VerticalY);RefreshItemAimRotationPivot();WieldingIKWeightController();WeaponOrientator();}else{LegsLayerWeight = Mathf.Lerp(LegsLayerWeight, 0, 8 * Time.deltaTime);}Events.UpdateRuntimeEventsCallbacks(this);}

因为Weapon Aim Rotation Center跟随人物根对象,所以瞄准移动时能看见人物身体上下晃动,但是枪保持稳定。尘白禁区的人物移动也有这个现象,所以很可能也是这种架构,即通过绑定在人物根对象的IK目标对象把双手摆在合适的位置,瞄准移动时枪异常的稳定。

武器绑定

枪绑定在右手上。

346f468ac86648669ebab4ee35e26258.png

枪的位置旋转是不规则的数据,且每把枪不一样……那这些数据要怎么记录?

29c39ae3f92f4dc484b517183c5c5ea4.png7f4405f916ec44d4bb95169be36eb2c7.pnga0490b352af3455592a46c5290db1438.png

答案是:所有枪都在手上挂一份,身上挂一份,使用的时候把手上的枪激活,身上的枪隐藏。只存在枪的激活和隐藏,不需要在手、后背之间转移。

74f81d6c0dda45dc8f3513c47c38844b.png

相机和人物的关系

二者没有直接的父子关系。

7718a84269f4484ebeab2d2b7f56ff25.png

ThirdPerson Camera Controller对象通过脚本固定在人物身上,旋转和世界一致。

Camera Pivot记录了相机的方向和仰角。Main Camera固定在Camera Pivot后上方。

从输入到执行

这个模板使用了新输入系统InputSystem,但是没用PlayerInput组件,而是直接用.inputactions生成的脚本。

各种动作bool

在JUInputManager里,定义了所有按键按下、按住、抬起的bool:

[HideInInspector]public bool PressedShooting, PressedAiming, PressedReload, PressedRun, PressedJump, PressedPunch,PressedCrouch, PressedProne, PressedRoll, PressedPickup, PressedInteract, PressedNextItem, PressedPreviousItem;//OnDown[HideInInspector]public bool PressedShootingDown, PressedAimingDown, PressedReloadDown, PressedRunDown, PressedJumpDown, PressedPunchDown,PressedCrouchDown, PressedProneDown, PressedRollDown, PressedPickupDown, PressedInteractDown, PressedNextItemDown, PressedPreviousItemDown, PressedOpenInventoryDown;//OnUp[HideInInspector]public bool PressedShootingUp, PressedAimingUp, PressedReloadUp, PressedRunUp, PressedJumpUp, PressedPunchUp,PressedCrouchUp, PressedProneUp, PressedRollUp, PressedPickupUp, PressedInteractUp, PressedNextItemUp, PressedPreviousItemUp;

在Update()里不停检测哪些按钮被按下、按住:

protected virtual void UpdateGetButtonDown(){PressedJumpDown = InputActions.Player.Jump.triggered;PressedRunDown = InputActions.Player.Run.triggered;PressedPunchDown = InputActions.Player.Punch.triggered;PressedRollDown = InputActions.Player.Roll.triggered;PressedProneDown = InputActions.Player.Prone.triggered;PressedCrouchDown = InputActions.Player.Crouch.triggered;PressedShootingDown = InputActions.Player.Fire.triggered;PressedAimingDown = InputActions.Player.Aim.triggered;PressedReloadDown = InputActions.Player.Reload.triggered;PressedPickupDown = InputActions.Player.Pickup.triggered;PressedInteractDown = InputActions.Player.Interact.triggered;PressedNextItemDown = InputActions.Player.Next.triggered;PressedPreviousItemDown = InputActions.Player.Previous.triggered;PressedOpenInventoryDown = InputActions.Player.OpenInventory.triggered;
protected virtual void UpdateGetButton(){PressedJump = InputActions.Player.Jump.ReadValue<float>() == 1;PressedRun = InputActions.Player.Run.ReadValue<float>() == 1;PressedPunch = InputActions.Player.Punch.ReadValue<float>() == 1;PressedRoll = InputActions.Player.Roll.ReadValue<float>() == 1;PressedProne = InputActions.Player.Prone.ReadValue<float>() == 1;PressedCrouch = InputActions.Player.Crouch.ReadValue<float>() == 1;PressedShooting = InputActions.Player.Fire.ReadValue<float>() == 1;PressedAiming = InputActions.Player.Aim.ReadValue<float>() == 1;PressedReload = InputActions.Player.Reload.ReadValue<float>() == 1;PressedPickup = InputActions.Player.Pickup.ReadValue<float>() == 1;PressedInteract = InputActions.Player.Interact.ReadValue<float>() == 1;PressedNextItem = InputActions.Player.Next.ReadValue<float>() == 1;PressedPreviousItem = InputActions.Player.Previous.ReadValue<float>() == 1;

然后定义了一个叫Buttons的枚举:

public enum Buttons{ShotButton, AimingButton, JumpButton, RunButton, PunchButton,RollButton, CrouchButton, ProneButton, ReloadButton,PickupButton, EnterVehicleButton, PreviousWeaponButton, NextWeaponButton, OpenInventory}

 然后用GetButtonDown()返回指定按钮是否被按下、按住(直接用InputActions的API不行吗?):

public static bool GetButtonDown(Buttons Button){GetJUInputInstance();switch (Button){case Buttons.ShotButton:return JUInputInstance.PressedShootingDown;case Buttons.AimingButton:return JUInputInstance.PressedAimingDown;case Buttons.JumpButton:return JUInputInstance.PressedJumpDown;case Buttons.RunButton:return JUInputInstance.PressedRunDown;case Buttons.PunchButton:return JUInputInstance.PressedPunchDown;case Buttons.RollButton:return JUInputInstance.PressedRollDown;case Buttons.CrouchButton:return JUInputInstance.PressedCrouchDown;case Buttons.ProneButton:return JUInputInstance.PressedProneDown;case Buttons.ReloadButton:return JUInputInstance.PressedReloadDown;case Buttons.PickupButton:return JUInputInstance.PressedPickupDown;case Buttons.EnterVehicleButton:return JUInputInstance.PressedInteractDown;case Buttons.PreviousWeaponButton:return JUInputInstance.PressedPreviousItemDown;case Buttons.NextWeaponButton:return JUInputInstance.PressedNextItemDown;case Buttons.OpenInventory:return JUInputInstance.PressedOpenInventoryDown;default:return false;}}
public static bool GetButton(Buttons Button){GetJUInputInstance();switch (Button){case Buttons.ShotButton:return JUInputInstance.PressedShooting;case Buttons.AimingButton:return JUInputInstance.PressedAiming;case Buttons.JumpButton:return JUInputInstance.PressedJump;case Buttons.RunButton:return JUInputInstance.PressedRun;case Buttons.PunchButton:return JUInputInstance.PressedPunch;case Buttons.RollButton:return JUInputInstance.PressedRoll;case Buttons.CrouchButton:return JUInputInstance.PressedCrouch;case Buttons.ProneButton:return JUInputInstance.PressedProne;case Buttons.ReloadButton:return JUInputInstance.PressedReload;case Buttons.PickupButton:return JUInputInstance.PressedPickup;case Buttons.EnterVehicleButton:return JUInputInstance.PressedInteract;case Buttons.PreviousWeaponButton:return JUInputInstance.PressedPreviousItem;case Buttons.NextWeaponButton:return JUInputInstance.PressedNextItem;default:return false;}}

 好的现在我们知道他的流程是InputActions.Player.XXX.triggered或InputActions.Player.XXX.ReadValue<float>()传到bool PressedXXX或PressedXXXDown,再通过GetButton()或GetButtonDown()。

移动和旋转float

定义:

//Move and Rotate Axis[HideInInspector] public float MoveHorizontal;[HideInInspector] public float MoveVertical;[HideInInspector] public float RotateHorizontal;[HideInInspector] public float RotateVertical;

赋值:在UpdateAxis()里,在Update()里执行。

MoveHorizontal = InputActions.Player.Move.ReadValue<Vector2>().x;MoveVertical = InputActions.Player.Move.ReadValue<Vector2>().y;MoveHorizontal = Mathf.Clamp(MoveHorizontal, -1, 1);MoveVertical = Mathf.Clamp(MoveVertical, -1, 1);

 和上面bool一样,通过GetAxis()输入轴的枚举,返回轴值。在Unity输入系统外封装了一层。

在人物脚本里也定义了一组移动旋转float

//MOVEMENT VARIABLES[HideInInspector] public float VelocityMultiplier;protected float VerticalY;protected float HorizontalX;

赋值:在ControllerInputs()里,在Update()里执行。

if (!BlockHorizontalInput) HorizontalX = JUInput.GetAxis(JUInput.Axis.MoveHorizontal);if (!BlockVerticalInput) VerticalY = JUInput.GetAxis(JUInput.Axis.MoveVertical);

 IsMoving会通过这两个float赋值:

IsMoving = (Mathf.Abs(VerticalY) != 0 || Mathf.Abs(HorizontalX) != 0);

背包系统

背包的脚本是人物身上的Inventory

物品的继承关系:

显示背包内容

在68行Awake()执行的SetSlots(),里面执行了每个格子的RefreshSlot()。

打开背包面板

按TAB打开背包面板,代码在InventoryUIManager的135行,Update()里。通过对象激活失活开关。

if (JUInputSystem.JUInput.GetButtonDown(JUInputSystem.JUInput.Buttons.OpenInventory)){if (!InventoryScreen.activeInHierarchy) { OpenInventory(); } else { ExitInventory(); }}public void OpenInventory(){if (InventoryScreen == null) return;InventoryScreen.SetActive(true);if (IsLootView) return;if (ShowCursorWhenOpenInventory){JUCameraController.LockMouse(false, false);}}

拾取物品 

检测拾取物品的函数是CheckItemsAround(),在Update()里执行,使用Physics.OverlapSphere()。会得到多个碰撞体,但是他只检测第一个。

记录拥有的物品

人物身上绑定有所有人物可能拥有的物品,每个物品有一个unlocked字段,unlocked就是拥有的。

碰撞体

模板支持站、蹲、趴,需要改变碰撞体高度和方向。但是他是用了一个脚本每一帧都在改变碰撞体大小。

物品系统

这个模板好像没有配表。因为很多同种物品相同的信息都放在预制体脚本里,好像初学者很容易这样写,把预制体当作信息中心。不难想象这样在物品很多的场景里会多占很多内存。

总结

为什么这个模板的代码看起来是屎山,原因有

  • 它在Update()或FixUpdate()里无脑执行所有动作函数,然后用一大堆bool判断这个函数是应该执行还是应该跳过。
  • 巨量的bool字段:有一些状态其实是互斥的,应该用int,比如人物不可能既蹲又趴。

  • 用代码做了一些适合动画做的功能,比如切换武器时武器的平滑运动; 

这个模板功能大而全,但是代码繁琐,难以读懂,运行开销估计也很大。没有用配表导致多占用了内存;交互功能使用范围检测但是只处理第一个交互对象,导致玩家难以获得想要的交互选项;

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

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

相关文章

[NewStarCTF 2023 公开赛道]ez_sql1 【sqlmap使用/大小写绕过】

题目&#xff1a; 发现id处可以sql注入&#xff1a; 虽然输入id1;show databases;#没什么回显&#xff0c;但是知道这里是字符型注入了 这次利用sqlmap注入 --dbs&#xff1a;列出所有数据库名字 python .\sqlmap.py -u http://a40b2f0a-823f-4c99-b43c-08b94ed0abb2.node5.…

DeepSeek-实用集成大礼包

随着DeepSeek的持续火热,在各种平台看到大家基于deepseek+各类应用的案例。这些案例真假难辨,现在DeepSeek已经推出了官方的Awesome DeepSeek Integrations,集成了各类应用,下面是详细的介绍。 DeepSeek Integrations 是 DeepSeek 官方在 GitHub 上精心整理的一个集合了各种…

Ubuntu安装问题汇总

参考文章&#xff1a; 【Ubuntu常用快捷键总结】 【王道Python常用软件安装指引】 1. 无法连接虚拟设备 sat0:0 【问题】&#xff1a;出现下图所示弹框。 【问题解决】&#xff1a; 点击 “否” 。 点击左上角的 “虚拟机” → “设置…” → “CD/DVD (SATA)” &#xff0c;…

深陷帕金森困境,怎样重燃生活信心?

帕金森&#xff0c;这个悄然影响无数中老年人生活的神经系统疾病&#xff0c;正逐渐走进大众视野。患病后&#xff0c;患者常出现静止性震颤&#xff0c;安静时手部、下肢不自主抖动&#xff0c;如同在默默诉说着身体的异常。肢体变得僵硬&#xff0c;行动迟缓&#xff0c;起步…

空间遥感智能处理技术发展现状与趋势

在数字化时代&#xff0c;空间遥感技术已经成为获取地球表面信息的重要手段。随着卫星遥感技术的快速发展&#xff0c;获取的遥感数据量激增&#xff0c;这对遥感数据的智能处理提出了更高的要求。本文将探讨空间遥感智能处理技术的发展现状与未来趋势。 发展现状 大数据与人工…

svn删除所有隐藏.svn文件,文件夹脱离svn控制

新建一个文件&#xff0c;取名remove-svn-folders.reg&#xff0c;输入如下内容&#xff1a; Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN] "Delete SVN Folders" [HKEY_LOCAL_MACHINE\SOFTWARE\Class…

Datawhale coze-ai-assistant 笔记2

目录 快速搭建一个 AI 助手智能体 搭建步骤 步骤1&#xff1a;创建一个智能体 步骤2&#xff1a;编写提示词 步骤3&#xff1a;调试智能体 步骤4&#xff1a;发布智能体 设置智能体模型 选择模型 生成多样性 输入及输出设置 如何使用 步骤1&#xff1a;更换模型 步…

win10电脑鼠标速度突然变的很慢?

电脑鼠标突然变很慢&#xff0c;杀毒检测后没问题&#xff0c;鼠标设置也没变&#xff0c;最后发现可能是误触鼠标的“DPI”调节键。 DPI调节键在鼠标滚轮下方&#xff0c;再次点击即可恢复正常鼠标速度。 如果有和-的按键&#xff0c;速度变快&#xff0c;-速度变慢。 图源&…

若依RuoYi-Cloud-Plus微服务版(完整版)前后端部署

一.目标 在浏览器上成功登录进入 二.源码下载 后端源码&#xff1a;前往Gitee下载页面(https://gitee.com/dromara/RuoYi-Cloud-Plus)下载解压到工作目录。 前端源码&#xff1a; 前往Gitee下载页面(https://gitee.com/JavaLionLi/plus-ui)下载解压到工作目录。 文档地址&a…

vue3+elementuiplus的table表格动态高度

table表格流体高度 1、前提 了解自定义指令、hooks 2、核心思路 通过自定义指令&#xff08;new ResizeObserver&#xff09;监听表格变化&#xff0c;然后通过hooks去更新表格高度。 3、核心代码 src/directives/resize.ts // import { debounce } from /utils;import { t…

Django与数据库

我叫补三补四&#xff0c;很高兴见到大家&#xff0c;欢迎一起学习交流和进步 今天来讲一讲alpha策略制定后的测试问题 mysql配置 Django模型体现了面向对象的编程技术&#xff0c;是一种面向对象的编程语言和不兼容类型能相互转化的编程技术&#xff0c;这种技术也叫ORM&#…

VMware下载安装Ubuntu详解

一、Linux简介 1、不同领域的主流操作系统 桌面操作系统服务器操作系统移动设备操作系统嵌入式操作系统 1.1、桌面操作系统 Windows&#xff08;用户数量最多&#xff09;Mac OS&#xff08;苹果电脑操作系统&#xff09;Linux&#xff08;用户数量少&#xff09; 1.2、服…

动态规划详解(二):从暴力递归到动态规划的完整优化之路

目录 一、什么是动态规划&#xff1f;—— 从人类直觉到算法思维 二、暴力递归&#xff1a;最直观的问题分解方式 1. 示例&#xff1a;斐波那契数列 2. 递归树分析&#xff08;以n5为例&#xff09; 3. 问题暴露 三、第一次优化&#xff1a;记忆化搜索&#xff08;Memoiza…

下降路径最⼩和(medium)

题目描述&#xff1a; 给你一个 n x n 的 方形 整数数组 matrix &#xff0c;请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始&#xff0c;并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列&#xff08…

YashanDB认证,YCA证书认证教程,免费证书,内含真题考试题库及答案——五分钟速成

目录 一.账号及平台注册登录流程 二.登录进行设备调试核验 三.考试&#xff08;考完获取分数&#xff09; 四.获取证书 五.题库及答案 一.账号及平台注册登录流程 1-点击这里进行账号注册&#xff08;首次学习必须先注册&#xff0c;有账号之后可以直接在2号链接登录&#…

texstudio: 编辑器显示行号+给PDF增加行号

texstudio在编辑器部分增加行号&#xff1a; texstudio默认在编辑器部分不显示行号&#xff0c;如下图&#xff1a; 要实现以下的在编辑部分增加行号&#xff1a; 执行如下操作&#xff1a; 选项-->设置TexStudio-->编辑器-->显示行号-->所有行号选择好后&…

解决vscode中出现“无法将pip项识别...“问题

问题 遇见问题如下&#xff1a; 查看pip 通过 winR &#xff0c;输入 cmd&#xff0c;进入终端&#xff0c;搜索 where pip。 发现 pip 查不出来&#xff0c;然后进入文件资源管理器&#xff0c;搜索 Scripts 文件夹&#xff0c;如果没有找到可能是电脑没有下载 python。 点击…

【webrtc debug tools】 rtc_event_log_to_text

一、rtc_event_log 简介 在学习分析webrtc的过程中&#xff0c;发现其内部提供了一个实时数据捕获接口RtcEventLog。通过该接口可以实时捕获进出webrtc的RTP报文头数据、音视频配置参数、webrtc的探测数据等。其内容实现可参考RtcEventLogImpl类的定义。其文件所在路径 loggin…

华为eNSP:2.配置OSPF报文分析和验证

一、OSPF的5种数据包 Hello包&#xff1a;用于发现和维护邻居关系。定期发送&#xff0c;确保邻居路由器在线。 数据库描述包&#xff08;DBD, Database Description Packet&#xff09;&#xff1a;在邻居关系建立后&#xff0c;用于交换链路状态数据库的摘要信息。 链路状…

初次体验Tauri和Sycamore(3)通道实现

​ 原创作者&#xff1a;庄晓立&#xff08;LIIGO&#xff09; 原创时间&#xff1a;2025年03月10日&#xff08;发布时间&#xff09; 原创链接&#xff1a;https://blog.csdn.net/liigo/article/details/146159327 版权所有&#xff0c;转载请注明出处。 20250310 LIIGO备注&…