【unity实战】使用旧输入系统Input Manager 写一个 2D 平台游戏玩家控制器——包括移动、跳跃、滑墙、蹬墙跳

news2024/7/5 1:11:04

最终效果

在这里插入图片描述

文章目录

  • 最终效果
  • 素材下载
    • 人物
    • 环境
  • 简单绘制环境
  • 角色移动跳跃
  • 视差和摄像机跟随效果
  • 奔跑动画切换
  • 跳跃动画,跳跃次数限制
  • 角色添加2d物理材质,防止角色粘在墙上
  • 如果角色移动时背景出现黑线条
    • 方法一
    • 方法二
  • 墙壁滑行
  • 实现角色滑墙不可以通过移动离开且不可翻转角色
  • 空中运动控制
  • 可变跳跃高度
  • 蹬墙跳
  • 完整代码
  • 源码
  • 完结

素材下载

人物

https://rvros.itch.io/animated-pixel-hero
在这里插入图片描述

环境

https://bardent.itch.io/the-bardent-asset-pack
在这里插入图片描述
https://brullov.itch.io/oak-woods
在这里插入图片描述

简单绘制环境

参考:【推荐100个unity插件之14】Unity2D TileMap的探究(最简单,最全面的TileMap使用介绍)
在这里插入图片描述

角色移动跳跃

新增PlayerController

public class PlayerController : MonoBehaviour
{
    private float movementInputDirection; // 水平输入方向
    private bool isFacingRight = true; // 玩家是否面向右侧
    private Rigidbody2D rb;
    public float movementSpeed = 10.0f; // 移动速度
    public float jumpForce = 16.0f; // 跳跃力度

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        CheckInput(); // 检查输入
        CheckMovementDirection();
    }

    private void FixedUpdate()
    {
        ApplyMovement(); // 应用移动
    }

    // 检查玩家面朝的方向
    private void CheckMovementDirection()
    {
        if (isFacingRight && movementInputDirection < 0)
        {
            Flip(); // 翻转角色
        }
        else if (!isFacingRight && movementInputDirection > 0)
        {
            Flip(); // 翻转角色
        }
    }

    // 检查输入
    private void CheckInput()
    {
        movementInputDirection = Input.GetAxisRaw("Horizontal"); // 获取水平输入
        if (Input.GetButtonDown("Jump"))
        {
            Jump(); // 如果按下跳跃键,则执行跳跃
        }
    }

    // 跳跃
    private void Jump()
    {
        rb.velocity = new Vector2(rb.velocity.x, jumpForce); // 设置 y 方向的速度为跳跃力度
    }

    // 移动
    private void ApplyMovement()
    {
        rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y); // 设置 x 方向的速度
    }

    // 翻转角色
    private void Flip()
    {
        isFacingRight = !isFacingRight; // 改变面向方向的标志
        transform.Rotate(0.0f, 180.0f, 0.0f); // 旋转角色
    }
}

配置
在这里插入图片描述
效果
在这里插入图片描述

视差和摄像机跟随效果

参考:【unity小技巧】Unity实现视差效果与无限地图

新增CameraController代码

public class CameraController : MonoBehaviour
{
    public Transform target;//玩家的位置
    public Transform farBackground, middleBackground, frontBackground;//远的背景和中间背景的位置
    private Vector2 lastPos;//最后一次的相机位置
    void Start()
    {
        lastPos = transform.position;//记录相机的初始位置
    }

    void Update()
    {
        //将相机的位置设置为玩家的位置,但限制在一定的垂直范围内
        //transform.position = new Vector3(target.position.x, target.position.y + 1f, transform.position.z);
        //计算相机在上一帧和当前帧之间移动的距离
        Vector2 amountToMove = new Vector2(transform.position.x - lastPos.x, transform.position.y - lastPos.y);
        //根据相机移动的距离,移动远背景和中间背景的位置
        farBackground.position += new Vector3(amountToMove.x, amountToMove.y, 0f);
        middleBackground.position += new Vector3(amountToMove.x * 0.9f, amountToMove.y, 0f);
        frontBackground.position += new Vector3(amountToMove.x * 0.5f, amountToMove.y, 0f);
        lastPos = transform.position;//更新最后一次的相机位置
    }
}

Map代码

public class Map : MonoBehaviour
{
    [Header("无限地图")]
    private GameObject mainCamera;//主摄像机对象
    private float mapwidth;//地图宽度
    private float totalwidth;//总地图宽度
    
