20240117-【UNITY 学习】增加墙跑功能和跳墙功能

替换脚本PlayerCam_01.cs

在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class PlayerCam_02 : MonoBehaviour
{
    // 视觉灵敏度参数
    public float sensX = 400;
    public float sensY = 400;

    // 视角垂直旋转角度限制
    public float minAngle = -90f;
    public float maxAngle = 90f;

    // 角色朝向的 Transform,用于水平旋转
    public Transform orientation;
    public Transform camHolder;

    // 当前的 X 和 Y 旋转角度
    private float xRotation;
    private float yRotation;

    private void Start()
    {
        // 初始时锁定鼠标光标并隐藏光标
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    private void Update()
    {
        // 获取鼠标输入
        float mouseX = Input.GetAxisRaw("Mouse X") * Time.deltaTime * sensX;
        float mouseY = Input.GetAxisRaw("Mouse Y") * Time.deltaTime * sensY;

        // 更新水平旋转角度
        yRotation += mouseX;

        // 更新垂直旋转角度,并限制在指定范围内
        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, minAngle, maxAngle);

        // 应用旋转到摄像机的 Transform 上,实现视角旋转
        camHolder.rotation = Quaternion.Euler(xRotation, yRotation, 0);

        // 应用水平旋转到角色的 Transform 上,使角色朝向与摄像机一致
        orientation.rotation = Quaternion.Euler(0, yRotation, 0);
    }

    // 修改相机视野的动画方法
    public void DoFov(float endValue)
    {
        GetComponent<Camera>().DOFieldOfView(endValue, 0.25f);
    }

    // 修改物体本地旋转的动画方法
    public void DoTilt(float zTilt)
    {
        transform.DOLocalRotate(new Vector3(0, 0, zTilt), 0.25f);
    }
}

替换脚本PlayerMovement_03.cs和Sliding.cs,并新增脚本WallRunning.cs

在这里插入图片描述
在这里插入图片描述

