当前位置: 首页 > news >正文

【Unity案例】搭建射击系统与UI

上期将基础的移动系统搭建完毕后就可以开始搭建更加复杂的系统部分了

前排提示,由于一开始仅思考如何完成操作相关功能,以至于到后面重构稍微有些困难,继续写下去恐成屎山,故在搭完射击和武器UI后不再继续泛化到敌人和敌人状态机

本次主要完成了

自由配置武器参数:武器所需的所有参数都可进行调整

请添加图片描述

武器的追随准星:

根据输入的武器槽位自动平滑的跟随指定武器的枪线,换弹时也会有相应提示

在这里插入图片描述

武器的切换:

不同武器根据数字键进行切换,在UI和准星上也会有所体现

在这里插入图片描述

第一第三人称的切换:

可以在第一第三人称间无缝切换

在这里插入图片描述

请看VCR!

Unity机甲2

文章目录

    • 总览
    • 武器系统
    • 子弹
    • 第一第三人称转换
    • UI

总览

类图结构

请添加图片描述

武器系统

武器使用状态机进行实现,WeaponState继承自State,内部持有Weapon的引用

Weapon是挂载在玩家身上的主要类,一个武器对应一个Weapon,手动输入索引标识其所属的武器槽位

public class Weapon : MonoBehaviour
{public enum FireMode{Single,Brust,Auto}private Entity owner;public int weaponSelectIndex = 0;public bool selected { get; private set; } = false;[Header("武器性能")][SerializeField] private int maxAmmo = 1;                                //最大弹匣弹药量[SerializeField] private int maxPrepareAmmo = 16;                //最大后备弹药量[SerializeField] private float shootingInterval = 0.1f;            //射击间隔[SerializeField] public float reloadTime = 2;                            //换弹时间[Header("开火模式")][SerializeField] public FireMode fireMode = FireMode.Single;      //开火模式 [SerializeField] private int brustNum = 3;                                      //brust一次开火射出的子弹数[SerializeField] private float brustTime = 1;                                  //两次brust开火之间的间隔//[Header("武器状态参数")]private int curAmmo;                                    //当前弹药量private int curPrepareAmmo;                       //当前后备弹药量private float shootingIntervalTimer = 0;    //射击间隔计时器private float brustTimeTimer = 0;               //brust射击间隔计时器private int brustCounter;                             //brust计数器[Header("发射物")][SerializeField] public Transform fireSocket;           [SerializeField] private GameObject bulletPrefab;   public float bulletVelocity = 100;                              public float inertialVelocityMultipler = 10;               public bool constantSpeed = false;                             //本来想做个委托外包出去,想了想不如直接集成在类里得了[Header("特效效果")][SerializeField] private GameObject fireFX;private CinemachineImpulseSource impulseSource;public float cameraShakeMultipler = 1f;[Header("音频")][SerializeField] private AudioClip fireSound;[SerializeField] private AudioClip reloadSound;[SerializeField] private float soundMultipler = 1f;//玩家的输入对应的委托转发public UnityAction onFireStart, onFiring, onFireEnd, onReload;//换弹时的委托,与UI通信使用public UnityAction onReloadStart, onReloadEnd;public UnityAction<float> onReloading;public UnityAction<int, int> onAmmoChanged;//是否选中public UnityAction<bool> onSelectChanged;//自己的状态机private StateMachine stateMachine = new StateMachine();public WeaponIdleState idleState;public WeaponFireState fireState;public WeaponReloadState reloadState;private void Awake(){owner = GetComponent<Entity>();impulseSource = fireSocket.GetComponent<CinemachineImpulseSource>();if (weaponSelectIndex == 1)selected = true;//初始化数据curAmmo = maxAmmo;curPrepareAmmo = maxPrepareAmmo;brustTimeTimer = brustTime;brustCounter = brustNum;//状态初始化idleState = new WeaponIdleState(stateMachine, this);fireState = new WeaponFireState(stateMachine, this);reloadState = new WeaponReloadState(stateMachine, this);//自身赋值到Controller方便其他组件引用PlayerController.Ins.weapons[weaponSelectIndex] = this;}private void Start(){//玩家操作本Weaponowner.onFireStart += () => onFireStart?.Invoke();owner.onFireEnd += () => onFireEnd?.Invoke();owner.onReload += () => onReload?.Invoke();owner.onSelect += (num) =>{selected = num == weaponSelectIndex;onSelectChanged?.Invoke(selected);};owner.onAllSelect += () =>{selected = true;onSelectChanged?.Invoke(selected);};//初始化状态机stateMachine.Init(idleState);}private void Update(){stateMachine.Update();if (shootingIntervalTimer > 0)shootingIntervalTimer -= Time.deltaTime;if (brustCounter <= 0 && brustTimeTimer > 0){brustTimeTimer -= Time.deltaTime;if (brustTimeTimer <= 0)brustCounter = brustNum;}if(owner.firing)onFiring?.Invoke();}public void ModifyAmmo(int amount){curAmmo += amount;curAmmo = Mathf.Clamp(curAmmo, 0, maxAmmo);onAmmoChanged?.Invoke(curAmmo, curPrepareAmmo);}public void Fire(){if (!CanFire())return;//发射投射物Bullet bullet = Instantiate(bulletPrefab, fireSocket.position, fireSocket.rotation).GetComponent<Bullet>();bullet.Init(bulletVelocity, constantSpeed, new Vector3(owner.velocity.x, 0, owner.velocity.z) * inertialVelocityMultipler, owner.flag);//数据更新ModifyAmmo(-1);shootingIntervalTimer = shootingInterval;if (fireMode == FireMode.Brust)                 //如果是Brust模式{brustCounter--;if (brustCounter <= 0)brustTimeTimer = brustTime;}//播放枪口特效Instantiate(fireFX, fireSocket.position, fireSocket.rotation);//震动!impulseSource.m_DefaultVelocity.x = Random.Range(-1f, 1f) * cameraShakeMultipler;impulseSource.m_DefaultVelocity.y = Random.Range(-1f, 1f) * cameraShakeMultipler;impulseSource.m_DefaultVelocity.z = Random.Range(-1f, 1f) * cameraShakeMultipler;impulseSource.GenerateImpulse();//枪口音效AudioManager.PlayClipAtPoint(fireSound, fireSocket.position, soundMultipler);}public void Reload(){int needAmmo = maxAmmo - curAmmo;curAmmo = Mathf.Min(curPrepareAmmo, maxAmmo);curPrepareAmmo = Mathf.Max(curPrepareAmmo - needAmmo, 0);onAmmoChanged?.Invoke(curAmmo, curPrepareAmmo);AudioManager.PlayClipAtPoint(reloadSound, owner.transform.position, soundMultipler);}public bool HaveAmmo() => curAmmo > 0;public bool HavePrepareAmmo() => curPrepareAmmo > 0;public bool CanFire(){if (!selected)return false;//没有子弹if (!HaveAmmo())return false;//没有结束冷却if (shootingIntervalTimer > 0)return false;//如果在Brust模式//如果Counter小于等于0,说明打完了,否则不管//如果打完了并且还没过brust冷却,那就不能打if (fireMode == FireMode.Brust && brustCounter <= 0 && brustTimeTimer > 0)return false;return true;}public bool CanBrust() => brustCounter > 0;public float GetReloadTime() => reloadTime;public int GetCurAmmo() => curAmmo;public int GetCurPrepareAmmo() => curPrepareAmmo;public bool CanReload() => curPrepareAmmo > 0 && curAmmo < maxAmmo;public State GetCurState() => stateMachine.curState;
}