    public int mapNums;//地图重复的次数
    void Start()
    {
        mainCamera = GameObject.FindGameObjectWithTag("MainCamera");//查找标签为"MainCamera'"的对象并赋值
        mapwidth = GetComponent<SpriteRenderer>().sprite.bounds.size.x;//通过SpriteRenderer获得图像宽度
        totalwidth = mapwidth * mapNums;//计算总地图宽度
    }

    void FixedUpdate()
    {
        Vector3 tempPosition = transform.position;//获取当前位置
        if (mainCamera.transform.position.x > transform.position.x + totalwidth / 2)
        {
            tempPosition.x += totalwidth;//将地图向右平移一个完整的地图宽度
            transform.position = tempPosition;//更新位置
        }
        else if (mainCamera.transform.position.x < transform.position.x - totalwidth / 2)
        {
            tempPosition.x -= totalwidth;//将地图向左平移一个完整的地图宽度
            transform.position = tempPosition;//更新位置
        }

    }
}

配置
在这里插入图片描述
在这里插入图片描述
效果
在这里插入图片描述

奔跑动画切换

动画配置
在这里插入图片描述

修改PlayerController

private void FixedUpdate()
{
    ApplyMovement(); // 应用移动
    UpdateStatus();
}

//判断状态 
private void UpdateStatus(){
    if(rb.velocity.x != 0){
        isRunning = true;
    }else{
        isRunning = false;
    }
}

//播放动画
private void UpdateAnimations(){
    animator.SetBool("isRunning", isRunning);
}

效果
在这里插入图片描述

跳跃动画,跳跃次数限制

配置跳跃动画
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
修改PlayerController

[Header("跳跃 地面检测")]
private float amountOfJumpsLeft;//当前可跳跃次数
private bool isGround;//是否是地面
private bool canJump;//能否跳跃
public int amountOfJumps = 1;//跳跃次数
public float groundCheckRadius;//地面检测距离
public Transform groundCheck;//地面检测点
public LayerMask whatIsGround;//地面检测图层


void Start()
{
    rb = GetComponent<Rigidbody2D>();
    animator = GetComponent<Animator>();
    amountOfJumpsLeft = amountOfJumps;
}

// 检查输入
private void CheckInput()
{
    movementInputDirection = Input.GetAxisRaw("Horizontal"); // 获取水平输入
    if (Input.GetButtonDown("Jump"))
    {
        Jump(); // 如果按下跳跃键,则执行跳跃
    }
}

// 跳跃
private void Jump()
{
    if (canJump)
    {
        rb.velocity = new Vector2(rb.velocity.x, jumpForce); // 设置 y 方向的速度为跳跃力度
        amountOfJumpsLeft--;
    }
}

//判断能否跳跃
private void CheckIfCanJump()
{
    if (isGround && rb.velocity.y < 0)
    {
        amountOfJumpsLeft = amountOfJumps;
    }
    if (amountOfJumpsLeft <= 0)
    {
        canJump = false;
    }
    else
    {
        canJump = true;
    }
}

//播放动画
private void UpdateAnimations()
{
    animator.SetBool("isRunning", isRunning);
    animator.SetBool("isGround", isGround);
    animator.SetFloat("yVelocity", rb.velocity.y);
}

//检测
private void CheckSurroundings()
{
    //地面检测
    isGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
}

//视图显示检测范围
private void OnDrawGizmos()
{
    Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
}

配置,这里配置了2段跳
在这里插入图片描述
记得配置地面图层为Ground
在这里插入图片描述
效果
在这里插入图片描述

角色添加2d物理材质,防止角色粘在墙上

在这里插入图片描述
修改摩檫力为0
在这里插入图片描述
配置
在这里插入图片描述
效果
在这里插入图片描述

如果角色移动时背景出现黑线条

方法一

添加材质
在这里插入图片描述
配置
在这里插入图片描述

方法二

我们创建了一个Sprite Atlas来将Spritesheet拖入其中
在这里插入图片描述
把你的瓦片素材拖入
在这里插入图片描述

墙壁滑行

配置滑墙动画
在这里插入图片描述

修改PlayerController

[Header("墙壁滑行")]
public float wallCheckDistance;//墙壁检测距离
public Transform wallCheck;//墙壁检测点
public float wallSlideSpeed;//墙壁滑行速度
private bool isTouchingWall;//是否接触墙壁
private bool isWallSliding;//是否正在墙壁滑行