PlayerMovement_04.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement_04 : MonoBehaviour
{
    private float moveSpeed; // 玩家移动速度
    public float walkSpeed = 7; // 行走速度
    public float sprintSpeed = 10; // 冲刺速度
    public float slideSpeed = 30; // 滑动速度
    public float wallrunSpeed = 8.5f;

    private float desiredMoveSpeed; // 期望的移动速度
    private float lastDesiredMoveSpeed; // 上一次的期望移动速度

    public float speedIncreaseMultiplier = 1.5f; // 速度增加倍数
    public float slopeIncreaseMultiplier = 2.5f; // 斜坡增加倍数

    public float groundDrag = 5; // 地面时的阻力

    public float playerHeight = 2; // 玩家身高
    public LayerMask whatIsGround; // 地面的LayerMask
    private bool grounded; // 是否在地面上

    public float jumpForce = 6; // 跳跃力度
    public float jumpCooldown = 0.25f; // 跳跃冷却时间
    public float airMultiplier = 0.4f; // 空中移动速度衰减
    private bool readyToJump = true; // 是否可以跳跃

    public float crouchSpeed = 3.5f; // 蹲伏时的移动速度
    public float crouchYScale = 0.5f; // 蹲伏时的Y轴缩放比例
    private float startYScale; // 初始Y轴缩放比例

    public float maxSlopAngle = 40; // 最大坡度角度
    private RaycastHit slopeHit; // 坡度检测的射线信息
    private bool exitingSlope = true; // 是否正在离开坡度

    public KeyCode jumpKey = KeyCode.Space; // 跳跃键
    public KeyCode sprintKey = KeyCode.LeftShift; // 冲刺键
    public KeyCode crouchKey = KeyCode.LeftControl; // 下蹲键

    public Transform orientation; // 玩家朝向的Transform

    private float h; // 水平输入
    private float v; // 垂直输入

    private Vector3 moveDirection; // 移动方向

    private Rigidbody rb; // 玩家刚体

    public MovementState state; // 当前玩家的移动状态
    public enum MovementState
    {
        walking,    // 行走
        sprinting,  // 冲刺
        wallrunning,//墙跑
        crouching,  // 蹲伏
        sliding,    // 滑动
        air         // 空中
    }

    public bool sliding; // 是否正在滑动
    public bool wallrunning;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        rb.freezeRotation = true; // 防止刚体旋转

        startYScale = transform.localScale.y;  // 记录初始的Y轴缩放
    }

    private void Update()
    {
        grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround);

        MyInput();

        SpeedControl();

        StateHandler();

        if (grounded)
            rb.drag = groundDrag;
        else
            rb.drag = 0;
    }

    private void FixedUpdate()
    {
        MovePlayer();
    }

    private void MyInput()
    {
        // 获取水平和垂直输入
        h = Input.GetAxisRaw("Horizontal");
        v = Input.GetAxisRaw("Vertical");

        // 如果按下跳跃键且准备好跳,并且在地面上
        if (Input.GetKey(jumpKey) && readyToJump && grounded)
        {
            readyToJump = false;

            Jump();

            Invoke(nameof(ResetJump), jumpCooldown);
        }

        if (Input.GetKeyDown(crouchKey))
        {
            // 调整玩家缩放以模拟蹲下效果
            transform.localScale = new Vector3(transform.localScale.x, crouchYScale, transform.localScale.z);

            rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
        }

        // 如果释放下蹲键
        if (Input.GetKeyUp(crouchKey))
        {
            // 恢复到原始Y轴缩放
            transform.localScale = new Vector3(transform.localScale.x, startYScale, transform.localScale.z);
        }
    }

    private void MovePlayer()
    {
        // 根据朝向计算移动方向
        moveDirection = orientation.forward * v + orientation.right * h;

        // 如果在斜坡上并且不是即将离开斜坡
        if (OnSlope() && !exitingSlope)
        {
            // 在斜坡上施加力,以便更好地移动
            rb.AddForce(GetSlopeMoveDirection(moveDirection) * moveSpeed * 20f, ForceMode.Force);

            // 如果垂直速度为正(上升),则额外施加向下的力,以克服斜坡引起的垂直速度变慢
            if (rb.velocity.y > 0)
            {
                rb.AddForce(Vector3.down * 80f, ForceMode.Force);
            }
        }
        else if (grounded) // 如果在地面上
        {
            rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force); // 在地面上施加移动力
        }
        else if (!grounded) // 如果在空中
        {
            // 在空中施加移动力,乘以空中移动速度衰减系数
            rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
        }

        // 根据是否在斜坡上决定是否启用重力
        if (!wallrunning)
            rb.useGravity = !OnSlope();
    }

    private void SpeedControl()
    {
        // 如果在斜坡上并且不是即将离开斜坡
        if (OnSlope() && !exitingSlope)
        {
            // 如果速度的大小超过了设定的移动速度
            if (rb.velocity.magnitude > moveSpeed)
            {
                // 将速度归一化,并乘以设定的移动速度,以限制速度在设定范围内
                rb.velocity = rb.velocity.normalized * moveSpeed;
            }
        }
        // 如果不在斜坡上
        else
        {
            // 获取水平方向的速度
            Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);

            // 如果水平速度的大小超过了设定的移动速度
            if (flatVel.magnitude > moveSpeed)
            {
                // 限制水平速度在设定范围内
                Vector3 limitedVel = flatVel.normalized * moveSpeed;

                // 更新刚体的速度,保持垂直速度不变
                rb.velocity = new Vector3(limitedVel.x, rb.velocity.y, limitedVel.z);
            }
        }
    }

    private void Jump()
    {
        exitingSlope = true;

        //rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
        rb.velocity = Vector3.zero;

        // 添加向上的力以实现跳跃
        rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
    }

    private void ResetJump()
    {
        readyToJump = true;

        exitingSlope = false;
    }

    private void StateHandler()
    {
        if (wallrunning)
        {
            state = MovementState.wallrunning;
            desiredMoveSpeed = wallrunSpeed;
        }

        if (sliding)
        {
            state = MovementState.sliding;  // 设置当前状态为滑动状态

            if (OnSlope() && rb.velocity.y < 0.1f)
            {
                desiredMoveSpeed = slideSpeed;  // 如果在斜坡上并且垂直速度小于0.1,则设置期望移动速度为滑动速度
            }
            else
            {
                desiredMoveSpeed = sprintSpeed;  // 否则,设置期望移动速度为冲刺速度
            }
        }
        // 如果按住蹲伏键
        else if (Input.GetKey(crouchKey))
        {
            // 设置当前状态为蹲伏状态
            state = MovementState.crouching;
            // 设置移动速度为蹲伏速度
            desiredMoveSpeed = crouchSpeed;
        }
        // 如果在地面上并且按住冲刺键
        else if (grounded && Input.GetKey(sprintKey))
        {
            // 设置当前状态为冲刺状态
            state = MovementState.sprinting;
            // 设置移动速度为冲刺速度
            desiredMoveSpeed = sprintSpeed;
        }
        // 如果在地面上但没有按住冲刺键
        else if (grounded)
        {
            // 设置当前状态为行走状态
            state = MovementState.walking;
            // 设置移动速度为行走速度
            desiredMoveSpeed = walkSpeed;
        }
        // 如果不在地面上
        else
        {
            // 设置当前状态为空中状态
            state = MovementState.air;
        }

        if (Mathf.Abs(desiredMoveSpeed - lastDesiredMoveSpeed) > 4f && moveSpeed != 0)
        {
            StopAllCoroutines();  // 停止所有协程
            StartCoroutine(SmoothlyLerpMoveSpeed());  // 启动平滑插值移动速度的协程
        }
        else
        {
            moveSpeed = desiredMoveSpeed;  // 否则,直接将移动速度设置为期望移动速度
        }

        lastDesiredMoveSpeed = desiredMoveSpeed;  // 更新上一次的期望移动速度
    }

    public bool OnSlope()
    {
        // 使用射线检测当前位置向下,获取击中信息存储在slopeHit中
        if (Physics.Raycast(transform.position, Vector3.down, out slopeHit, playerHeight * 0.5f + 0.3f))
        {
            // 计算斜坡的角度
            float angle = Vector3.Angle(Vector3.up, slopeHit.normal);

            // 如果角度小于最大允许斜坡角度且不等于0,表示在斜坡上
            return angle < maxSlopAngle && angle != 0;
        }

        // 如果没有击中信息,或者角度不符合条件,表示不在斜坡上
        return false;

    }

    public Vector3 GetSlopeMoveDirection(Vector3 direction)
    {
        // 使用Vector3.ProjectOnPlane将移动方向投影到斜坡法线上,然后进行归一化
        return Vector3.ProjectOnPlane(direction, slopeHit.normal).normalized;
    }

    private IEnumerator SmoothlyLerpMoveSpeed()
    {
        float time = 0;  // 记录经过的时间
        float difference = Mathf.Abs(desiredMoveSpeed - moveSpeed);  // 计算期望移动速度与当前移动速度的差值
        float startValue = moveSpeed;  // 记录开始时的移动速度

        while (time < difference)
        {
            moveSpeed = Mathf.Lerp(startValue, desiredMoveSpeed, time / difference);  // 使用插值平滑地改变移动速度

            if (OnSlope())
            {
                float slopeAngle = Vector3.Angle(Vector3.up, slopeHit.normal);  // 计算当前坡度的角度
                float slopeAngleIncrease = 1 + (slopeAngle / 90f);  // 根据坡度角度增加速度

                // 根据时间、速度增加倍数、坡度增加倍数进行平滑插值
                time += Time.deltaTime * speedIncreaseMultiplier * slopeIncreaseMultiplier * slopeAngleIncrease;
            }
            else
            {
                // 在平地上,只考虑时间和速度增加倍数
                time += Time.deltaTime * speedIncreaseMultiplier;
            }

            yield return null;  // 等待下一帧
        }

        moveSpeed = desiredMoveSpeed;  // 最终将移动速度设置为期望移动速度
    }
}