武器的主要逻辑存在于状态机中

在这里插入图片描述

但是由于武器的开火分为连发,单发,爆发,因此还需要做一些特殊的处理

以下是WeaponFireState

在使用爆发模式时,即使玩家松开开火键也不能立即停止开火

public class WeaponFireState : WeaponCommonState
{public bool readyEnd;public WeaponFireState(StateMachine stateMachine, Weapon weapon) : base(stateMachine, weapon){}public override void Enter(){base.Enter();weapon.onFireEnd += OnFireEnd;FireOrReload();readyEnd = false;}public override void Exit(){base.Exit();weapon.onFireEnd -= OnFireEnd;}private void OnFireEnd(){if (weapon.fireMode != Weapon.FireMode.Brust)stateMachine.ChangeState(weapon.idleState);readyEnd = true;}public override void Update(){base.Update();//爆发模式if (weapon.fireMode == Weapon.FireMode.Brust){if (weapon.CanBrust())FireOrReload();else if(readyEnd)stateMachine.ChangeState(weapon.idleState);}else if (weapon.fireMode == Weapon.FireMode.Auto)FireOrReload();}private void FireOrReload(){if (weapon.HaveAmmo()){weapon.Fire();if (!weapon.HaveAmmo())stateMachine.ChangeState(weapon.reloadState);}elsestateMachine.ChangeState(weapon.reloadState);}
}

其他部分较为简短不特别描述

子弹

子弹同样使用一个通用的类进行配置

public class Bullet : MonoBehaviour
{[Header("Physical")]private Rigidbody rb;private Vector3 lastPosition;[Header("Attribute")]//子弹所属派系,可以设定是否开启友军伤害,-1为中立派系public int flag = -1;public float velocity = 100;public bool constantSpeed = false;public float lifeTime = 6f;private float lifeTimer;public float gravityMultiper = 1f;[Header("VFX")]public GameObject explosionPrefab;public GameObject trailPrefab;private void Awake(){rb = GetComponent<Rigidbody>();lastPosition = transform.position;lifeTimer = lifeTime;}public void Init(float velocity, bool constantSpeed, Vector3 inertialVelocity /*惯性力*/, int flag = -1){this.velocity = velocity;this.constantSpeed = constantSpeed;rb.velocity += transform.forward * velocity * Time.fixedDeltaTime / rb.mass;rb.AddForce(transform.forward * velocity + inertialVelocity, ForceMode.Impulse);this.flag = flag;}private void Update(){lifeTimer -= Time.deltaTime;if (lifeTimer < 0)OnCollisionEnter(null);}void FixedUpdate(){//防止错过刚体,对即将经过的间隔做一个射线检测if (Physics.Raycast(lastPosition, rb.velocity.normalized, out RaycastHit hitInfo, rb.velocity.magnitude * Time.fixedDeltaTime)){transform.position = hitInfo.point;rb.velocity = Vector3.zero;return;}//持久动力if (constantSpeed)rb.AddForce(transform.forward * velocity);//调整旋转朝向transform.forward = rb.velocity.normalized;//应用重力乘数rb.velocity += new Vector3(0, 9.8f * (1 - gravityMultiper) * Time.fixedDeltaTime, 0);//记录位置lastPosition = transform.position;}private void OnCollisionEnter(Collision collision){if(collision != null && collision.gameObject.TryGetComponent(out Entity entity)){if (entity.flag == flag)return;}if (trailPrefab){trailPrefab.transform.parent = null;var particleSystems = trailPrefab.GetComponentsInChildren<ParticleSystem>();foreach (var particle in particleSystems){var main = particle.main;main.loop = false;}}Instantiate(explosionPrefab, transform.position, Quaternion.identity);Destroy(gameObject);}private void DelayTrail(){trailPrefab.SetActive(true);}    
}

其内部包含初始惯性处理,持续动力,防止高速穿过物体的处理以及视觉和销毁时如果有拖尾的处理

第一第三人称转换

这一块比较简单,直接使用Cinemachine自带的混合,代码只需要控制两个虚拟相机的激活即可

public class PlayerCameraController : MonoBehaviour
{//Third Person Camera[SerializeField] private CinemachineVirtualCamera thirdPersonCamera;private Cinemachine3rdPersonFollow thirdCameraBody;public float freeLookSide = 0;public float freeLookDistance = 20;float cameraSide;float cameraDistance;//First Peroson Camera[SerializeField] private CinemachineVirtualCamera firstPersonCamera;private Cinemachine3rdPersonFollow firstCameraBody;private Quaternion lastQuaternion;private void Awake(){thirdCameraBody = thirdPersonCamera.GetCinemachineComponent<Cinemachine3rdPersonFollow>();cameraSide = thirdCameraBody.CameraSide;cameraDistance = thirdCameraBody.CameraDistance;firstCameraBody = firstPersonCamera.GetCinemachineComponent<Cinemachine3rdPersonFollow>();}// Update is called once per framevoid Update(){HandleFreeLook();HandleSwitchView();}private void HandleFreeLook(){if (Input.GetKeyDown(KeyCode.C)){//控制器冻结lastQuaternion = PlayerController.GetControllerRotation();PlayerController.SetPause(true);//第三人称参数thirdCameraBody.CameraSide = freeLookSide;thirdCameraBody.CameraDistance = freeLookDistance;//隐藏准星(有视觉Bug)foreach(var hair in UIManager.Ins.crossHairs){hair.gameObject.SetActive(false);}}if (Input.GetKeyUp(KeyCode.C)){//控制器恢复PlayerController.SetControllerRotation(lastQuaternion);PlayerController.SetPause(false);//第三人称参数thirdCameraBody.CameraSide = cameraSide;thirdCameraBody.CameraDistance = cameraDistance;//显示UIforeach (var hair in UIManager.Ins.crossHairs){hair.gameObject.SetActive(PlayerController.Ins.weapons[hair.weaponIndex].selected);}}}private void HandleSwitchView(){if (Input.GetKeyDown(KeyCode.V)){firstPersonCamera.gameObject.SetActive(!firstPersonCamera.gameObject.activeSelf);thirdPersonCamera.gameObject.SetActive(!thirdPersonCamera.gameObject.activeSelf);}}
}

UI

比较重要的地方是丝滑的UI跟随以及实时的武器栏

后者只需要在制作时留意委托就可以很方便的调用,前者则需要一些不同空间的变换知识

准星的跟随部分

一开始我在Canvas中选择的渲染模式是覆盖,后来发现在覆盖的模式下不能添加自发光,导致UI较暗,于是调整为了摄像机空间,但调整后导致原本跟踪正确的准星又不再正确,下面是解决办法

public class CrossHairUI : MonoBehaviour
{//自身private RectTransform rect, parent;[SerializeField] private GameObject aimHair, reloadHair;[SerializeField] private TextMeshPro reloadTxt;//武器public int weaponIndex = 0;private Weapon weapon;private Transform fireSocket;public float lerpMultipler = 0.1f;void Start(){rect = GetComponent<RectTransform>();parent = rect.parent.GetComponent<RectTransform>();weapon = PlayerController.Ins.weapons[weaponIndex];fireSocket = weapon.fireSocket;weapon.onReloadStart += OnReloadStart;weapon.onReloading += OnReloading;weapon.onReloadEnd += OnReloadEnd;weapon.onSelectChanged += (selected) =>{gameObject.SetActive(selected);};gameObject.SetActive(weapon.selected);}void Update(){if (Physics.SphereCast(fireSocket.position, .5f, fireSocket.forward, out RaycastHit hitInfo, 1000)){if(RectTransformUtility.ScreenPointToLocalPointInRectangle(parent, RectTransformUtility.WorldToScreenPoint(Camera.main, hitInfo.point), Camera.main, out Vector2 localPoint)){rect.localPosition = Vector2.Lerp(rect.localPosition, localPoint, lerpMultipler);}}else{Vector3 point = fireSocket.position + fireSocket.forward * 3000;if (RectTransformUtility.ScreenPointToLocalPointInRectangle(parent, RectTransformUtility.WorldToScreenPoint(Camera.main, point), Camera.main, out Vector2 localPoint)){rect.localPosition = Vector2.Lerp(rect.localPosition, localPoint, lerpMultipler);}}}private void OnReloadStart(){aimHair.SetActive(false);reloadHair.SetActive(true);}private void OnReloading(float remainTime){reloadTxt.SetText(remainTime.ToString("0.00"));}private void OnReloadEnd(){aimHair.SetActive(true);reloadHair.SetActive(false);}
}

在Update中首先SphereCast来获取击中的点,再将其WorldToScreenPoint变换到屏幕空间,如果是覆盖的渲染模式,此时已经结束了,但由于是摄像机模式,因此需要再多一个变换即ScreenPointToLocalPointInRectangle将其变换到面板上的相对位置。之后使用插值即可实现丝滑的跟踪准

相关文章:

【Unity案例】搭建射击系统与UI

上期将基础的移动系统搭建完毕后就可以开始搭建更加复杂的系统部分了 前排提示&#xff0c;由于一开始仅思考如何完成操作相关功能&#xff0c;以至于到后面重构稍微有些困难&#xff0c;继续写下去恐成屎山&#xff0c;故在搭完射击和武器UI后不再继续泛化到敌人和敌人状态机…...

Python使用zdppy_mysql操作MySQL和MariaDB数据库快速入门教程

zdppy_mysql 使用python操作MySQL 项目开源地址&#xff1a;https://github.com/zhangdapeng520/zdppy_mysql 安装 pip install zdppy_mysql使用教程 连接MySQL import zdppy_mysql from config import host, username, password, database, port# 连接数据库 db zdppy_…...

union 的正确食用方法

0.前情提要 &#xff08;很久&#xff09;之前上编译原理时&#xff0c;一次实验课需要补充完善一个用 c 写的词法分析器&#xff1b;而这个分析器在定义语法树结点时使用了 union 存储语言中不同表达式的类型标签或值本身。因为当时刚好学完了 cpp&#xff0c;拿着锤子看啥都…...

汇编语言在虚拟机中输出“Hello World!”

1.软件 Nasmide64.exe(李忠老师编写) Fixvhdw64.exe(李忠老师编写) VirtualBox虚拟机(免费 开源) 2.过程 01.Fixvhdw64.exe输入以下代码: mov ax,0xb800 mov ds,ax mov byte [0x00],H mov byte [0x02],e mov byte [0x04],l mov byte [0x06],l mov byte [0x08],o mov byte…...

JVM类的加载和类的加载器

JVM类的加载和类的加载器 一.类的加载过程 类的加载指的是将类的.class文件中的二进制数据读入到内存中&#xff0c;将其放在运行时数据区的方法区内&#xff0c;然后在堆区创建一个java.lang.Class对象&#xff0c;用来封装类在方法区内的数据结构。类的加载的最终产品是位于…...

MLM:多模态大型语言模型的简介、微调方法、发展历史及其代表性模型、案例应用之详细攻略

MLM&#xff1a;多模态大型语言模型的简介、微调方法、发展历史及其代表性模型、案例应用之详细攻略 目录 相关文章 AI之MLM&#xff1a;《MM-LLMs: Recent Advances in MultiModal Large Language Models多模态大语言模型的最新进展》翻译与解读 MLM之CLIP&#xff1a;CLIP…...

Java健康养老智慧相伴养老护理小程序系统源码代办陪诊陪护更安心

健康养老&#xff0c;智慧相伴 —— 养老护理小程序&#xff0c;代办陪诊陪护更安心 &#x1f308;【开篇&#xff1a;智慧养老&#xff0c;新时代的温馨守护】&#x1f308; 在这个快节奏的时代&#xff0c;我们总希望能给予家人更多的关爱与陪伴&#xff0c;尤其是家中的长…...

Python | Leetcode Python题解之第390题消除游戏

题目&#xff1a; 题解&#xff1a; class Solution:def lastRemaining(self, n: int) -> int:a1 1k, cnt, step 0, n, 1while cnt > 1:if k % 2 0: # 正向a1 stepelse: # 反向if cnt % 2:a1 stepk 1cnt >> 1step << 1return a1...

Github 2024-09-01 开源项目月报 Top16

根据Github Trendings的统计,本月(2024-09-01统计)共有16个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目9TypeScript项目5Dart项目2C项目1Jupyter Notebook项目1Rust项目1开发者职业成长指南 创建周期:2670 天开发语言:TypeScript协议类…...

C++ 继承(二)

目录 1. 实现一个不能被继承的类 2. 友元与继承 3.继承与静态成员 4.多继承及其菱形继承问题 (1). 继承模型 (2). 虚继承 (2.1)虚继承解决数据冗余和二义性的原理 (3). 多继承中指针偏移问题 (4). IO库中的菱形虚拟继承 5. 继承和组合 1. 实现一个不能被继承的类 方法1…...

第 2 章:AJAX 的使用

AJAX 的使用 核心对象&#xff1a;XMLHttpRequest&#xff0c;AJAX 的所有操作都是通过该对象进行的。 1. 使用步骤 创建 XMLHttpRequest 对象 var xhr new XMLHttpRequest(); 设置请求信息 xhr.open(method, url);//可以设置请求头&#xff0c;一般不设置 xhr.setReques…...

ROS——视觉抓取

纲要 视觉抓取中的关键技术 内参标定 物体识别定位 抓取姿态分析 运动规划 外参标定 任意两个位姿之间的关系 眼在外 眼在内 手眼标定流程 robot 部分 标定效果 视觉抓取例程 grasping_demo.cpp 获取两个坐标系之间变换关系:waitForTransform 、 LookupTransform 求相…...

EPLAN2022基础教程

EPLAN2022软件介绍 EPLAN是一款专业的电气设计和绘图软件&#xff0c;它可以帮助我创建和管理电气项目&#xff0c;生成各种报表和文档&#xff0c;与其他软件和系统进行交互&#xff0c;优化工程流程和质量。与传统的CAD绘图对比&#xff0c;EPLAN更适合绘制电气原理图。 下…...

【JavaWeb】Servlet 详解(处理逻辑及常见方法)

文章目录 1. Tomcat1.1 常见的错误1.1.1 出现 4041.1.2 出现 4051.1.3 出现 500 1.2 HttpServlet1.2.1 Tomcat 的处理逻辑1.2.2 相关方法 1.3 HttpServletRequest1.3.1 常见方法1.3.2 jackson 处理逻辑 1.4 HttpServletResponse1.4.1 常见方法 1. Tomcat tomcat 是一个 HTTP 服…...

6 自研rgbd相机基于rk3566之深度计算库程序详解

自研rgbd相机基于rk3566之深度计算库详解 1 tof深度计算库框架读入深度图像参数配置tof模组标定参数读入及解析深度计算函数接口2 tof深度计算库程序详解深度计算程序头文件深度计算程序 源文件1 tof深度计算库框架 读入深度图像参数配置 支持raw8/raw10/raw16 格式 /*******…...

分布式系统框架hadoop3入门

分布式系统框架hadoop3入门 (qq.com) Hadoop3作为分布式系统架构的重要基石&#xff0c;为大规模数据存储与处理提供了强大支持 基本信息 hadoop&#xff1a;一个存储和处理大数据的分布式系统框架 组成&#xff1a; HDFS&#xff08;数据存储&#xff09;、MapReduce&…...

使用 i3.LayoutCell() 方法绘制版图并输出为 GDS 文件

使用 i3.LayoutCell 方法绘制版图并输出为 GDS 文件 引言正文引言 在 IPKISS i3.SRef() 函数 一文中我们介绍了如何使用 i3.SRef() 函数将 instance 对象添加到 i3.LayoutCell() 创建的 Cell 对象上。但是当我们使用 write_gdsii() 输出版图时代码就会报错。这里我们将介绍如何…...

mariadb容器

下载镜像 $ sudo docker pull mariadb启动容器 $ sudo docker run --name my-mariadb -d -e MARIADB_DATABASEtestdb -e MARIADB_ROOT_PASSWORDLetmein -p 3306:3306 mariadb上面命令会启动一个名为my-mariadb的容器&#xff0c;并初始化一个testdb数据库&#xff0c;同时设置…...

应用层协议Http

Http协议 1.1 什么是http协议 在进行网络通信时&#xff0c;应用层协议一般都是程序员自己写的&#xff0c;但是有一些大佬其实已经定义出了一些现成的应用层协议&#xff0c;例如&#xff1a;HTTP&#xff08;超文本传输协议&#xff09;、FTP&#xff08;文件传输协议&#…...

display flex 的div 被子元素撑开不显示滚动条的一个解决demo

display flex 的div 被子元素撑开&#xff0c;不显示y轴滚动条的 一个解决demo。 注&#xff1a; 不一定适用所有人的的相同问题 less # less .contact {display: flex;flex-grow: 1;overflow: hidden auto;flex-direction: column;.contact-items {flex: 1 1 0;display: flex…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...