// 移动
private void ApplyMovement()
{
    rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y); // 设置 x 方向的速度
    
    //应用滑墙速度    
    if (isWallSliding)
    {
        if (rb.velocity.y < -wallSlideSpeed)
        {
            rb.velocity = new Vector2(rb.velocity.x, -wallSlideSpeed);// 限制垂直速度以应用墙壁滑行速度
        }
    }
}

//是否正在墙壁滑行
private void CheckIfWallSliding()
{
    if (isTouchingWall && !isGround && rb.velocity.y < 0)
    {
        isWallSliding = true;
    }
    else
    {
        isWallSliding = false;
    }
}

//播放动画
private void UpdateAnimations()
{
    animator.SetBool("isRunning", isRunning);
    animator.SetBool("isGround", isGround);
    animator.SetFloat("yVelocity", rb.velocity.y);
    animator.SetBool("isWallSliding", isWallSliding);
}

//检测
private void CheckSurroundings()
{
    //地面检测
    isGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);

    //墙面检测
    isTouchingWall = Physics2D.Raycast(wallCheck.position, transform.right, wallCheckDistance, whatIsGround);
}

//视图显示检测范围
private void OnDrawGizmos()
{
    Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
    Gizmos.DrawLine(wallCheck.position, wallCheck.position + wallCheckDistance * Vector3.right);
}

配置
在这里插入图片描述
效果
在这里插入图片描述

实现角色滑墙不可以通过移动离开且不可翻转角色

// 移动
private void ApplyMovement()
{
    // 如果在地面上
    if (isGround)
    {
        rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y); // 设置 x 方向的速度
    }

    //应用滑墙速度    
    if (isWallSliding)
    {
        if (rb.velocity.y < -wallSlideSpeed)
        {
            rb.velocity = new Vector2(rb.velocity.x, -wallSlideSpeed);// 限制垂直速度以应用墙壁滑行速度
        }
    }
}

// 翻转角色
private void Flip()
{
    if (!isWallSliding)
    {
        isFacingRight = !isFacingRight; // 改变面向方向的标志
        transform.Rotate(0.0f, 180.0f, 0.0f); // 旋转角色
    }
}

效果
在这里插入图片描述

空中运动控制

空气阻力和移动速度控制

public float movementForceInAir;//空气中的运动力
public float airDragMultiplier = 0.95f;//空气阻力

// 移动
private void ApplyMovement()
{
    // 如果在地面上
    if (isGround)
    {
        rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y); // 设置 x 方向的速度
    }
    // 如果不在地面上且不是在墙壁滑行且有水平输入
    else if (!isGround && !isWallSliding && movementInputDirection != 0)
    {
        Vector2 forceToAdd = new Vector2(movementForceInAir * movementInputDirection, 0);// 在空中施加的力
        rb.AddForce(forceToAdd);// 添加力到刚体
        if (Mathf.Abs(rb.velocity.x) > movementSpeed)
        {
            rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y);// 限制水平速度
        }
    }
    // 如果不在地面上且不是在墙壁滑行且没有水平输入
    else if (!isGround && !isWallSliding && movementInputDirection == 0)
    {
        rb.velocity = new Vector2(rb.velocity.x * airDragMultiplier, rb.velocity.y);// 应用空气阻力
    }

    //应用滑墙速度    
    if (isWallSliding)
    {
        if (rb.velocity.y < -wallSlideSpeed)
        {
            rb.velocity = new Vector2(rb.velocity.x, -wallSlideSpeed);// 限制垂直速度以应用墙壁滑行速度
        }
    }
}

配置
在这里插入图片描述
效果
在这里插入图片描述

可变跳跃高度

长跳跃和短跳,长按和之前跳的和之前一样高

public float variableJumpHeightMultiplier = 0.5f;

 // 检查输入
private void CheckInput()
{
    movementInputDirection = Input.GetAxisRaw("Horizontal"); // 获取水平输入
    if (Input.GetButtonDown("Jump"))
    {
        Jump(); // 如果按下跳跃键,则执行跳跃
    }

	// 检测是否松开Jump
    if (Input.GetButtonUp("Jump"))
    {
        rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * variableJumpHeightMultiplier);
    }
}

效果
在这里插入图片描述

蹬墙跳

实现不输入,点击跳跃就从墙上跳下来,方向按键+跳跃控制左右蹬墙跳