Sliding_01.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sliding_01 : MonoBehaviour
{
    public Transform orientation;  // 玩家方向的Transform
    public Transform playerObj;   // 玩家对象的Transform,用于在滑动期间调整缩放
    private Rigidbody rb;          // 玩家的刚体组件
    private PlayerMovement_04 pm_04; // PlayerMovement_03脚本的引用

    public float maxSlideTime = 0.75f; // 滑动的最大持续时间
    public float slideForce = 200;     // 滑动期间施加的力
    private float slideTimer;          // 用于跟踪滑动持续时间的计时器

    public float slideYScale = 0.5f;   // 滑动期间玩家的Y轴缩放
    private float startYScale;          // 玩家的初始Y轴缩放

    public KeyCode slideKey = KeyCode.F; // 启动滑动的按键
    private float h;  // 水平输入
    private float v;  // 垂直输入

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        pm_04 = GetComponent<PlayerMovement_04>();
        startYScale = playerObj.localScale.y;
    }

    private void Update()
    {
        h = Input.GetAxisRaw("Horizontal");
        v = Input.GetAxisRaw("Vertical");

        // 检查是否按下滑动键且存在水平或垂直输入
        if (Input.GetKeyDown(slideKey) && (h != 0 || v != 0))
        {
            StartSlide(); // 启动滑动
        }

        // 检查是否释放了滑动键且玩家当前正在滑动
        if (Input.GetKeyUp(slideKey) && pm_04.sliding)
        {
            StopSlide(); // 停止滑动
        }
    }

    private void FixedUpdate()
    {
        // 检查玩家当前是否在滑动
        if (pm_04.sliding)
        {
            SlidingMovement(); // 处理滑动运动
        }
    }

    private void StartSlide()
    {
        pm_04.sliding = true; // 在PlayerMovement_03脚本中设置滑动标志

        // 调整玩家的缩放以创建蹲伏效果
        playerObj.localScale = new Vector3(playerObj.localScale.x, slideYScale, playerObj.localScale.z);

        // 应用向下的力以模拟蹲伏
        rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);

        slideTimer = maxSlideTime; // 初始化滑动计时器
    }

    private void SlidingMovement()
    {
        Vector3 inputDirection = orientation.forward * v + orientation.right * h; // 计算输入方向

        // 检查玩家是否不在斜坡上或向上移动
        if (!pm_04.OnSlope() || rb.velocity.y > -0.1f)
        {
            // 在滑动期间在输入方向上施加力
            rb.AddForce(inputDirection.normalized * slideForce, ForceMode.Force);

            slideTimer -= Time.deltaTime; // 减少滑动计时器
        }
        else
        {
            // 在斜坡上滑动时根据斜坡的方向调整力
            rb.AddForce(pm_04.GetSlopeMoveDirection(inputDirection) * slideForce, ForceMode.Force);
        }

        // 检查滑动持续时间是否已过期
        if (slideTimer <= 0)
        {
            StopSlide(); // 停止滑动
        }
    }

    private void StopSlide()
    {
        pm_04.sliding = false; // 在PlayerMovement_03脚本中重置滑动标志

        // 将玩家的缩放恢复到初始大小
        playerObj.localScale = new Vector3(playerObj.localScale.x, startYScale, playerObj.localScale.z);
    }
}

