【Unity入门】详解Unity中的射线与射线检测
目录
- 前言
- 一、射线的创建方法
- 二、射线检测
- 1、Raycast()
- Raycast()不使用射线Ray
- Raycast()使用射线Ray
- 2、RaycastAll()
- 使用射线Ray
- RaycastAll() 不使用射线Ray
- 3、射线的碰撞信息
- 三、示例
- 四、具体使用场景
- 射线的调试方法
- 1、Debug.DrawLine()
- 2、Debug.DrawRay
- 利用Gizmos
前言
碰撞检测可以帮助我们实现诸如抵达某个地点自动触发剧情、判断子弹是否击中玩家等功能,但我如果想要实现如当鼠标悬浮某个人物上,自动弹出该人物信息,要如何判断呢?这时使用碰撞检测,从摄像机生成一个透明碰撞体朝着人物移动,等碰撞到了人物再弹出该人物信息?会不会太繁琐了。或许你又会想,若我直接生成一个足够长的透明碰撞体呢,是不是在创建的那一刻就可以触发该人物的弹出信息逻辑?没错这样的确可以,而这就是射线!不过是把无限长的透明碰撞体变为了无限长的一条线,仅此而已。
一、射线的创建方法
常用的直线射线类型用类型Ray表示,Ray包含了 起点origin 跟 方向direction的定义,起点和方向都用Vector3类型表示,前者是一个坐标,后者是一个表示方向的向量。
Vector3 origin = transform.position;
Vector3 direction = Vector3.down;
Ray ray = new Ray(origin, direction);
二、射线检测
在游戏中发射一条射线,最常用的是Physics.Raycast()和Physics.RaycastAll(),前者只能检测一个碰撞体而被返回,后者可以一起检测多个碰撞体。如果使用 Physics.RaycastAll() 进行多次射线投射,将返回一个 RaycastHit[] 数组,其中包含所有射线与场景中对象的交互信息。这在需要获取所有碰撞点信息的情况下很有用。
1、Raycast()
从某个初始点开始,沿着特定的方向发射一条不可见且无限长的射线,通过此射线检测是否有任何模型添加了Collider碰撞器组件。一旦检测到碰撞,停止射线继续发射。
Raycast()不使用射线Ray
public static bool Raycast (Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask, QueryTriggerInteraction queryTriggerInteraction);
参数:
- origin:射线在世界坐标系中的起点。
- direction:射线的方向。
- hitInfo:如果返回 true,则 hitInfo 将包含有关最近的碰撞体的命中位置的更多信息。(另请参阅:RaycastHit)。
- maxDistance:射线应检查碰撞的最大距离。(可选,不写默认无限长)
- layerMask:层遮罩,用于在投射射线时有选择地忽略碰撞体。(可选,不写默认检测所有层)
- queryTriggerInteraction:指定该查询是否应该命中触发器。可以通过指定 queryTriggerInteraction 来控制是让触发碰撞体生成命中效果,还是使用全局 Physics.queriesHitTriggers 设置。
返回
bool 当光线与任何碰撞体相交时,返回 true,否则返回 false
Raycast()使用射线Ray
public static bool Raycast (Ray ray, out RaycastHit hitInfo, float maxDistance= Mathf.Infinity, int layerMask= DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction= QueryTriggerInteraction.UseGlobal);
参数:
- ray 光线的起点和方向。
- hitInfo:如果返回 true,则 hitInfo 将包含有关最近的碰撞体的命中位置的更多信息。(另请参阅:RaycastHit)。
- maxDistance 射线应检查碰撞的最大距离。(可选,不写默认无限长)
- layerMask 层遮罩,用于在投射射线时有选择地忽略碰撞体。(可选,不写默认检测所有层)
- queryTriggerInteraction 指定该查询是否应该命中触发器。
返回
bool 当光线与任何碰撞体相交时,返回 true,否则返回 false
Physics.Raycast 更多详情
2、RaycastAll()
使用射线Ray
public static RaycastHit[] RaycastAll (Ray ray, float maxDistance= Mathf.Infinity, int layerMask= DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction= QueryTriggerInteraction.UseGlobal);
参数:
- ray 光线的起点和方向。
- maxDistance 从射线起点开始,允许射线命中的最大距离。(可选,不写默认无限长)
- layerMask 层遮罩,用于在投射射线时有选择地忽略碰撞体。(可选,不写默认检测所有层)
- queryTriggerInteraction 指定该查询是否应该命中触发器。
返回
RaycastHit[] RaycastHit 对象的数组。注意,这些结果的顺序未定义。
描述
向场景中投射射线并返回所有命中对象。注意,这些结果的顺序未定义。
RaycastAll() 不使用射线Ray
public static RaycastHit[] RaycastAll (Vector3 origin, Vector3 direction, float maxDistance= Mathf.Infinity, int layerMask= DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction= QueryTriggerInteraction.UseGlobal);
参数
- origin 射线在世界坐标系中的起点。
- direction 射线的方向。
- maxDistance 从射线起点开始,允许射线命中的最大距离。(可选,不写默认无限长)
- layermask 层遮罩,用于在投射射线时有选择地忽略碰撞体。(可选,不写默认检测所有层)
- queryTriggerInteraction 指定该查询是否应该命中触发器。
Physics.RaycastAll 更多详情
3、射线的碰撞信息
我们再重点讲讲第三个参数RaycastHit,若没有这个参数,我们的返回值仅仅只是“是否碰到了物体”,而无法确定碰撞点在哪,也不知道碰撞体是哪一个。射线检测其实有着非常丰富的碰撞信息,如可以获得其碰撞坐标,信息,以及法线。这些丰富的信息都被保存在RaycastHit结构体中。
综合用法演示如下:
//声明变量,用于保存信息
RaycastHit hitInfo;
//发射射线,起点是当前物体位置,方向是世界前方
if(Physics.Raycast(transform.position,Vector3.forward,out hitInfo))
{//如果碰到物体,运行此处,返回的是bOOl值//获取碰撞点坐标Vector3 point = hitInfo.point;//获取对方碰撞体组件Collider coll = hitInfo.collider;//获取对方的Transgorm组件Transform trans = hitInfo.transform;//获取对方的物体名称string name = hitInfo.collider.name;//获取碰撞点的法线向量Vector3 normal = hitInfo.normal;
}
注意,2D游戏跟3D游戏获取碰撞体的方式有些不一样,具体对比如下
//声明变量,将碰撞信息直接赋值给变量
RaycastHit2D hitInfo=Physics2D.Raycast(transform.position,Vector3.forward);
//发射射线,起点是当前物体位置,方向是世界前方
if(hitInfo.collider != null)
{//如果检测的碰撞体不为空,运行此处。//获取碰撞点坐标Vector3 point = hitInfo.point;//获取对方碰撞体组件Collider coll = hitInfo.collider;//获取对方的Transgorm组件Transform trans = hitInfo.transform;//获取对方的物体名称string name = hitInfo.collider.name;//获取碰撞点的法线向量Vector3 normal = hitInfo.normal;
}
三、示例
//第一个简单小栗子void Update(){Ray ray = new Ray(transform.position, transform.forward);//声明一个Ray结构体,用于存储该射线的发射点,方向RaycastHit hitInfo;//声明一个RaycastHit结构体,存储碰撞信息if (Physics.Raycast(ray, out hitInfo)){Debug.Log(hitInfo.collider.gameObject.name);//这里使用了RaycastHit结构体中的collider属性//因为hitInfo是一个结构体类型,其collider属性用于存储射线检测到的碰撞器。//通过collider.gameObject.name,来获取该碰撞器的游戏对象的名字。}}
//第二个简单小栗子void Update(){RaycastHit hitInfo;if (Physics.Raycast(transform.position, transform.forward, out hitInfo)){Debug.Log(hitInfo.collider.gameObject.name);}}
四、具体使用场景
当使用 RaycastHit 类进行射线投射时,有许多不同的使用场景,包括检测碰撞、拾取物体、瞄准检测、物体高亮等。在以下每个场景示例中,我将向您展示如何使用 RaycastHit,并加入一些粒子效果(“lizi”,即粒子效果在中文中的写法)来增强可视化效果。
- 检测碰撞并发射粒子:
在这个场景中,我们将使用射线投射来检测是否与一个可交互的对象发生碰撞,然后在碰撞点发射一些粒子效果。
using UnityEngine;public class RaycastCollisionExample : MonoBehaviour
{public ParticleSystem collisionParticles; // 粒子效果void Update(){Ray ray = new Ray(transform.position, transform.forward);RaycastHit hitInfo;if (Physics.Raycast(ray, out hitInfo)){// 碰撞点发射粒子效果if (collisionParticles != null){collisionParticles.transform.position = hitInfo.point;collisionParticles.Play();}Debug.Log("碰撞对象:" + hitInfo.collider.gameObject.name);}}
}
在这个示例中,我们在碰撞点发射了一个粒子效果,从而在用户与可交互对象发生碰撞时产生视觉效果。
- 物体拾取与交互:
在这个场景中,我们将使用射线投射来检测是否与一个可拾取的物体发生碰撞,然后可以将物体拾取并交互。
using UnityEngine;public class ObjectPickupExample : MonoBehaviour
{private Transform pickedObject = null; // 当前拾取的物体void Update(){Ray ray = new Ray(transform.position, transform.forward);RaycastHit hitInfo;if (Physics.Raycast(ray, out hitInfo)){// 拾取物体if (Input.GetKeyDown(KeyCode.E)){if (hitInfo.collider.CompareTag("Pickable")){pickedObject = hitInfo.collider.transform;Debug.Log("拾取了:" + pickedObject.name);}}// 交互if (Input.GetKeyDown(KeyCode.F)){if (pickedObject != null){Debug.Log("与 " + pickedObject.name + " 进行了交互。");}}}}
}
在这个示例中,我们使用 Input.GetKeyDown(KeyCode.E) 来拾取与射线相交的可拾取物体,并使用 Input.GetKeyDown(KeyCode.F) 来与拾取的物体进行交互。
- 物体高亮效果:
在这个场景中,我们将使用射线投射来检测是否与一个物体发生碰撞,然后在碰撞对象上显示一个高亮的粒子效果。
using UnityEngine;public class ObjectHighlightExample : MonoBehaviour
{public ParticleSystem highlightParticles; // 高亮粒子效果private Transform lastHighlightedObject = null; // 上一个高亮的物体void Update(){Ray ray = new Ray(transform.position, transform.forward);RaycastHit hitInfo;if (Physics.Raycast(ray, out hitInfo)){// 高亮物体if (hitInfo.collider.CompareTag("Highlightable")){if (lastHighlightedObject != hitInfo.collider.transform){if (lastHighlightedObject != null){highlightParticles.Stop();}lastHighlightedObject = hitInfo.collider.transform;highlightParticles.transform.position = lastHighlightedObject.position;highlightParticles.Play();}}else if (lastHighlightedObject != null){highlightParticles.Stop();lastHighlightedObject = null;}}}
}
在这个示例中,我们使用高亮粒子效果来显示玩家当前所指的物体。粒子效果在物体上播放和停止,从而实现高亮效果。
- 通过鼠标点击的位置获取与射线碰撞的物体
private void Update(){if (Input.GetMouseButtonDown(0)){/*判断鼠标是否点击在UI上*/if (EventSystem.current.IsPointerOverGameObject() == false){/*通过鼠标位置获取射线*/Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);/*用于存储射线投射操作的结果*/RaycastHit hit;/* Physics.Raycast参数:* 射线在世界坐标系中的起点、* 射线的方向和存储射线投射操作的结果、* 射线应检查碰撞的最大距离、* 层遮罩,用于在投射射线时有选择地忽略碰撞体*/bool isCpllider = Physics.Raycast(ray, out hit, 1000, LayerMask.GetMask("MapCobe"));if (isCpllider){/*得到点击的MapCude*/GameObject mapCude = hit.collider.gameObject;Debug.Log("成功");}}}}
注意:Collider组件中Is Trigger选项的开关并不影响射线检测! 对了还有一个参数,写在Raycast末尾,QueryTriggerInteraction(指定该射线是否应该命中触发器),上面我说过Is Trigger选项的开关不影响射线检测,但是前提是QueryTriggerInteraction该参数设置为检测触发器了,你也可以将该参数设置为仅对碰撞器进行检测,这个参数可以全局设置。对于射线投射起点位于碰撞体内的情况,Raycast 不会检测到碰撞体。在所有这些示例中,都使用了 FixedUpdate 而不是 Update。请参阅事件函数的执行顺序,以了解 Update 与 FixedUpdate 的区别,以及它们与物理查询的关系。
射线的调试方法
利用Debug调试
在游戏开发中,射线的调试方法非常重要,可以将看不见的射线以可视化的形式表现出来,方便我们查看数据是否正确。这个方法是使用Debug.DrawLine()函数和Debug.DrawRay()
1、Debug.DrawLine()
public static void DrawLine (Vector3 start, Vector3 end, Color color= Color.white, float duration= 0.0f, bool depthTest= true);
参数:
- start 应作为该直线起始点的世界空间中的点。
- end 应作为该直线结束点的世界空间中的点。
- color 该直线的颜色。
- duration 该直线的可见长度应为多长。
- depthTest 该直线是否应被靠近此摄像机的对象遮挡?
描述
在指定的起始点与结束点之间绘制一条直线。
当游戏正在运行并且启用辅助图标绘图时,将在 Editor 的游戏视图中绘制直线。当直线在游戏视图中可见时,还会在场景中绘制该直线。让游戏运行并显示直线。切换到场景视图,该直线将可见。
duration 是在第一次显示该直线后该直线可见的时间长短(单位为秒)。如果持续时间为零,则该直线仅显示一帧。
注意:这仅用于调试播放模式。应改用 Gizmos.Drawline 或 Handles.DrawLine 来绘制 Editor 辅助图标。
Debug.DrawLine 更多详情
2、Debug.DrawRay
public static void DrawRay (Vector3 start, Vector3 dir, Color color= Color.white, float duration= 0.0f, bool depthTest= true);
参数:
- start 应作为该射线起始点的世界空间中的点。
- dir 该射线的方向和长度。
- color 绘制的直线的颜色。
- duration 该直线的可见时长(单位为秒)。
- depthTest 该直线是否应被靠近此摄像机的其他对象遮挡?
描述
在世界坐标中绘制一条从 start 到 start + dir 的直线。
duration 参数确定在绘制该直线所在的帧之后该直线可见时长。如果持续时间为 0(默认值),则该直线被渲染 1 帧。
如果将 depthTest 设置为 true,则该直线将被此场景中更靠近摄像机的其他对象遮挡。将在该 Editor 的场景视图中绘制该直线。如果在游戏视图中启用了辅助图标绘图,则在该视图中也将绘制该直线。
Debug.DrawRay 更多详情
效果图可以看上面,都有涉及使用到。需要说明的是在默认的情况下,该辅助线仅在编辑器的场景窗口可见,如果要在game窗口看到,则需要单机Game窗口右上角的Gizmos开关。
利用Gizmos
调用OnDrawGizmos()函数或OnDrawGizmosSelected,它们同样都可以用来绘制辅助图标。区别在于
函数OnDrawGizmos()在程序一运行就执行,之后每帧都在执行,
函数OnDrawGizmosSelected()在鼠标点击到脚本挂载的物体的身上的时候运行,不管有多少父类对象,它都会执行。
这里推荐使用OnDrawGizmosSelected()
范例如下
private void OnDrawGizmosSelected(){Gizmos.DrawLine(Vector3 from, Vector3 to);Gizmos.DrawRay((Vector3 from, Vector3 direction);}
可在scence窗口查看辅助线,同样想在game窗口可以看到,则需要单机Game窗口右上角的Gizmos开关。
相关文章:
【Unity入门】详解Unity中的射线与射线检测
目录 前言一、射线的创建方法二、射线检测1、Raycast()Raycast()不使用射线RayRaycast()使用射线Ray 2、RaycastAll()使用射线RayRaycastAll() 不使用射线Ray 3、射线的碰撞信息 三、示例四、具体使用场景射线的调试方法1、Debug.DrawLine()2、Debug.DrawRay利用Gizmos 前言 碰…...
实验11-2-5 链表拼接(PTA)
题目: 本题要求实现一个合并两个有序链表的简单函数。链表结点定义如下: struct ListNode {int data;struct ListNode *next; }; 函数接口定义: struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2); 其中lis…...
Mybatis Plus + Spring 分包配置 ClickHouse 和 Mysql 双数据源
目录 一、背景 二、各个配置文件总览(文件位置因人而异) 2.1 DataSourceConfig 2.2 MybatisClickHouseConfig (ClickHouse 配置类) 2.3 MybatisMysqlConfig(Mysql 配置类) 2.4 application.propertie…...
27-3 文件上传漏洞 - 文件类型绕过(后端绕过)
环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 导语 后端校验由开发决定是检测文件后缀,还是文件内容。 文件类型绕过(Content-Type) 1)MIME 类型 定义:MIME(Multipurpose Internet Mail Extensions)类型是一种标准,…...
widget一些控件的使用
QRadioButton使用 先使用ui界面拖拽创建radio button #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->male->setChecked(true);//选中按钮ui->o…...
Python基础(七)之数值类型集合
Python基础(七)之数值类型集合 1、简介 集合,英文set。 集合(set)是由一个或多个元素组成,是一个无序且不可重复的序列。 集合(set)只存储不可变的数据类型,如Number、…...
电脑充电器能充手机吗?如何给手机充电?
电脑充电器可以给手机充电吗? 电脑充电器可以给手机充电,但前提是电脑充电器的功率输出与手机的功率匹配且接口匹配。 假设电脑充电器的输出功率为5V/2A,手机也支持5V/2A的输入功率。 只要接口匹配,就可以使用电脑充电器给手机充…...
矩阵中移动的最大次数
文章目录 所属专栏:BFS算法 题目链接 思路如下: 1.首先我们需要从第一列开始遍历,寻找每一个都能够满足条件的位置,将它插入到数组里面 2.第一列遍历完了后我们先判断第一列的数是否都满足条件插入到数组里面,如果数组为空&#…...
Linux:系统初始化,内核优化,性能优化(3)
优化系统的文件句柄数(全局) 也就是系统的最大文件数量 查看最大数量 cat /proc/sys/fs/file-max 当我们的服务器有非常大的一个数据并发的时候十几二十万的文件需要去配置,可能这个是远远不够的,我们就要去修改 vim /etc/sy…...
使用 GitHub Actions 通过 CI/CD 简化 Flutter 应用程序开发
在快节奏的移动应用程序开发世界中,速度、可靠性和效率是决定项目成功或失败的关键因素。持续集成和持续部署 (CI/CD) 实践已成为确保满足这些方面的强大工具。当与流行的跨平台框架 Flutter 和 GitHub Actions 的自动化功能相结合时,开发人员可以创建无…...
微软 CEO Satya Nadella 的访谈
Nicolai: 大家好。我刚经历了人生中最不可思议的事情,我有幸采访了微软的 CEO、Satya Nadella。微软现在是全球市值最高的公司。真是太棒了,请继续关注。 第一章 微软的发展与平台转变 Nicolai: Satya,你是全球市值最高公司的 CEOÿ…...
万界星空科技商业开源MES,技术支持+项目合作
商业开源的一套超有价值的JAVA制造执行MES系统源码 亲测 带本地部署搭建教程 教你如何在本地运行运行起来。 开发环境:jdk11tomcatmysql8springbootmaven 可以免费使用,需要源码价格便宜,私信我获取。 一、系统概述: MES制造执…...
Docker Mysql无root账户创建最高权限用户
创建最高权限用户 进入 MySQL 容器的命令行界面。您可以使用以下命令: 修改配置文件my.cnf 无密码进入 [mysqld]下输入 skip-grant-tables重启mysql容器 进入容器内部 container_name 容器ID或name docker restart mysql docker exec -it <container_name>…...
常用芯片学习——DS3231M芯片
DS3231M RTC实时时钟 芯片介绍 DS3231M是一款低成本、极其精确的 I2C 实时时钟 (RTC)。该设备集成了电池输入,并在设备主电源中断时保持准确的计时。微型电子机械系统 (MEMS) 谐振器的集成提高了器件的长期精度&…...
蓝桥杯单片机快速开发笔记——矩阵键盘
一、原理分析 二、思维导图 三、示例框架 定义了四个位控制变量,用于控制键盘扫描时的行列信号。 在Scan_Keys()函数中,首先设置行列信号,将其中一个行信号置为0,另一个行信号置为1,同时将列信号置为1,用于…...
每周一算法:双向深搜
题目描述 达达帮翰翰给女生送礼物,翰翰一共准备了 N N N 个礼物,其中第 i i i 个礼物的重量是 G [ i ] G[i] G[i]。 达达的力气很大,他一次可以搬动重量之和不超过 W W W的任意多个物品。 达达希望一次搬掉尽量重的一些物品,请…...
蓝桥杯刷题(十)
1.翻转 代码 输入数据,每组数据进行比较,j的范围掐头去尾,若a[j]b[j],继续,若出现010,101子串则改成000,111,遍历完后比较a是否等于b,相同则输出次数,不同则输出-1。 for _ in ran…...
ioDraw:与 GitHub、gitee、gitlab、OneDrive 无缝对接,绘图文件永不丢失!
🌟 绘图神器 ioDraw 重磅更新,文件保存再无忧!🎉 无需注册,即刻畅绘!✨ ioDraw 让你告别繁琐注册,尽情挥洒灵感! 新增文件在线实时保存功能,支持将绘图文件保存到 GitHu…...
利用 Python 处理遥感影像数据:计算年度平均影像
在地球科学、气象学以及环境监测等领域,遥感影像数据是一种重要的信息源,它们可以提供地表的地形、植被覆盖、气候变化等丰富信息。然而,随着观测技术的进步,我们通常会获得大量的遥感影像数据,如何高效地处理和分析这…...
【Leetcode-73.矩阵置零】
题目: 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1: 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出:[[1,0,1],[0,0,0],[1,0,1]]示例 2&…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