[Header("蹬墙跳")]
public float wallHopForce; // 离开墙时的力
public float wallJumpForce; // 蹬墙跳时施加的力
public Vector2 wallHopDirection; // 离开墙时的方向向量
public Vector2 wallJumpDirection; // 蹬墙跳时的方向向量
private int facingDirection = 1; // 角色面向的方向,1右 -1左

void Start()
{
    rb = GetComponent<Rigidbody2D>();
    animator = GetComponent<Animator>();
    amountOfJumpsLeft = amountOfJumps;
    
    //归一化向量,因为我们只要向量的方向,而不考虑长度
    wallHopDirection = wallHopDirection.normalized;
    wallJumpDirection = wallJumpDirection.normalized;
}

// 跳跃
private void Jump()
{
    // 如果可以跳跃并且不是在墙壁滑行状态下
    if (canJump && !isWallSliding)
    {
        rb.velocity = new Vector2(rb.velocity.x, jumpForce); // 设置 y 方向的速度为跳跃力度
        amountOfJumpsLeft--;
    }
    // 如果正在墙壁滑行且没有输入水平移动方向,并且可以跳跃
    else if(isWallSliding && movementInputDirection == 0 && canJump){
        isWallSliding = false;
        amountOfJumpsLeft--;
        // 计算添加的力量,使角色从墙壁上弹开
        Vector2 forceToAdd = new Vector2(wallHopForce * wallHopDirection.x * -facingDirection, wallHopForce * wallHopDirection.y);
        rb.AddForce(forceToAdd, ForceMode2D.Impulse);
    }
    // 如果正在墙壁滑行或者正在接触墙壁,并且有水平移动输入,并且可以跳跃
    else if((isWallSliding || isTouchingWall) && movementInputDirection != 0 && canJump){
        isWallSliding = false;
        amountOfJumpsLeft --;
        // 计算添加的力量,使角色从墙壁上跳跃
        Vector2 forceToAdd = new Vector2(wallHopForce * wallHopDirection.x * movementInputDirection, wallJumpForce * wallJumpDirection.y);
        rb.AddForce(forceToAdd, ForceMode2D.Impulse);
    }
}

 //判断能否跳跃
private void CheckIfCanJump()
{
    if ((isGround && rb.velocity.y < 0) || isWallSliding)
    {
        amountOfJumpsLeft = amountOfJumps;
    }

    if (amountOfJumpsLeft <= 0)
    {
        canJump = false;
    }
    else
    {
        canJump = true;
    }
}

// 翻转角色
private void Flip()
{
    if (!isWallSliding)
    {
        facingDirection *= -1;
        isFacingRight = !isFacingRight; // 改变面向方向的标志
        transform.Rotate(0.0f, 180.0f, 0.0f); // 旋转角色
    }
}

配置
在这里插入图片描述
运行效果
在这里插入图片描述

完整代码