WallRunning.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WallRunning : MonoBehaviour
{
    public LayerMask whatIsWall; // 定义墙体的LayerMask,用于射线检测
    public LayerMask whatIsGround; // 定义地面的LayerMask,用于射线检测
    public float wallRunForce = 200; // 墙体运动时施加的力
    public float wallJumpUpForce = 7; // 墙跳时向上施加的力的大小
    public float wallJumpSideForce = 12; // 墙跳时向侧面施加的力的大小
    public float wallClimbSpeed = 3; // 沿墙上移动时的速度
    public float maxWallRunTime = 0.7f; // 最大墙体运动时间
    private float wallRunTimer; // 当前墙体运动计时器

    public KeyCode upwardsRunKey = KeyCode.E; // 向上墙体运动的按键
    public KeyCode downwardsRunKey = KeyCode.Q; // 向下墙体运动的按键
    public KeyCode jumpKey = KeyCode.Space;
    private bool upwardsRunning; // 是否正在向上墙体运动
    private bool downwardsRunning; // 是否正在向下墙体运动
    private float h; // 水平输入
    private float v; // 垂直输入

    public float wallCheckDistance = 0.7f; // 射线检测墙体的距离
    public float minJumpHeight = 1; // 最小跳跃高度
    private RaycastHit leftWallHit; // 射线检测到的左侧墙体信息
    private RaycastHit rightWallHit; // 射线检测到的右侧墙体信息
    private bool wallLeft; // 是否靠近左侧墙体
    private bool wallRight; // 是否靠近右侧墙体

    private bool exitingWall; // 是否正在退出墙壁状态的标志
    public float exitWallTime = 0.2f; // 退出墙壁状态的时间阈值
    private float exitWallTimer; // 退出墙壁状态的计时器

    public bool useGravity = true; // 是否使用重力的标志,默认为 true,表示使用重力
    public float gravityCounterForce = 3; // 用于控制在墙上的反向重力的力大小

    public Transform orientation; // 玩家朝向的Transform
    public PlayerCam_02 cam_02;
    private PlayerMovement_04 pm_04; // 玩家移动脚本
    private Rigidbody rb; // 玩家刚体

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        pm_04 = GetComponent<PlayerMovement_04>();
    }

    private void Update()
    {
        CheckForWall(); // 检测是否靠近墙体
        StateMachine(); // 墙体运动状态机
    }

    private void FixedUpdate()
    {
        if (pm_04.wallrunning)
        {
            WallRunningMovement(); // 处理墙体运动
        }
    }

    private void CheckForWall()
    {
        // 使用 Physics.Raycast 检测角色右侧是否有墙壁,将结果存储在 rightWallHit 中
        wallRight = Physics.Raycast(transform.position, orientation.right, out rightWallHit, wallCheckDistance, whatIsWall);
        // 使用 Physics.Raycast 检测角色左侧是否有墙壁,将结果存储在 leftWallHit 中
        wallLeft = Physics.Raycast(transform.position, -orientation.right, out leftWallHit, wallCheckDistance, whatIsWall);
    }

    private bool AboveGround()
    {
        // 使用 Physics.Raycast 检测角色当前位置向下的射线,检测距离为 minJumpHeight,目标层级为 whatIsGround
        return !Physics.Raycast(transform.position, Vector3.down, minJumpHeight, whatIsGround);
    }

    private void StateMachine()
    {
        // 获取水平和垂直输入
        h = Input.GetAxisRaw("Horizontal");
        v = Input.GetAxisRaw("Vertical");

        // 检查是否按住上墙和下墙的按键
        upwardsRunning = Input.GetKey(upwardsRunKey);
        downwardsRunning = Input.GetKey(downwardsRunKey);

        // 如果靠近墙,并且朝上移动,并且在地面上,并且不在退出墙体状态
        if ((wallLeft || wallRight) && v > 0 && AboveGround() && !exitingWall)
        {
            // 如果当前不在墙体运动状态
            if (!pm_04.wallrunning)
            {
                StartWallRun(); // 开始墙体运动
            }

            // 如果墙体运动计时器仍在计时
            if (wallRunTimer > 0)
            {
                wallRunTimer -= Time.deltaTime;
            }

            // 如果墙体运动计时器结束,并且当前在墙体运动状态
            if (wallRunTimer <= 0 && pm_04.wallrunning)
            {
                exitingWall = true;
                exitWallTimer = exitWallTime;
            }

            // 如果按下跳跃键
            if (Input.GetKeyDown(jumpKey))
            {
                WallJump();
            }
        }
        // 如果正在退出墙体状态
        else if (exitingWall)
        {
            // 如果当前在墙体运动状态,停止墙体运动
            if (pm_04.wallrunning)
            {
                StopWallRun();
            }

            // 如果退出墙体计时器仍在计时
            if (exitWallTimer > 0)
            {
                exitWallTimer -= Time.deltaTime;
            }

            // 如果退出墙体计时器结束
            if (exitWallTimer <= 0)
            {
                exitingWall = false;
            }
        }
        else
        {
            // 如果当前在墙体运动状态
            if (pm_04.wallrunning)
            {
                StopWallRun(); // 停止墙体运动
            }
        }
    }

    private void StartWallRun()
    {
        pm_04.wallrunning = true; // 设置玩家正在进行墙体运动

        wallRunTimer = maxWallRunTime; // 设置墙体运动计时器

        rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z); // 将垂直速度置为0,确保在墙体上的水平移动

        cam_02.DoFov(90f); // 调用摄像机的方法,改变视野角度为90度,提高视野

        // 根据墙的方向调整摄像机的倾斜角度
        if (wallLeft)
        {
            cam_02.DoTilt(-5f); // 如果靠左墙,摄像机向左倾斜5度
            Debug.Log("摄像机向左倾斜5度");
        }

        if (wallRight)
        {
            cam_02.DoTilt(5f); // 如果靠右墙,摄像机向右倾斜5度
            Debug.Log("摄像机向右倾斜5度");
        }
    }

    private void WallRunningMovement()
    {
        rb.useGravity = useGravity; // 关闭重力,以免影响墙体运动

        Vector3 wallNormal = wallRight ? rightWallHit.normal : leftWallHit.normal; // 获取墙体法线向量

        Vector3 wallForward = Vector3.Cross(wallNormal, transform.up); // 获取墙体的前方向量

        if ((orientation.forward - wallForward).magnitude > (orientation.forward - -wallForward).magnitude)
        {
            wallForward = -wallForward; // 选择与玩家朝向更一致的前方向量
        }

        rb.AddForce(wallForward * wallRunForce, ForceMode.Force); // 施加墙体运动的力

        if (upwardsRunning)
        {
            rb.velocity = new Vector3(rb.velocity.x, wallClimbSpeed, rb.velocity.z); // 向上墙体运动
        }
        if (downwardsRunning)
        {
            rb.velocity = new Vector3(rb.velocity.x, -wallClimbSpeed, rb.velocity.z); // 向下墙体运动
        }

        if (!(wallLeft && h > 0) && !(wallRight && h < 0))
        {
            rb.AddForce(-wallNormal * 100, ForceMode.Force); // 防止水平移动
        }
        if (useGravity)
        {
            rb.AddForce(transform.up * gravityCounterForce, ForceMode.Force);
        }
    }

    private void StopWallRun()
    {
        pm_04.wallrunning = false; // 设置玩家停止墙体运动

        cam_02.DoFov(80f); // 调用摄像机的方法,恢复视野角度为80度
        cam_02.DoTilt(0f); // 调用摄像机的方法,恢复倾斜角度为0度
    }

    private void WallJump()
    {
        exitingWall = true; // 设置正在进行墙体跳跃,触发退出墙体运动的逻辑
        exitWallTimer = exitWallTime; // 设置退出墙体的计时器

        Vector3 wallNormal = wallRight ? rightWallHit.normal : leftWallHit.normal; // 获取墙体的法线方向

        // 计算施加到玩家身上的力,包括向上的力和沿墙的侧向力
        Vector3 forceToApply = transform.up * wallJumpUpForce + wallNormal * wallJumpSideForce;

        rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z); // 将垂直速度置为0,确保在墙体上的水平移动

        rb.AddForce(forceToApply, ForceMode.Impulse); // 应用力到刚体,实现墙体跳跃效果
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA怎么用Devtools热部署

