Pixel Adventure Unity2D开发完整指南
本文参考:2-2. Get and Setup Assets_哔哩哔哩_bilibili
1、下载资源
在Asset Store中下载Pix Adventure1 +2的资源:
在import的时候,不用到Scene import进来,如下图所示,Scenes目录反勾选一下。
两个资源都下载完成后,则下图所示:
在Assets下创建目录名为Graphiics,然后把Pixel Adventure1和Pixel Adventure2下Assets中的内容全部都copy到Graphics目录下,如下图所示:
2、Unity使用基础说明
(1)CSharp知识
1)virtual和abstract的区别
abstract方法只能声明在抽象类中,同时不能有方法体,必须被子类重写
virtual方法可以声明在任何非密封类中,它可以有方法体,可以被子类选择性重写
2)使用父类的方法
base.func()
(2)Collider
我们经常使用的Collider是Box Collider,这个是矩形的碰撞体。实际上还有Circle Collider。这样,针对不同的物体形状,我们可以选择不同的Collider。
(3)Debug模式
在Normal模式下,我们看到的是对象所有组件的Inspector信息,如下:
在Debug模式下,我们可以看到组件中各个变量的详细信息,所以debug时该模式非常有用。
(4)SerializeField字段
在C#脚本中
如果我们希望公开某个变量,那么可以使用public进行标识
如果我们不希望公开某个变量,那么可以使用private进行标识
如果我们不希望公开某个变量,但是在Inspector中又可以看到该变量的值,那么可以使用private进行标识,同时加上[SerializeField]的标识,示例如下:
[SerializeField] private float speed;
(5)Header字段
用于标记下方在Inspector中显示字段的header名称,效果如下:
(6)ContextMenu字段
创建类的选项,本身继承自MonoBehaviour。
比如在脚本中创建ContextMenu信息如下:
[ContextMenu("Debug here")]private void print(){Debug.Log("here!");}
此时当脚本挂载到某个对象后,右击该脚本,即可看到"Debug here"的选项,点击该选项即可执行对应的函数。
(7)Camera方式让Game视野变大
如果Game中物体过大,一种做法是分别缩小每个物体,如果物体特别多操作起来特别麻烦。另一种做法是,修改Camera的size大小,值越大视野也就越大。
(8)Flip左右翻转的方法
transform.Rotate(0, 180, 0);
通过rb.velocity.x判断朝向,如果该值小于0则朝左,否则朝右。
完整方法:
(9)例程(类似进程)
启动例程:StartCoroutine(func()), func的返回值为IEnumerator类型。
使用例程的好处:单独开进程,不会阻塞当前主进程。
比如例程中含有sleep时间,主线程就不用卡在那里了。
等待的写法:yield return new WaitForSeconds(xx);
例程举例:
假如两个例程存在相互干扰,那么可以在例程开始时停止已有的所有例程,使用StopAllCoroutines()方法。
比如:
(10)物体移动的方式
方法1: transform.position = new Vector2(pos.x, pos.y);
方法2:transform.position = Vector2.MoveTowards(pos1, pos2, moveSpeed * Time.deltaTime);
(11)给物体施加力量rb.AddForce
方法1:AddForce(Vector3 force),使用Vector3类型参数,可以分别向刚体按Vector3对象指定x/y/z分量施加力。使用该方法会对刚体施加一个持续的力。rb.AddForce(new Vector3(10f, 0f, 0f));
方法2:AddForce(x, y, x),与方法1类似,只是把Vector3的3个值拆开了。
方法3:AddForce(Vector3 force, ForceMode mode),其中force是施加力的矢量,参数mode是一个枚举类型的参数,用于指定力的模式。模式有:
- ForceMode.Force:施加一个持续的力
- ForceMode.Impulse:施加一个瞬间的冲击力
- ForceMode.Acceleration:施加一个持续的加速度
- ForceMode.VelocityChange:施加一个改变刚体速度的力
方法4:AddForce(x, y, z, ForceMode mode),与方法3类似,只是把Vector3的3个值拆开了。
(12)创建预设体
GameObject newObj = Instantiate(prefab, position, Quaternion.identity);
其中,prefab也是GameObject的对象
position是Vector3的位置信息
Quaternion.identity表示新复制的对象不会有初始旋转,假如使用prefab.transform.rotation表示新复制的对象会保留原来的旋转。
(13)Invoke委托函数
它是U3D的一种委托机制。
Invoke("SendMsg", 5); 意思是:5秒钟之后调用SendMsg()方法。
注意:
1)只能在脚本的生命周期里的(Start、Update、OnGUI、FixedUpdate、LateUpdate)中被调用
2)Invoke不接受含有参数的方法
3)当Time.ScaleTime = 0 时 invoke()方法无效
(14)Raycast检测光线
Physics2D.Raycast是用于检测2D光线命中图层的函数,可以用于检测光线是否与指定图层中的物体相交,并返回相交点的信息。
常见的使用方法:
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, rayDirection, rayLength, layerMask);
rayOrigin:光线的起点
rayDirection:光线的方向
rayLength:光线的长度
layerMask:需要检测的图层
(15)设置物体间的碰撞矩阵
在Edit -> Project Settings -> Physics 2D -> Layer Collision Matrix
通过设置该矩阵,可以让反选的两个物体之间不会发生碰撞。
3、Animator和Animation的使用
(1)创建Idle动画
Animation用来将图片生成动画,Animator可控制动画的状态。
首先,在Assets下创建Animations的目录,并在该目录下右击创建Animator Controller,如下图所示:
其次,在SampleScene中Create Empty,命名为Player。将Graphics -> Main Characters -> Virtual Guy中Idle的一张图片拖入Scene,该对象重命名为Animator,并移到Player的下一级。同时将上一步的Animator Controller拖到Animator下作为组件。如下图所示:
此时,双击Animator组件的Controller的Player,会进入Animator的编辑界面。
点击Window -> Animation -> Animation,就出来Animation的编辑界面。
点击Create,重命名为PlayerIdle,此时在Animator界面中会自动出现PlayerIdle的节点,并且与Entry相连。
然后将Assets的Graphics下所有的Idle图片拖入Animation中,点击播放就可以看到Idle状态下的动画了。
播放动画时会发现对象运动过快,此时需要调整Sample Rate的值,但是目前Animation界面中没有操作该值的选项。需要点击Animation界面右上角的三个点,然后点击"Show Sample Rate"。
默认情况下Samples的值为60,我们调整到15.
(2)创建Move动画
在Animation界面,点击PlayerIdle下的Create NewClip,并且重命名为PlayerMove。
->
然后,把Run的所有动画拖入Animation中,并且设置Samples的值为15。
此时在Animator下会有两个节点,然后分别右击两个节点Make Transition。
点击Animator的Parameters,添加变量isRunning。后续通过该变量实现两个动画之间的切换。
然后设置Transition的条件,Idle -> Move的isRunning为true,Move -> Idle的isRunning为false。
并且反选Has Exist Time。如下图所示:
(3)编写脚本
创建一个Squre,然后挂载Box Collider 2D的组件。
给Animator对象挂载Rigidbody 2D + Capsule Collider 2D这两个组件,Rigidbody 2d-> Constraints -> Freeze Rotation 勾选Z,否则物体移动时会滚动着移动。
然后在Assets下创建Scripts的目录,并创建AnimatorPlay的C#脚本,挂载到Animator对象下,完整的C#脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AnimatorPlay : MonoBehaviour
{Rigidbody2D rb;public float x;Animator anim;private void Awake(){rb = GetComponent<Rigidbody2D>();anim = GetComponent<Animator>();}void Start(){}void Update(){x = Input.GetAxisRaw("Horizontal");anim.SetBool("isRunning", rb.velocity.x != 0);rb.velocity = new Vector2(x, rb.velocity.y);}
}
(4)创建Blend Tree混合树
混合树:就是将多个动画混合在一起,通过阈值控制动画的变换。也需要通过变量控制别的节点transition到该Blend Tree。
首先,点中Animator这个角色,然后在Animation下Create New Clip,命名为PlayerJump如下:
然后把Jump的图片拖进去,只有一帧。
同样的方法创建PlayerFall,然后把Fall的图片拖进去,同样也只有一帧。
接着,在Animator界面中,将其他Animator动画都删除掉,只剩一个PlayerIdle,右击Create State -> From New Blend Tree。
创建的Blend Tree重命名为Jump/Fall。
双击该Blend Tree进入编辑界面
1)增加Parameters:yVelocity
2)在右边Inspector -> Parameter中选择yVelocity
3)点击"+",Add Motion Field,分别把PlayerJump和PlayerFall添加进去
4)反勾选Automate Thresholds,然后修改PlayerJump和PlayerFall的Threshold分别为-1和1
5)增加一个isGround的Bool变量,通过该变量控制PlayerIdle到Jump/Fall之间的切换,到isGround=false时变为Jump/Fall,否则变为PlayerIdle。
6)代码中控制transition的变化(isGound的判断并不是很严谨,只是演示使用)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AnimatorPlay : MonoBehaviour
{Rigidbody2D rb;public float x;Animator anim;Boolean isGround;private void Awake(){rb = GetComponent<Rigidbody2D>();anim = GetComponent<Animator>();}void Start(){}void Update(){if (Input.GetKeyDown(KeyCode.Space)){rb.velocity = new Vector2(rb.velocity.x, 5);}anim.SetFloat("yVelocity", rb.velocity.y);anim.SetBool("isGround", isGround);if(rb.velocity.y != 0){isGround = false;}else{isGround = true;}}}
(5)触发类型Trigger
该类型没有任何状态值,通过trigger可以直接触发某个动画。
演示:
1)创建PlayerKnockback的动画,并把所有的Hit动画拖入其中,设置Samples为12。
2)在Animator中,创建Any State 到PlayerKnockback的transition,条件中反勾选“Can Transition to S”(不能重新回到原来状态,否则会导致循环了),设置Transition Duration为0。
增加knockback的trigger类型变量,在transition中也指定一下该变量。
3)在Animator中,创建PlayerKnockback到PlayerIdle的transition,设置Exit Time为1(表示knockback的动画需要存在1秒钟),设置Transition Duration为0。
4)脚本中编写使用逻辑:
在Update()函数中,
if(Input.GetKeyDown(KeyCode.K)){
Knockback():
}
编写和Update平级的函数Knockback:
public void Knockback(){
anim.SetTrigger("knockback");
}
(6)Add Event
在Animation界面,可以选择一帧Add Event,如下图所示:
add Event的函数只能选择当前gameobject挂载脚本中的方法。
4、Tile Palette瓦片调色板
(1)打开Tile Palette
Window -> 2D -> Tile Palette,点击Create New Palette。
将新的Palette命名为:Tile Palette
保存到Assets的新建的Tile Palette目录下:
(2)使用Tile Palette
打开Assets -> Graphics,选择Terrain Slice -> Sprite Editor
点击后可以看到各种切片好的图片:
选择Pixels Per Unit为16,然后点击Apply。
将Terrain Slice拖入到Tile Palette 下,然后选择保存目录为新建的 Assets -> Tile Paletter -> Assets:
此时,在Tile Palette界面可以看到切片后的的图片,同时在Assets -> Tile Palette -> Assets下也可以看到一个个切片后的图片。
在Hierachry下2D Object -> Tilemap -> Rectangular,此时在Hierachry下会出现Grid -> Tilemap,重命名为Ground。
点击Brush画笔,在Scene界面左击即可添加元素。
按Shift左击可以删除元素。
(3)创建基于Tile的组件
1)添加Tilemap Collider 2D组件
ps:Tilemap:瓦片地图
此时角色可以站在我们创建的Ground之上。
但是此时存在一个问题,就是Ground上创建了很多的Collider检测器如下:
我们需要合并这些Collider以提高性能。
2)添加Composite Collider 2D组件
添加完之后会自动添加了Rigidbody 2D组件,
在Rigidbody 2D -> Body Type中选择Static,表明这个对象不需要动态计算刚体。
然后在Tilemap Collider 2D的Used By Composite打勾,此时Collider就会合并。
对比如下:
合并前:
合并后:
(4)创建Background
在Assets -> Graphics -> Background下选择图片,并设置Sprite mode为multiple, Pixels Per Unit为16.
点击Sprite Editor, Slice -> Grid By Cell Size,并设置Pixel Size为16 * 16,与之前的参数吧保持一致。
将切片后的图片拖入Tile Palette,然后根据提示保存到Assets -> Tile Palette -> Assets下。
在Hierachry的Grid下创建新的Tilemap命名为Background。
选中背景图,然后点击paint,即可在scene中画出一条。
选择Pick,然后在Scene中选中那一条,即可整条的进行draw,而不用一块一块的。
如下,整条进行draw。
画完之后,之前的ground不见了,只剩下角色和背景了。
(5)调整显示优先级
在Hierachy中点击Ground,点击Tilemap Renderer,在Sorting Layer中,点击Add Sorting Layer。
新增3个Sorting Layers如下:
Layer值越大,显示时越靠前。
然后Animator角色、Ground、Background分别选择对应的Sorting Layer,就可以正确显示如下:
5、GameManager
GameManager游戏管理器,可以做很多的事情:
- 可以用于获取玩家的参考
- 用于重生玩家
- 记录您收集的水果或硬币的分数
- 重新启动游戏、保存游戏
我们需要在Hierachy中Create Empty命名为***GameManager***,加*号是为了区分普通的对象。同时创建GameManager的脚本挂载到该对象下。
正常情况下,在一个游戏中我们只需要一个GameManager。
6、创建类秋千的SpikedBall
(1)创建秋千的支点
将Terrain的一个图标拖入scene
设置Scale大小均为0.5,并且设置Sorting Layer为Ground
在Hierarchy中重命名为Base
在这个过程中,点击下方小按钮即可让xyz的数值保持一致,修改其中一个,其他两个同步修改。
添加组件Distance Joint 2D,则会自动添加Rigidbody 2D的组件。
设置Rigidbody的Body Type为Static,表示支点不可移动。
(2)创建Empty Parent并命名为SpikedBall
这个是秋千的根元素,而秋千实际上是由多个部件组成的。
(3)插入秋千元素SpikedBall
选择Assets -> Graphics -> Traps -> Spiked Ball,设置Pixels Per Unit为16
将Spiked Ball拖入Scene中,并使其成为SpikedBall的子节点
同时新增Rigidbody 2D组件 ,设置Collision Detection和interpolate的值如下。
(4)配置支点和ball之间的铰链
点击Base,然后将Spiked Ball拖入Base的Distance Joint 2D组件的Connected Rigid Body中,使得Base和Spiked Ball形成距离关节。
然后执行程序,在Scene界面拉一下Spiked Ball,便可使其左右摆动
(5)通过脚本初始化Spiked Ball的摆动
在此之前,程序执行时需要手工拉一下ball才能使其摆动,现在我们希望通过在脚本初始化时推一下ball使其可以自行进行摆动。
public class SpikedBall : MonoBehaviour
{[SerializeField] private Rigidbody2D rb;[SerializeField] private float pushForce;void Start(){Vector2 pushVector = new Vector2(pushForce, 0);rb.AddForce(pushVector, ForceMode2D.Impulse);}}
(6)增加秋千的链子
同样在Traps -> Spiked Ball下
设置Chain的Pixels Per Unit 为16,拖入Scene中,并且再复制3份,将这4个Chain同时拖到Hierarchy的SpikedBall父节点下方。
给这四个Chain同时添加Hinge Joint 2D组件。
然后依次设置Joint 2D中Connected Rigid Body的值:
Base设置Chain
Chain设置Chain(1)
Chain(1)设置Chain(2)
Chain(2)设置Chain(3)
Chain(3)设置Spiked Ball
此时再次执行程序,可以看到Spiked Ball带动Chain一起摆动了。
(7)Joint之间的区别
可以参考:Unity 2DJoint 物理关节功能与总结_target joint 2d-CSDN博客
Distance Joint距离关节:该关节使得两物体保持一定的距离。
Hinge Joint铰链关节:允许rb对象围绕空间中的点火另一个对象上的点旋转的关节,常用于绳子模拟、开门等铰链。
相关文章:

Pixel Adventure Unity2D开发完整指南
本文参考:2-2. Get and Setup Assets_哔哩哔哩_bilibili 1、下载资源 在Asset Store中下载Pix Adventure1 2的资源: 在import的时候,不用到Scene import进来,如下图所示,Scenes目录反勾选一下。 两个资源都下载完成后…...
signed main()与int main()的区别
刷算法题时为了防止爆int ,通常会开long long #define int long long 但这样int main()会出现问题,main函数的返回值必须是signed或int,由于定义int 为long long 我们只能让返回值变为signed main() #include<bits/stdc.h> using namespace std; #define int long lo…...
【面试宝典】Java基础 这个面试题整理的不全 后期会进行补充
一、equals 和 hashcode 1、简述 hashCode() 和 equals(Object obj) 的作用及其关系 hashCode() 方法用于获取对象的哈希码,即一个整数。这个哈希码在基于哈希的集合(如HashSet、HashMap等)中用于确定对象的存储位置。 equals(Object obj)…...
获取语音文件时长
获取语音文件时长一会儿有一会儿没的,百思不得其解。 错误代码: const getAudioDuration async src > {const audio new Audio(src);const duration await new Promise(resolve > {if (audio.duration) {return resolve(parseInt(audio.duratio…...
应急响应计划:网络安全事件后的快速恢复策略
在数字化时代,网络安全威胁日益严峻,任何企业都无法完全避免遭受网络攻击或数据泄露的风险。因此,制定一套完善的应急响应计划,以便在网络安全事件发生后能够迅速、有效地进行应对和恢复,成为企业保障业务连续性、保护…...

【网络】IP和MAC地址的映射——ARP协议和ARP欺骗概述
目录 引言 ARP的工作机制 ARP欺骗 ARP欺骗的断网行为 ARP欺骗成为中间人 工具介绍 个人主页:东洛的克莱斯韦克-CSDN博客 引言 同一子网内不同主机用数据链路层的MAC地址来寻址,而不是子网内的私有IP(网络层)。数据包中的IP…...

鸿蒙(API 12 Beta3版)【音视频解封装】 文件解析封装
开发者可以调用本模块的Native API接口,完成音视频解封装,即从比特流数据中取出音频、视频等媒体帧数据。 当前支持的数据输入类型有:远程连接(http协议、HLS协议)和文件描述符(fd)。 支持的解封装格式如下: 媒体格式封装格式码…...
智能马桶盖和普通马桶盖有什么不同?
智能马桶盖与普通马桶盖之间存在显著的差异,主要体现在以下几个方面: 一、功能差异 1.清洗功能: 智能马桶盖:配备了清洗功能,包括臀洗、妇洗等,特别针对女性设计了贴心功能,如移动喷水、水流按…...

C# OnnxRuntime部署LivePortrait实现快速、高质量的人像驱动视频生成
目录 效果 说明 项目 模型信息 代码 下载 效果 LivePortrait实现快速、高质量的人像驱动视频生成 说明 官网地址:https://github.com/KwaiVGI/LivePortrait 代码实现参考:https://github.com/hpc203/liveportrait-onnxrun 模型下载:…...

Spring boot框架指南
1. Spring Boot 概述 1.1 定义与起源 Spring Boot是一种基于Spring框架的开源框架,旨在简化Spring应用程序的创建和开发过程。它通过提供一系列默认配置和自动配置功能,减少了开发者在配置上的工作量,使得快速搭建生产级别的Spring应用程序…...

数据结构--树与二叉树
数据结构分类 集合 线性结构(一对一) 树形结构(一对多) 图结构(多对多) 数据结构三要素 1、逻辑结构 2、数据的运算 3、存储结构(物理结构) 树的概念 树的分类 满二叉树和完全二叉树 二叉排序树 平衡二叉树 二叉树分类总结 二叉树的存储结构 …...
C#项目实战经验——计时方法总结
前言 我们在开发C#程序的过程中经常需要计算某段程序执行的时间,比如调用的某个算法的时间,这时候我们就需要利用计时工具,本文就是详细介绍在C#中我们常用哪些计时工具。 1、计时方法—StopWatch 在C#中我们可以利用Stopwatch这个类来实现…...
电子盖章软件哪个好|盖章软件
在选择电子盖章软件时,需要考虑多个因素,包括软件的功能、安全性、易用性、兼容性以及成本等。以下是根据当前市场情况推荐的一些优秀的电子盖章软件: e章宝: 功能丰富:e章宝是国内领先的电子盖章系统,功能…...

ThreejsWebGPU运动残影demo
功能点 实例化SkinnedMesh 修改NodeMaterial着色器 节点材质系统 shader 语言 使用uniform和attribute 中合其他几篇博客中的内容 代码仓库 克隆后需要放到three源码同级别目录下 运行 three源码部分不在git仓库中(太大了) 使用vscode的live-server启动后访问 http://127.0.0.…...

HttpSession常用方法
1.HttpSession常用方法 是在Java Servlet中用来管理会话状态的重要接口,它提供了一种在多个请求或页面之间存储用户特定信息的方式。以下是一些 HttpSession 常用的方法和用法: 获取会话对象: HttpSession session request.getSession();…...

【JavaEE初阶】文件操作和IO
目录 🌴认识文件 🚩树型结构组织和目录 🚩文件路径(Path) 🚩 文件分类 🎍Java 中操作文件 🚩 File 概述: 📌属性 📌构造方法 Ὄ…...

存储器芯片的基本原理
目录 1.存储元 1.1栅极电容 1.2双稳态触发器 2.存储单元 3.存储体 4.存储器 5.容量计算 6.寻址 1.存储元 1.1栅极电容 给MOS管一个阈值电压(5v)就能够导电,若是不给那么就是一个绝缘体不会导电。 读出二进制原理: 通常…...
前端实习手记(7):立秋快乐
这周相比上周感觉挺好的哈哈哈,可能只有自己感觉蛮好的,旁边师父忙的飞起了要,不仅赶工作还要回答我乱七八糟的问题(心疼一秒)。这周也是立秋&七夕咯,立秋快乐哇家人们(虽然还是很热嘛&…...
感恩放下,笑对人生,在人生的长河中,每一天都是独特的篇章,或顺心如意,或充满挑战
在人生的长河中,每一天都是独特的篇章,或顺心如意,或充满挑战。然而,无论今日的经历如何,我们都应怀着感恩与放下的心态,因为人生的旅程远不止这短暂的一天,明天依然充满希望,等待我们继续努力前行。 生活,犹如一场变幻莫测的舞台剧,顺心之时,我们仿佛置身于温暖的…...
URLSession之初窥门径
NSURLSession 于 2013 年随 iOS 7 的发布一起面世,苹果将其定位为 NSURLConnection 的替代者。我们使用最广泛的第三方框架如 AFNetworking 和 SDWebImage 的最新版也都已经全面切换至 NSURLSession。 NSURLSession 不仅仅指代同名类 NSURLSession,它还…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...