using Unity.VisualScripting;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private float movementInputDirection; // 水平输入方向
    private bool isFacingRight = true; // 玩家是否面向右侧
    private Rigidbody2D rb;
    public float movementSpeed = 10.0f; // 移动速度
    public float jumpForce = 16.0f; // 跳跃力度

    private Animator animator;

    [Header("状态")]
    public bool isRunning;

    [Header("跳跃 地面检测")]

    public int amountOfJumps = 1;//跳跃次数
    public float groundCheckRadius;//地面检测距离
    public Transform groundCheck;//地面检测点
    public LayerMask whatIsGround;//地面检测图层
    private float amountOfJumpsLeft;//当前可跳跃次数
    private bool isGround;//是否是地面
    private bool canJump;//能否跳跃

    [Header("墙壁滑行")]
    public float wallCheckDistance;//墙壁检测距离
    public Transform wallCheck;//墙壁检测点
    public float wallSlideSpeed;//墙壁滑行速度
    public float movementForceInAir;//空气中的运动力
    public float airDragMultiplier = 0.95f;//空气阻力
    private bool isTouchingWall;//是否接触墙壁
    private bool isWallSliding;//是否正在墙壁滑行

    [Header("可变高度")]
    public float variableJumpHeightMultiplier = 0.5f;

    [Header("蹬墙跳")]
    public float wallHopForce; // 离开墙时的力
    public float wallJumpForce; // 蹬墙跳时施加的力
    public Vector2 wallHopDirection; // 离开墙时的方向向量
    public Vector2 wallJumpDirection; // 蹬墙跳时的方向向量
    private int facingDirection = 1; // 角色面向的方向,1右 -1左

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        amountOfJumpsLeft = amountOfJumps;
        //归一化向量,因为我们只要向量的方向,而不考虑长度
        wallHopDirection = wallHopDirection.normalized;
        wallJumpDirection = wallJumpDirection.normalized;
    }

    void Update()
    {
        CheckInput(); // 检查输入
        CheckMovementDirection();
        UpdateAnimations();
        CheckIfCanJump();
        CheckIfWallSliding();
        CheckSurroundings();
    }

    private void FixedUpdate()
    {
        ApplyMovement(); // 应用移动
        UpdateStatus();
    }

    // 检查玩家面朝的方向
    private void CheckMovementDirection()
    {
        if (isFacingRight && movementInputDirection < 0)
        {
            Flip(); // 翻转角色
        }
        else if (!isFacingRight && movementInputDirection > 0)
        {
            Flip(); // 翻转角色
        }
    }

    // 检查输入
    private void CheckInput()
    {
        movementInputDirection = Input.GetAxisRaw("Horizontal"); // 获取水平输入
        if (Input.GetButtonDown("Jump"))
        {
            Jump(); // 如果按下跳跃键,则执行跳跃
        }
        
        if (Input.GetButtonUp("Jump"))
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * variableJumpHeightMultiplier);
        }
    }

    // 移动
    private void ApplyMovement()
    {
        // 如果在地面上
        if (isGround)
        {
            rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y); // 设置 x 方向的速度
        }
        // 如果不在地面上且不是在墙壁滑行且有水平输入
        else if (!isGround && !isWallSliding && movementInputDirection != 0)
        {
            Vector2 forceToAdd = new Vector2(movementForceInAir * movementInputDirection, 0);// 在空中施加的力
            rb.AddForce(forceToAdd);// 添加力到刚体
            if (Mathf.Abs(rb.velocity.x) > movementSpeed)
            {
                rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y);// 限制水平速度
            }
        }
        // 如果不在地面上且不是在墙壁滑行且没有水平输入
        else if (!isGround && !isWallSliding && movementInputDirection == 0)
        {
            rb.velocity = new Vector2(rb.velocity.x * airDragMultiplier, rb.velocity.y);// 应用空气阻力
        }

        // //应用滑墙速度    
        if (isWallSliding)
        {
            if (rb.velocity.y < -wallSlideSpeed)
            {
                rb.velocity = new Vector2(rb.velocity.x, -wallSlideSpeed);// 限制垂直速度以应用墙壁滑行速度
            }
        }
    }

    // 移动
    private void ApplyMovement()
    {
        if(!isGround && !isWallSliding && movementInputDirection == 0){
            rb.velocity = new Vector2(rb.velocity.x * airDragMultiplier, rb.velocity.y);// 应用空气阻力
        }else{
            rb.velocity = new Vector2(movementSpeed * movementInputDirection, rb.velocity.y); // 设置 x 方向的速度
        }

        //应用滑墙速度    
        if (isWallSliding)
        {
            if (rb.velocity.y < -wallSlideSpeed)
            {
                rb.velocity = new Vector2(rb.velocity.x, -wallSlideSpeed);// 限制垂直速度以应用墙壁滑行速度
            }
        }
    }

    //判断跑步状态 
    private void UpdateStatus(){
        if(rb.velocity.x != 0){
            isRunning = true;
        }else{
            isRunning = false;
        }
    }

    // 翻转角色
    private void Flip()
    {
        if (!isWallSliding)
        {
            facingDirection *= -1;
            isFacingRight = !isFacingRight; // 改变面向方向的标志
            transform.Rotate(0.0f, 180.0f, 0.0f); // 旋转角色
        }
    }

    //播放动画
    private void UpdateAnimations()
    {
        animator.SetBool("isRunning", isRunning);
        animator.SetBool("isGround", isGround);
        animator.SetFloat("yVelocity", rb.velocity.y);
        animator.SetBool("isWallSliding", isWallSliding);
    }

    //判断能否跳跃
    private void CheckIfCanJump()
    {
        if ((isGround && rb.velocity.y < 0) || isWallSliding)
        {
            amountOfJumpsLeft = amountOfJumps;
        }

        if (amountOfJumpsLeft <= 0)
        {
            canJump = false;
        }
        else
        {
            canJump = true;
        }
    }

    //检测
    private void CheckSurroundings()
    {
        //地面检测
        isGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);

        //墙面检测
        isTouchingWall = Physics2D.Raycast(wallCheck.position, transform.right, wallCheckDistance, whatIsGround);
    }

    //是否墙壁滑行
    private void CheckIfWallSliding()
    {
        if (isTouchingWall && !isGround && rb.velocity.y < 0)
        {
            isWallSliding = true;
        }
        else
        {
            isWallSliding = false;
        }
    }

    //视图显示检测范围
    private void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
        Gizmos.DrawLine(wallCheck.position, wallCheck.position + wallCheckDistance * Vector3.right);
    }
}