IDEA怎么用Devtools热部署 大家知道在项目开发过程中&#xff0c;有时候会改动代码逻辑或者修改数据结构&#xff0c;为了能使改动的代码生效&#xff0c;往往需要重启应用查看改变效果&#xff0c;这样会相当耗费时间。 重启应用其实就是重新编译生成新的Class文件&#xff0…

axios的原理及源码解析

面试官&#xff1a;你了解axios的原理吗&#xff1f;有看过它的源码吗&#xff1f; 一、axios的使用 关于axios的基本使用&#xff0c;上篇文章已经有所涉及&#xff0c;这里再稍微回顾下&#xff1a; 发送请求 import axios from axios;axios(config) // 直接传入配置 axio…

C语言数据结构之线性表-顺序表篇

星光不负赶路人 江河眷顾奋楫者 &#x1f3a5;烟雨长虹&#xff0c;孤鹜齐飞的个人主页 &#x1f525;个人专栏 期待小伙伴们的支持与关注&#xff01;&#xff01;&#xff01; 线性表的简介# 线性表&#xff08;linearlist&#xff09;&#xff1a;是n个具有相同特性的数据元…

Vue3前端开发,computed计算属性的基础练习

Vue3前端开发&#xff0c;computed计算属性的基础练习&#xff01; 在新版里面&#xff0c;和传统的vue2一样&#xff0c;计算属性&#xff0c;都是对一些数据运算进行了封装操作。返回结果是一个实时监控的效果。区别在于&#xff0c;写法不同。效果是一样。 下面给大家展示…