源码

整理好了我会放上来

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

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

相关文章

opencascade AIS_InteractiveContext源码学习7 debug visualization

AIS_InteractiveContext 前言 交互上下文&#xff08;Interactive Context&#xff09;允许您在一个或多个视图器中管理交互对象的图形行为和选择。类方法使这一操作非常透明。需要记住的是&#xff0c;对于已经被交互上下文识别的交互对象&#xff0c;必须使用上下文方法进行…

PIRANA: Faster Multi-query PIR via Constant-weight Codes(论文解析)

一、介绍 匿踪查询&#xff1a;一个客户从服务器查询数据&#xff0c;并且服务器无法知晓查询内容。注意这里是保护查询安全&#xff0c;并不保护服务器数据安全。 主要贡献&#xff1a; 1.设计了一款更高速度的匿踪查询方案。 2.设计一款支持批量查询的匿踪查询方案。 3.匿踪…

分享一款Type C接口USB转2路485模块【带完整原理图】

大家好&#xff0c;我是『芯知识学堂』的SingleYork&#xff0c;今天给大家分享一款很实用的工具–基于Type C接口的USB转2路485模块。 这款模块主芯片采用南京沁恒的CH342F这款芯片&#xff0c;芯片特性如下&#xff1a; 该系列芯片有QFN24和ESSOP10 这2种封装&#xff0c;…

快速申请IP地址SSL证书指南

在当今数字化时代&#xff0c;网络安全已成为每个互联网用户和企业的首要关注点。为了保护在线数据传输的安全和隐私&#xff0c;使用SSL证书对网站进行加密变得至关重要。 IP地址SSL证书是一种用于专门保护IP地址的SSL证书。与域名SSL证书不同&#xff0c;IP地址SSL证书可以直…

TensorRT学习(二)TensorRT使用教程(Python版)

本文适合快速了解TensorRT使用的整体流程,具体细节还是建议参考TensorRT的官方文档。 加速原理: 加速原理比较复杂,它将会根据显卡来优化算子,以起到加速作用(如下图所示)。简单的来说,就是类似于你出一个公式1+1+1,而你的显卡支持乘法,直接给你把这个公式优化成了1*…

免费可视化工具如何提升智慧物流管理效率

在现代智慧物流中&#xff0c;免费可视化工具正扮演着越来越重要的角色。这些工具通过数据的可视化展示&#xff0c;使物流管理更加高效、透明和智能化。免费可视化工具可以将复杂的物流数据转换为直观的图表和图形&#xff0c;帮助管理者实时监控和分析物流运作情况&#xff0…

文件销毁是一件非常重要的事情分享一下我是如何安全、环保地处理

如何安全有效地销毁文件&#xff1a;一份详尽指南 在信息爆炸的时代&#xff0c;文件的生成、存储与处理已成为日常生活和工作中不可或缺的一部分。然而&#xff0c;随着数据量的激增&#xff0c;如何妥善管理并最终安全销毁不再需要的文件&#xff0c;成为了一个日益重要的议…

sql拉链表

1、定义&#xff1a;维护历史状态以及最新数据的一种表 2、使用场景 1、有一些表的数据量很大&#xff0c;比如一张用户表&#xff0c;大约1亿条记录&#xff0c;50个字段&#xff0c;这种表 2.表中的部分字段会被update更新操作&#xff0c;如用户联系方式&#xff0c;产品的…

图文识别0难度上手~基于飞浆对pdf简易ocr并转txt

前言 本篇pdf适用windows对视觉识别0基础的的纯小白用户。大佬请绕道~~ 注意&#xff1a; 本项目pdf的ocr对于表格、画图文字&#xff0c;水印等干扰没做任何处理&#xff0c;因此希望各位使用该功能的pdf尽量不要含有这些干扰项&#xff0c;以免影响翻译效果。 流程 1.构建…