【萤火虫系列教程】3/5-Adobe Firefly 创意填充

003-Adobe Firefly 创意填充 创意填充 登录账号后&#xff0c;在主页点击创意填充的【生成】按钮&#xff0c;进入到创意填充页面 我们可以上传自己的图像 一键抠图 点击【背景】就可以把主图抠出来 点击【反转】就可以把背景抠出来 点击【清除】就可以恢复到图片原来…

一文详解Linux文本处理三剑客

1.正则表达式 目录 1.正则表达式 1.什么是正则表达式 &#xff1f; 2.正则表达式的使用场景 3.正则表达式字符表示 4.它们之间的区别 2.grep命令 作用&#xff1a; 语法&#xff1a; 说明&#xff1a; 选项&#xff1a;options 重点 实例 3.后面的下次再更新。 …

【征服redis7】谈谈Redis的RDB持久化方式

从现在开始&#xff0c;我们来探讨redis的一个非常重要的问题——集群&#xff0c;要讨论集群&#xff0c;我们需要先理解redis持久化数据的方法&#xff0c;因为集群本质上就是将一个集群的数据同步到其他机器上。 Redis 6的持久化机制主要有两种&#xff1a;RDB&#xff08;…

【CUDA】GPU 算力与 CUDA 版本对应关系