vue2项目的打包以及部署

打包 当我们写好vue2的项目后&#xff0c;可以通过npm build来对项目进行打包 npm build 打包完成后我们可以看到在当面目录下生成了dis目录,src下的文件都会被打包进这个目录里&#xff0c;当然打包后的文件我们不能直接在浏览器打开&#xff0c;需要进行部署 部署 1.新建一个…

Ubuntu开通5005端口 记录

Ubuntu版本&#xff1a;20.04 使用systemctl status firewalld查看防火墙状态&#xff0c;报错Unit firewalld.service could not be found 报错的原因是没有安装firewall&#xff0c;安装命令为sudo apt install firewalld&#xff0c;然后进行安装 安装完成后输入systemctl…

大数据可视化实验(八):大数据可视化综合实训

目录 一、实验目的... 1 二、实验环境... 1 三、实验内容... 1 1&#xff09;Python纵向柱状图实训... 1 2&#xff09;Python水平柱状图实训... 3 3&#xff09;Python多数据并列柱状图实训.. 3 4&#xff09;Python折线图实训... 4 5&#xff09;Python直方图实训...…

vscode jupyter选择Python环境时找不到我安装的Python

在一些情况下&#xff0c;我们需要自己安装一个Python&#xff0c;在选择内核是可能找不到指定的Python版本&#xff0c; 再次打开内核选择页面就能看到Python环境了 注意先到指定环境下安装依赖包&#xff1a; ./python3 pip install ipykernel notebook jupyter

高考失利咨询复读,银河补习班客服开挂回复

补习班的客服在高考成绩出来后&#xff0c;需要用专业的知识和足够的耐心来回复各种咨询&#xff0c;聊天宝快捷回复软件&#xff0c;帮助客服开挂回复。 ​ 前言 高考成绩出来&#xff0c;几家欢喜几家愁&#xff0c;对于高考失利的学生和家长&#xff0c;找一个靠谱的复读补…

爬虫笔记18——selenium自动加载并存储vip(唯品会)网页数据

爬取唯品会的商品数据信息 整体的流程就是在唯品会首页搜索栏搜索对应的商品&#xff0c;然后跳转到对应商品页面进行数据的爬取、筛选和存储。 其实也有另外一个爬取方案&#xff0c;不用selenium也是可以爬取到相应的数据&#xff0c;通过分析&#xff0c;搜索结果的页面是…

【机器学习】语音转文字 - FunASR 的应用与实践(speech to text)

本文将介绍 FunASR&#xff0c;一个多功能语音识别模型&#xff0c;包括其特点、使用方法以及在实际应用中的表现。我们将通过一个简单的示例来展示如何使用 FunASR 将语音转换为文字&#xff0c;并探讨其在语音识别领域的应用前景。 一、引言 随着人工智能技术的不断发展&am…

如何理解MySql的MVCC机制

MVCC是什么 MySQL的MVCC机制&#xff0c;全称为多版本并发控制&#xff08;Multi-VersionConcurrency Control&#xff09;&#xff0c;是一种提高数据库并发性能的技术。MVCC的主要目的是在保证数据一致性的同时&#xff0c;提高数据库的并发性能。 它通过为每个读操作创建数…

基于若依(ruoyi-vue)的周报管理系统

喂wangyinlon 填报人页面 审批人 审批不通过,填报人需要重新填写.

【漏洞复现】D-Link NAS 未授权RCE漏洞(CVE-2024-3273)

0x01 产品简介 D-Link 网络存储 (NAS)是中国友讯&#xff08;D-link&#xff09;公司的一款统一服务路由器。 0x02 漏洞概述 D-Link NAS nas_sharing.cgi接口存在命令执行漏洞&#xff0c;该漏洞存在于“/cgi-bin/nas_sharing.cgi”脚本中&#xff0c;影响其 HTTP GET 请求处…

Flink实现准确和高效流处理的关键问题

时间相关: Watermark 水位线 水位线是插入到数据流中的一个标记,可以认为是一个特殊的数据。水位线主要的内容是一个时间戳,用来表示当前事件时间的进展。水位线是基于数据的时间戳生成的。水位线的时间戳必须单调递增,以确保任务的事件时间时钟一直向前推进,进展。水位线…