1. 查询 GPU 算力&#xff08;Compute Capability&#xff09; 官方算力表&#xff1a;https://developer.nvidia.com/cuda-gpus#compute 2. GPU 算力与 CUDA 版本对应关系 2.1. 信息来源 1 https://docs.nvidia.com/datacenter/tesla/drivers/index.html#cuda-arch-matri…

Kafka-消费者-KafkaConsumer分析-SubscriptionState

KafkaConsumer从Kafka拉取消息时发送的请求是FetchRequest(具体格式后面介绍),在其中需要指定消费者希望拉取的起始消息的offset。 为了消费者快速获取这个值&#xff0c;KafkaConsumer使用SubscriptionState来追踪TopicPartition与offset对应关系。 图展示了SubscriptionSta…

el-dialog嵌套使用,只显示遮罩层的问题

直接上解决方法 <!-- 错误写法 --><el-dialog><el-dialog></el-dialog></el-dialog><!-- 正确写法 --><el-dialog></el-dialog><el-dialog></el-dialog>我是不建议嵌套使用的&#xff0c;平级也能调用&#xff0c…

LaWGPT安装和使用教程的复现版本【细节满满】

文章目录 前言一、下载和部署1.1 下载1.2 环境安装1.3 模型推理 总结 前言 LaWGPT 是一系列基于中文法律知识的开源大语言模型。该系列模型在通用中文基座模型&#xff08;如 Chinese-LLaMA、ChatGLM等&#xff09;的基础上扩充法律领域专有词表、大规模中文法律语料预训练&am…

Qt 状态机框架:The State Machine Framework (二)

传送门: Qt 状态机框架:The State Machine Framework (一) Qt 状态机框架:The State Machine Framework (二) 1、利用并行态避免态的组合爆炸 假设您想在单个状态机中对汽车的一组互斥属性进行建模。假设我们感兴趣的属性是干净与肮脏&#xff0c;以及移动与不移动。需要四个…

【教3妹学编程-算法题】检查按位或是否存在尾随零

3妹&#xff1a;呜呜&#xff0c;烦死了&#xff0c; 脸上长了一个痘 2哥 : 不要在意这些细节嘛&#xff0c;不用管它&#xff0c;过两天自然不就好了。 3妹&#xff1a;切&#xff0c;你不懂&#xff0c;影响这两天的心情哇。 2哥 : 我看你是不急着找工作了啊&#xff0c; 工作…

Golang通过Gorm操作Mysql时遇到的datetime时区问题

情景描述 golang使用Gorm操作MySQL&#xff0c;MySQL中数据类型是datetime&#xff0c;Golang中用的是time.now。 但是会导致存储的时间与北京时间有8h误差&#xff0c; 显然是没有初始化时区导致。 问题修复 初始化设置时区 参考我自己之前写过的一篇总结——Mysql中多种日…

QT上位机开发(不同场景下界面的设计模板)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 qt由于其优秀的跨平台属性&#xff0c;几乎成了嵌入式开发界面开发的标配。同时呢&#xff0c;由于它在windows平台开发出来的效果也是非常的好&am…

Python开发环境安装:梦的起点

Python解释器安装 前言 解释器&#xff08;Interpreter&#xff09;&#xff0c;又译为直译器&#xff0c;是一种电脑程序能够把高级编程语言一行一行直接转译运行。解释器不会一次把整个程序转译出来&#xff0c;只像一位“中间人”&#xff0c;每次运行程序时都要先转成另一…

dubbo入门案例!!!

入门案例之前我们先介绍一下&#xff1a;zookeeper。 Zookeeper是Apacahe Hadoop的子项目&#xff0c;可以为分布式应用程序协调服务&#xff0c;适合作为Dubbo服务的注册中心&#xff0c;负责服务地址的注册与查找&#xff0c;相当于目录服务&#xff0c;服务提供者和消费者只…

rust跟我学七:获取外网IP地址

图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info是怎么获取到本机的外网IP地址。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址:[…

测试驱动开发:基于Jenkins+GoTest+HTML的持续化集成

目录 前言 一、项目框架 1.项目迭代 2.项目时序图 3.项目测试执行 二、项目具体实现 1.创建流水线 2.拉取代码 3.执行测试代码 4.生成测试报告 5.报告内容解读 6.数据统计 7.邮件通知 8.企业微信通知 三、项目遇到的问题 1.go test -args 2.go test生…

MyBatisPlus学习笔记四-扩展功能

1、代码生成器 1.1、官方的1 1.3、官方的2-idea插件 1.3、非官方的-idea插件 2、静态工具 先查询&#xff0c;再分组 3、逻辑删除 4、枚举处理器 5、JSON处理器