Unity教程(二十二)技能系统 分身技能
Unity开发2D类银河恶魔城游戏学习笔记
Unity教程(零)Unity和VS的使用相关内容
Unity教程(一)开始学习状态机
Unity教程(二)角色移动的实现
Unity教程(三)角色跳跃的实现
Unity教程(四)碰撞检测
Unity教程(五)角色冲刺的实现
Unity教程(六)角色滑墙的实现
Unity教程(七)角色蹬墙跳的实现
Unity教程(八)角色攻击的基本实现
Unity教程(九)角色攻击的改进
Unity教程(十)Tile Palette搭建平台关卡
Unity教程(十一)相机
Unity教程(十二)视差背景
Unity教程(十三)敌人状态机
Unity教程(十四)敌人空闲和移动的实现
Unity教程(十五)敌人战斗状态的实现
Unity教程(十六)敌人攻击状态的实现
Unity教程(十七)敌人战斗状态的完善
Unity教程(十八)战斗系统 攻击逻辑
Unity教程(十九)战斗系统 受击反馈
Unity教程(二十)战斗系统 角色反击
Unity教程(二十一)技能系统 基础部分
Unity教程(二十二)技能系统 分身技能
Unity教程(二十三)技能系统 投掷技能
如果你更习惯用知乎
Unity开发2D类银河恶魔城游戏学习笔记目录
文章目录
- Unity开发2D类银河恶魔城游戏学习笔记
- 前言
- 一、概述
- 二、预制件(Prefab)
- (1)预制件介绍
- (2)创建分身预制件
- 三、分身技能的实现
- (1)分身技能的创建
- (2)分身技能的实现
- (3)分身的消失与销毁
- (4)补充:将预制件Clone实例化到当前位置
- 四、分身攻击的实现
- (1)攻击动画
- (2)分身攻击的实现
- (3)分身攻击方向
- 总结 完整代码
- PlayerDashState.cs
- Clone_Skill.cs
- Clone_Skill_Controller.cs
- SkillManager.cs
- Player.cs
前言
本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记,如有错误,欢迎指正。
本节实现角色分身技能。
Udemy课程地址
对应视频:
Clone Creating Ability
Clone’s Attack
一、概述
本节实现分身技能。
实现解锁技能后,在角色冲刺时产生一个分身,分身会攻击距离最近的一个敌人。
二、预制件(Prefab)
(1)预制件介绍
Unity的预制件相当于创建一个模板,使得游戏对象作为可重用资源。可以用这个模板在场景中创建新的预制件实例。
详细内容可见Unity官方手册预制件
首先是预制件的创建。
预制件的创建很简单,将一个游戏对象从 Hierarchy 窗口拖入 Project 窗口就可以了。
预制件的实例化。
最简单的是将预制件资源从 Project 视图拖动到 Hierarchy 或 Scene 视图,创建实例。
也可通过脚本进行实例化。使用Object的Instantiate函数。
Object Instantiate (Object original);Object Instantiate (Object original, Transform parent);Object Instantiate (Object original, Transform parent, bool instantiateInWorldSpace);Object Instantiate (Object original, Vector3 position, Quaternion rotation);Object Instantiate (Object original, Vector3 position, Quaternion rotation, Transform parent);
参数含义如下表:
参数 | 含义 |
---|---|
original | 要复制的现有对象(如预制件) |
position | 新对象的位置 |
rotation | 新对象的方向 |
parent | 将指定给新对象的父对象 |
instantiateInWorldSpace | 分配父对象时,传递 true 可直接在世界空间中定位新对象。 传递 false 可相对于其新父项来设置对象的位置。 |
预制件的编辑。 可以在预制件模式下编辑预制件。这种情况可以单独或在上下文中编辑预制件资源。
也可以在实例中编辑后覆盖预制体。使用Overrides应用和还原覆盖。
(2)创建分身预制件
将玩家精灵表第一帧拖入层次面板中并重命名为Clone。
创建动画控制器Clone_AC
将Clone_AC挂载到Clone下面
这时我们发现Clone的图像被遮挡了。
调整SpriteRenderer中的层次顺序,使Clone位于敌人之前,玩家之后。
给Clone添加动画,这里我们不需要重新建立动画,只需要把原来Player的动画复用。
打开Clone的Aniamtor面板,将PlayerIdle拖入作为默认状态,再拖入PlayerAttack1、PlayerAttack2、PlayerAttack3。
创建Prefabs文件夹存放预制件。
将层次面板中的Clone拖入文件夹,预制件创建完成。
把层次面板中的Clone删除,后续我们用到它时会在脚本中创建。
三、分身技能的实现
分身技能Clone_Skill继承自Skill基类。我们要实现按下冲刺键后,在玩家冲刺的位置创建一个分身,因此我们需要在PlayerDashState开始时传入Player的位置创建分身。
实现时还要创建一个分身技能的控制器Clone_Skill_Controller,将它挂载到Clone预制件下,控制分身的位置。这里让人容易疑惑,为什么要大费周章再创建一个控制器脚本。个人理解,更多是因为马上要实现的分身攻击,攻击时需要触发动画事件,因此必须有个脚本挂在Clone预制体下面。这里就把控制分身位置的功能也写进去了。
此外,还可在实例化时就指定分身位置,这种形式也会在下面写一下。
(1)分身技能的创建
在Scripts文件夹中创建Skills文件夹存放技能相关脚本。
创建分身技能脚本Clone_Skill,它继承自Skill基类,将它挂到技能管理器下。
在技能管理器脚本中创建分身技能并赋值。
public Clone_Skill clone { get; private set; }private void Start(){dash = GetComponent<Dash_Skill>();clone = GetComponent<Clone_Skill>();}
(2)分身技能的实现
创建分身技能控制器Clone_Skill_Controller,创建函数SetupClone设置分身信息。
双击预制件Clone,在面板中点击Add Component添加组件。
注意:脚本是添加在预制件上的。
在Clone_Skill_Controller中添加设置分身信息的函数。
//Clone_Skill_Controller:分身技能控制器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Clone_Skill_Controller : MonoBehaviour
{//设置分身信息public void SetupClone(Transform _newTransform){transform.position = _newTransform.position;}
}
在Clone_Skill脚本中添加实例化预制体的函数,并调用SetupClone设置分身信息。
//Clone_Skill:分身技能
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Clone_Skill : Skill
{[SerializeField] private GameObject clonePerfab;public void CreateClone(Transform _clonePosition){GameObject newClone = Instantiate(clonePerfab);newClone.GetComponent<Clone_Skill_Controller>().SetupClone(_clonePosition);}
}
为预制体赋值
在Player中创建SkillManager方便管理。
public SkillManager skill;// 设置初始状态protected override void Start(){base.Start();skill = SkillManager.instance;StateMachine.Initialize(idleState);}
接着在PlayerDashState的中调用CreateClone,使得冲刺后在玩家位置创建一个分身。
//进入状态public override void Enter(){base.Enter();player.skill.clone.CreateClone(player.transform);//设置冲刺持续时间stateTimer = player.dashDuration;}
效果如下:
基本功能已经实现,但有个很明显的问题,创建的分身没有回收。
(3)分身的消失与销毁
此技能需要让分身持续一段时间后逐渐消失,可以使clone预制件的图像随时间透明度逐渐降低实现,最后透明度降到0时销毁分身。这需要用到计时器,而且要设置分身持续的时长和消失的速度。
我们把经常需要变动修改的变量放在CloneSkill中方便管理,这里将分身持续时长cloneDuration放在里面。
public class Clone_Skill : Skill
{[Header("Clone Info")][SerializeField] private GameObject clonePerfab;[SerializeField] private float cloneDuration;public void CreateClone(Transform _clonePosition){GameObject newClone = Instantiate(clonePerfab);newClone.GetComponent<Clone_Skill_Controller>().SetupClone(_clonePosition, cloneDuration);}
}
在Clone_Skill_Controller中设置计时器,实现图像透明度递减,并在透明度为0时销毁对象。
public class Clone_Skill_Controller : MonoBehaviour
{private SpriteRenderer sr;[SerializeField] private float colorLosingSpeed;private float cloneTimer;private void Awake(){sr = GetComponent<SpriteRenderer>();}private void Update(){cloneTimer -= Time.deltaTime;if(cloneTimer < 0){sr.color = new Color(1, 1, 1, sr.color.a - Time.deltaTime * colorLosingSpeed);if (sr.color.a <= 0)Destroy(gameObject);}}//设置分身信息public void SetupClone(Transform _newTransform, float _cloneDuration){transform.position = _newTransform.position;cloneTimer = _cloneDuration;}
}
设置合适的技能持续时间和消失速度
效果如下:
(4)补充:将预制件Clone实例化到当前位置
只需在实例化时直接传入位置参数即可,其他函数要随着做一些更改。
在Clone_Skill中
public void CreateClone(Transform _clonePosition){GameObject newClone = Instantiate(clonePerfab,_clonePosition);newClone.GetComponent<Clone_Skill_Controller>().SetupClone(cloneDuration);}
在Clone_Skill_Controller中
//设置分身信息public void SetupClone(float _cloneDuration){cloneTimer = _cloneDuration;}
四、分身攻击的实现
(1)攻击动画
进入预制件Clone的编辑,在Animator中创建空状态用于空闲和攻击状态过渡。创建Int型变量AttackNumber用于确定攻击段数。
连接playerIdle与Empty状态,当AttackNumber>0时,进入Empty。
PlayerIdle->Empty, 加条件变量并更改设置
分别连接Empty和三个攻击状态,在AttackNumber等于1时进入playerAttack1,同理等于2、3时分别进入其他两个状态
(2)分身攻击的实现
在技能树中分身攻击技能解锁后才可使用,这里我们先实现功能部分,所以先在Clone_Skill中添加一个变量canAttack用于测试。
public class Clone_Skill : Skill
{[Header("Clone Info")][SerializeField] private GameObject clonePerfab;[SerializeField] private float cloneDuration;[Space][SerializeField] private bool canAttack;public void CreateClone(Transform _clonePosition){GameObject newClone = Instantiate(clonePerfab);newClone.GetComponent<Clone_Skill_Controller>().SetupClone(_clonePosition, cloneDuration,canAttack);}
}
当解锁分身攻击技能时,在Clone_Skill_Controller中实现分身攻击的设置。
设置Animator中的条件变量AttackNumber为1-3中随机一个数,播放相应攻击动画。
注意:在Unity中Random.Range(a, b) 生成的是 [ a, b ) 区间内的整数。
private Animator anim;private void Awake(){sr = GetComponent<SpriteRenderer>();anim = GetComponent<Animator>();}//设置分身信息public void SetupClone(Transform _newTransform, float _cloneDuration, bool _canAttack){if (_canAttack)anim.SetInteger("AttackNumber", Random.Range(1, 4));transform.position = _newTransform.position;cloneTimer = _cloneDuration;}
效果如下:
现在分身攻击是连续不断地没有结束攻击的部分,我们可以复用攻击动画以前的事件实现。
参照PlayerAnimationTriggers里函数的写法,在Clone_Skill_Controller中添加AnimationTrigger和AttackTrigger两个函数,分别用于结束攻击和触发攻击效果。
AnimatonTrigger会将计时器设置为小于0的数,相当于分身技能持续时间直接结束,开始逐渐消失。
AttackTrigger与玩家攻击的实现逻辑一样,检查攻击范围内的敌人,造成伤害效果。
添加如下代码:
[SerializeField] private Transform attackCheck;[SerializeField] private float attackCheckRadius = 0.8f;private void AnimationTrigger(){cloneTimer = -0.1f;}private void AttackTrigger(){Collider2D[] colliders = Physics2D.OverlapCircleAll(attackCheck.position, attackCheckRadius);foreach (var hit in colliders){if (hit.GetComponent<Enemy>() != null)hit.GetComponent<Enemy>().Damage();}}
在Clone下创建一个空物体并重命名为attackCheck,将它移动到分身前方合适的位置。然后用它为变量attackCheck赋值。
进行修改时可以在预制体的编辑里,也可以将预制体拖到场景中修改完再覆盖原来的预制体。
做完这些你会发现分身可以攻击敌人了,但攻击还是接连不断。
因为这次在Animator中没有将PlayerAttack连到Exit状态,没有退出,所以动画会循环播放。
将三个攻击动画的lLoop Time勾掉就可以了。
现在每次冲刺产生分身就是正常攻击一次了。
(3)分身攻击方向
最后一个需要解决的问题是分身面向现在是固定朝右的,我们需要再添加一个让分身朝向最近敌人攻击的功能。
在分身一定范围内检测敌人,比较后选取离分身最近的一个。如果它在分身左侧,则翻转分身让它面向左侧。
private Transform closestEnemy;//设置分身信息public void SetupClone(Transform _newTransform, float _cloneDuration, bool _canAttack){if (_canAttack)anim.SetInteger("AttackNumber", Random.Range(1, 4));transform.position = _newTransform.position;cloneTimer = _cloneDuration;FaceClosestTarget();}private void FaceClosestTarget(){Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 25);float closestDistace = Mathf.Infinity;foreach(var hit in colliders){if (hit.GetComponent<Enemy>() != null){float distanceToEnemy = Vector2.Distance(transform.position, hit.transform.position);if (distanceToEnemy < closestDistace){closestDistace = distanceToEnemy;closestEnemy = hit.transform;}}}if(closestEnemy != null){if (closestEnemy.position.x < transform.position.x)transform.Rotate(0, 180, 0);}}
效果如下:
总结 完整代码
PlayerDashState.cs
添加分身的创建。
//PlayerDashState:冲刺状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerDashState : PlayerState
{//构造函数public PlayerDashState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName) : base(_stateMachine, _player, _animBoolName){}//进入状态public override void Enter(){base.Enter();player.skill.clone.CreateClone(player.transform);//设置冲刺持续时间stateTimer = player.dashDuration;}//退出状态public override void Exit(){base.Exit();}//更新public override void Update(){base.Update();//切换滑墙状态if(!player.isGroundDetected() && player.isWallDetected()) stateMachine.ChangeState(player.wallSlideState);//设置冲刺速度player.SetVelocity(player.dashDir * player.dashSpeed, 0);//切换到空闲状态if (stateTimer < 0)stateMachine.ChangeState(player.idleState);}
}
Clone_Skill.cs
创建分身,添加经常需要在面板上更改的相关变量。
//Clone_Skill:分身技能
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Clone_Skill : Skill
{[Header("Clone Info")][SerializeField] private GameObject clonePerfab;[SerializeField] private float cloneDuration;[Space][SerializeField] private bool canAttack;public void CreateClone(Transform _clonePosition){GameObject newClone = Instantiate(clonePerfab);newClone.GetComponent<Clone_Skill_Controller>().SetupClone(_clonePosition, cloneDuration,canAttack);}
}
Clone_Skill_Controller.cs
设置分身信息,实现分身逐渐消失,实现分身攻击,将分身改为面向最近的敌人。
//Clone_Skill_Controller:分身技能控制器
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;public class Clone_Skill_Controller : MonoBehaviour
{private SpriteRenderer sr;private Animator anim;[SerializeField] private float colorLosingSpeed;private float cloneTimer;[SerializeField] private Transform attackCheck;[SerializeField] private float attackCheckRadius = 0.8f;private Transform closestEnemy;private void Awake(){sr = GetComponent<SpriteRenderer>();anim = GetComponent<Animator>();}private void Update(){cloneTimer -= Time.deltaTime;if(cloneTimer < 0){sr.color = new Color(1, 1, 1, sr.color.a - Time.deltaTime * colorLosingSpeed);if (sr.color.a <= 0)Destroy(gameObject);}}//设置分身信息public void SetupClone(Transform _newTransform, float _cloneDuration, bool _canAttack){if (_canAttack)anim.SetInteger("AttackNumber", Random.Range(1, 4));transform.position = _newTransform.position;cloneTimer = _cloneDuration;FaceClosestTarget();}private void AnimationTrigger(){cloneTimer = -0.1f;}private void AttackTrigger(){Collider2D[] colliders = Physics2D.OverlapCircleAll(attackCheck.position, attackCheckRadius);foreach (var hit in colliders){if (hit.GetComponent<Enemy>() != null)hit.GetComponent<Enemy>().Damage();}}private void FaceClosestTarget(){Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 25);float closestDistance = Mathf.Infinity;foreach(var hit in colliders){if (hit.GetComponent<Enemy>() != null){float distanceToEnemy = Vector2.Distance(transform.position, hit.transform.position);if (distanceToEnemy < closestDistance){closestDistance = distanceToEnemy;closestEnemy = hit.transform;}}}if(closestEnemy != null){if (closestEnemy.position.x < transform.position.x)transform.Rotate(0, 180, 0);}}
}
SkillManager.cs
创建分身技能。
//SkillManager:玩家管理器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkillManager : MonoBehaviour
{public static SkillManager instance;public Dash_Skill dash { get; private set; }public Clone_Skill clone { get; private set; }private void Awake(){if (instance != null && instance != this){Destroy(this.gameObject);}else{instance = this;}}private void Start(){dash = GetComponent<Dash_Skill>();clone = GetComponent<Clone_Skill>();}
}
Player.cs
创建并初始化技能管理器。
//Player:玩家
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : Entity
{[Header("Attack details")]public Vector2[] attackMovement;public float counterAttackDuration = 0.2f;public bool isBusy { get; private set; }[Header("Move Info")]public float moveSpeed = 8f;public float jumpForce = 12f;[Header("Dash Info")]public float dashSpeed=25f;public float dashDuration=0.2f;public float dashDir { get; private set; }public SkillManager skill;#region 状态public PlayerStateMachine StateMachine { get; private set; }public PlayerIdleState idleState { get; private set; }public PlayerMoveState moveState { get; private set; }public PlayerJumpState jumpState { get; private set; }public PlayerAirState airState { get; private set; }public PlayerDashState dashState { get; private set; }public PlayerWallSlideState wallSlideState { get; private set; }public PlayerWallJumpState wallJumpState { get; private set; }public PlayerPrimaryAttackState primaryAttack { get; private set; }public PlayerCounterAttackState counterAttack { get; private set; }#endregion//创建对象protected override void Awake(){base.Awake();StateMachine = new PlayerStateMachine();idleState = new PlayerIdleState(StateMachine, this, "Idle");moveState = new PlayerMoveState(StateMachine, this, "Move");jumpState = new PlayerJumpState(StateMachine, this, "Jump");airState = new PlayerAirState(StateMachine, this, "Jump");dashState = new PlayerDashState(StateMachine, this, "Dash");wallSlideState = new PlayerWallSlideState(StateMachine, this, "WallSlide");wallJumpState = new PlayerWallJumpState(StateMachine, this, "Jump");primaryAttack = new PlayerPrimaryAttackState(StateMachine, this, "Attack");counterAttack = new PlayerCounterAttackState(StateMachine, this, "CounterAttack");}// 设置初始状态protected override void Start(){base.Start();skill = SkillManager.instance;StateMachine.Initialize(idleState);}// 更新protected override void Update(){base.Update();StateMachine.currentState.Update();CheckForDashInput();}public IEnumerator BusyFor(float _seconds){isBusy = true;yield return new WaitForSeconds(_seconds);isBusy = false;}//设置触发器public void AnimationTrigger() => StateMachine.currentState.AnimationFinishTrigger();//检查冲刺输入public void CheckForDashInput(){if (Input.GetKeyDown(KeyCode.LeftShift) && SkillManager.instance.dash.CanUseSkill()){dashDir = Input.GetAxisRaw("Horizontal");if (dashDir == 0)dashDir = facingDir;StateMachine.ChangeState(dashState);}}}
相关文章:
Unity教程(二十二)技能系统 分身技能
Unity开发2D类银河恶魔城游戏学习笔记 Unity教程(零)Unity和VS的使用相关内容 Unity教程(一)开始学习状态机 Unity教程(二)角色移动的实现 Unity教程(三)角色跳跃的实现 Unity教程&…...
RTSPtoWeb, 一个将rtsp转换成webrtc的开源项目
RTSPtoWeb是一个开源项目,旨在将RTSP流转换为可在现代web浏览器中消费的格式,如Media Source Extensions (MSE)、WebRtc或HLS。该项目完全使用golang编写,不依赖于ffmpeg或gstreamer,确保了高效的性能和轻量…...
AIAgent有哪些不错的开源平台
AIAgent领域有许多优秀的开源平台和框架,以下是一些值得推荐的开源平台: AutoGPT AutoGPT 是一个基于 OpenAI 的 GPT-4 和 GPT-3.5 大型语言模型的开源框架,能够根据用户给定的目标自动生成所需提示,并利用多种工具 API 执行多步骤…...
Java---JavaSpringMVC解析(1)
Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring MVC" 1.MVC MVC是Model View Controller的缩写&#…...
Vector 的模拟实现:从基础到高级
文章目录 1. 引言2. vector的核心设计3. vector的常用接口介绍3.1 构造函数和析构函数3.1.1 默认构造函数3.1.2 带初始容量的构造函数3.1.3 析构函数 3.2 拷贝构造函数和拷贝赋值运算符3.2.1 拷贝构造函数3.2.2 拷贝赋值运算符 3.5 数组长度调整和动态扩容3.5.1 调整大小&#…...
【大模型科普】大模型:人工智能的前沿(一文读懂大模型)
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能(AI)通过算法模拟人类智能,利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络(如ChatGPT&…...
[漏洞修复]用yum update修openssh漏洞
[漏洞修复]用yum update修openssh漏洞 1. 需求2. 更新Yum仓库2.1 生成本地仓库2.2 生成内网仓库2.3 将Openssh的包更新到仓库 3. 客户端升级3.1 客户端repo文件配置3.2 升级Openssh3.3 升级后的确认 1. 需求 最近经常有朋友问Openssh 漏洞修复的问题,我也在自己的gitee仓库里更…...
[RH342]iscsi配置与排错
[RH342]iscsi配置与排错 1. 服务端配置1.1 安装targetcli1.2 准备磁盘1.3 服务端配置1.4 防火墙配置 2. 客户端配置2.1 安装客户端软件2.2 配置客户端2.3 连接登录服务端2.4 挂载使用 3. 安全验证扩展3.1 服务端3.2 客户端 4. 常见的排错点4.1 服务端常见错误4.2 客户端常见错误…...
Nginx 代理访问一个 Web 界面时缺少内容
1. 资源路径问题 Web 页面中的静态资源(如图片、CSS、JavaScript 文件)可能使用了相对路径或绝对路径,而这些路径在代理后无法正确加载。 解决方法: 检查资源路径:打开浏览器的开发者工具(按 F12…...
HOVER:人形机器人的多功能神经网络全身控制器
编辑:陈萍萍的公主一点人工一点智能 HOVER:人形机器人的多功能神经网络全身控制器HOVER通过策略蒸馏和统一命令空间设计,为人形机器人提供了通用、高效的全身控制框架。https://mp.weixin.qq.com/s/R1cw47I4BOi2UfF_m-KzWg 01 介绍 1.1 摘…...
SEO新手基础优化三步法
内容概要 在网站优化的初始阶段,新手常因缺乏系统性认知而陷入技术细节的误区。本文以“三步法”为核心框架,系统梳理从关键词定位到内容布局、再到外链构建的完整优化链路。通过拆解搜索引擎工作原理,重点阐明基础操作中容易被忽视的底层逻…...
遨游科普:三防平板是哪三防?有哪些应用场景?
在工业智能化与数字化转型的浪潮中,电子设备的耐用性和环境适应性成为关键需求。普通消费级平板电脑虽然功能强大,但在极端环境下往往“水土不服”。而三防平板凭借其独特的防护性能,正逐步成为“危、急、特”场景的核心工具。 AORO P300 Ult…...
Etcd 服务搭建
💢欢迎来到张胤尘的开源技术站 💥开源如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Etcd 服务搭建预编译的二进制文件安装下载 etcd 的…...
C++《红黑树》
在之前的篇章当中我们已经了解了基于二叉搜索树的AVL树,那么接下来在本篇当中将继续来学习另一种基于二叉搜索树的树状结构——红黑树,在此和之前学习AVL树类似还是通过先了解红黑树是什么以及红黑树的结构特点,接下来在试着实现红黑树的结构…...
Axios 请求取消:从原理到实践
Axios 请求取消:从原理到实践 在现代前端开发中,网络请求是不可或缺的一部分。Axios 是一个基于 Promise 的 HTTP 客户端,广泛应用于浏览器和 Node.js 环境中。然而,在某些场景下,我们可能需要取消正在进行的请求&…...
【css酷炫效果】纯CSS实现照片堆叠效果
【css酷炫效果】纯CSS实现照片堆叠效果 缘创作背景html结构css样式完整代码基础版进阶版(增加鼠标悬停查看) 效果图 想直接拿走的老板,链接放在这里:https://download.csdn.net/download/u011561335/90492022 缘 创作随缘,不定时更新。 创…...
论文精度:Transformers without Normalization
前言 论文题目:Transformers without Normalization 作者:Jiachen Zhu 1,2 , Xinlei Chen 1 , Kaiming He 3 , Yann LeCun 1,2 , Zhuang Liu 1,4,† 论文地址:https://arxiv.org/pdf/2503.10282 摘要 这篇论文探讨了现代神经网络中广泛使用的归一化层是否是必不可少的。…...
基于香橙派 KunpengPro学习CANN(3)——pytorch 模型迁移
通用模型迁移适配可以分为四个阶段:迁移分析、迁移适配、精度调试与性能调优。 迁移分析 迁移支持度分析: 准备NPU环境,获取模型的源码、权重和数据集等文件;使用迁移分析工具采集目标网络中的模型/算子清单,识别第三方…...
微软远程桌面即将下架?Splashtop:更稳、更快、更安全的 RDP 替代方案
近日,Windows 官方博客宣布:将于2025年5月27日起,在 Windows 10 和 Windows 11 应用商店中下架“Microsoft 远程桌面”应用,建议用户迁移至新的 Windows App。这一变动引发了广大用户对远程访问解决方案的关注。作为全球领先的远程…...
【Python】Python与算法有应用关系吗?
李升伟 整理 是的,Python与算法有着密切的应用关系。Python作为一种高级编程语言,因其简洁的语法和强大的库支持,被广泛应用于算法设计、实现和应用中。以下是Python与算法之间的一些主要应用关系: 1. 算法学习与教学࿱…...
js,html,css,vuejs手搓级联单选
<!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>级联选择器</title><script src"h…...
将Django连接到mysql
将Django连接到mysql 文章目录 将Django连接到mysql一.按照我的文章 在Django模型中的Mysql安装 此篇 的步骤完成mysql的基础配置二.Django配置 一.按照我的文章 ‘在Django模型中的Mysql安装’ 此篇 的步骤完成mysql的基础配置 基础配置具体内容 1.打开PowerShell 安装mysql的…...
每天五分钟深度学习框架pytorch:基于pytorch搭建循环神经网络RNN
本文重点 我们前面介绍了循环神经网络RNN,主要分析了它的维度信息,其实它的维度信息是最重要的,一旦我们把维度弄清楚了,一起就很简单了,本文我们正式的来学习一下,如何使用pytorch搭建循环神经网络RNN。 RNN的搭建 在pytorch中我们使用nn.RNN()就可以创建出RNN神经网络…...
【力扣刷题实战】无重复的最长字串
大家好,我是小卡皮巴拉 文章目录 目录 力扣题目: 无重复的最长字串 题目描述 解题思路 问题理解 算法选择 具体思路 解题要点 完整代码(C) 兄弟们共勉 !!! 每篇前言 博客主页&#x…...
vulhub/joker 靶机----练习攻略
1. 靶机下载地址 https://download.vulnhub.com/ha/joker.zip 下载下来是ova文件,直接双击,在VMware打开,选择保存位置,点击导入。 2. 设置网卡模式为NAT,打开靶机 3.老规矩,打开kali,扫同C…...
Nuxt2 vue 给特定的页面 body 设置 background 不影响其他页面
首先认识一下 BODY_ATTRS 他可以在页面单独设置 head () {return {bodyAttrs: {form: form-body}};},设置完效果是只有这个页面会加上 接下来在APP.vue中添加样式...
【Go】运算符笔记
基本数学运算 Go 语言支持常见的 算术运算符,用于执行数学计算。 运算符说明加法-减法*乘法/除法%取余自增--自减 整数运算只能得到整数部分 package mainimport ("fmt""math" )func main() {go_math() }func go_math() {x, y : 8, 5fmt.Pr…...
常见的前端安全问题
前端安全是 Web 开发中至关重要的一环,以下是常见的前端安全问题及对应的防御措施: 1. XSS(跨站脚本攻击) 攻击原理 攻击者向页面注入恶意脚本(如 JavaScript),在用户浏览器中执行,…...
基于Spring Boot的项目申报系统的设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
SPI驱动(九) -- SPI_Master驱动程序
文章目录 参考资料:一、SPI传输概述二、SPI传输的两种方法2.1 旧方法2.2 新方法 参考资料: 参考资料: 参考内核源码: drivers\spi\spi.c 一、SPI传输概述 SPI控制器的作用是发起与它下面挂接的SPI设备之间的数据传输,那么控制…...
Transformer网络发展概述2025.3.18
一.Transformer概述 1.1 定义与原理 Transformer是一种基于自注意力机制的深度学习模型,在处理序列数据时表现卓越。其核心原理包括: 自注意力机制 :允许模型同时考虑输入序列中的所有位置,捕捉语义关系多头注意力 :…...
3.4 二分查找专题:LeetCode 69. x 的平方根
1. 题目链接 LeetCode 69. x 的平方根 2. 题目描述 给定一个非负整数 x,计算并返回 x 的平方根的整数部分(向下取整)。 示例: 输入:x 4 → 输出:2输入:x 8 → 输出:2࿰…...
机器人曲面跟踪Surface-Tracking
定义 机器人曲面跟踪(Surface-Tracking)是指机器人通过实时感知工件曲面的三维形貌,动态调整运动轨迹和位姿,以精确跟随曲面进行加工(如打磨、抛光、喷涂等)的技术。 力 - 位姿协同控制 力控模式ÿ…...
opencv中stitch图像融合
openv版本: opencv249 vs :2010 qt : 4.85 #include "quanjing.h"#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <open…...
深入解析ES6+新语法:复杂的迭代器与生成器
一、迭代器(Iterator):数据遍历的统一协议 1. 迭代器协议的本质 **迭代器协议(Iterator Protocol)** 是一种标准化的数据访问接口,它要求对象实现一个 next() 方法,每次调用返回包含 { valu…...
【C语言】自定义类型:结构体
一、结构体类型的声明 我们前面学习操作符的时候已经接触过结构体了,下面我们回顾一下结构体的基本内容。 创建结构体的语法如上所示: struct是创建结构体的关键字,然后tag就是我们结构体的名称,member-list是结构体的成员列表&…...
微服务即时通信系统---(五)框架学习
目录 ODB 介绍 安装 build2安装 odb-compiler安装 ODB运行时库安装 mysql和客户端开发包安装 boost profile库安装 总体打包安装 总体卸载 总体升级 头文件包含和编译时指明库 ODB常见操作介绍 类型映射 ODB编程 类与接口介绍 mysql连接池对象类 mysql客户端…...
蓝桥杯练习day1:自除数
前言 自除数 是指可以被它包含的每一位数整除的数。 例如,128 是一个 自除数 ,因为 128 % 1 0,128 % 2 0,128 % 8 0。 自除数 不允许包含 0 。 给定两个整数 left 和 right ,返回一个列表,列表的元素…...
0基础 | 上下拉电阻典型应用场景
三极管典型运用: 上拉电阻 下拉电阻 限流电阻 此处开关为三极管 左侧电阻:驱动电阻【限流电阻】 (控制mos管) 下面电阻:下拉电阻【关断电阻】 %%作用1: (因为IO口输出信号分为低电平&…...
MySQL数据高效同步到Elasticsearch的四大方案
目录 引言 一、为什么需要MySQL到ES的同步? 二、四大同步方案对比 三、方案详解与代码实战 1. 应用层双写:简单但强耦合 2. 定时任务同步:可控的准实时 3. Logstash JDBC:离线迁移利器 4. Binlog监听:生产级实…...
Docker详解
云是一种服务理念。在云里docker是业务的最小载体 doker是管理容器的引擎,为应用打包、部署平台、而非单纯的虚拟化技术 1.轻量级虚拟化 2.一致性 4.高效的资源利用 5.易于部署和扩展 docker和虚拟机的区别: 虚拟机:真机需要一个操作系…...
清晰易懂的Maven安装教程(含自定义依赖包位置)
初学者也能看懂的 Maven 安装教程(含自定义依赖包位置) Maven 是一个强大的项目管理和构建工具,广泛用于 Java 项目的依赖管理和构建自动化。本教程将手把手教你如何在 Windows 系统上安装 Maven,并配置环境变量,同时…...
王道数据结构6.3
顶点x的第一个邻接点以及下一个邻接点 int first_neighbor(Algraph G, int x){if(G.vertices[x].firstarc! nullptr){return G.vertices[x].firstarc->adjvex;}else return -1; }int next_neighbor(Algraph G,int x,int y){ArcNode *pG.vertices[x].firstarc;while(p! null…...
【Linux操作系统——学习笔记二】Linux简单导航命令操作
一、前言 学习Linux,本质上是学习在命令行下熟练使用Linux的各类命令。 命令行:是一种通过输入命令和参数与计算机系统进行交互的方式,可以使用各种字符化命令对系统发出操作指令,打开Linux终端,进入命令行界面。 …...
贪心算法——c#
贪心算法通俗解释 贪心算法是一种"每一步都选择当前最优解"的算法策略。它不关心全局是否最优,而是通过局部最优的累积来逼近最终解。优点是简单高效,缺点是可能无法得到全局最优解。 一句话秒懂 自动售货机找零钱:用最少数量的…...
SPI 总线协议
1、协议介绍 SPI,是英语 Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接口。是 Motorola 首先在其 MC68HCXX 系列处理器上定义的。 SPI,是一种高速的,全双工,同步的通信总线。主节点或子节点的数据在…...
单片机开发资源分析的实战——以STM32G431RBT6为例子的单片机资源分析
目录 第一点:为什么叫STM32G431RBT6 从资源手册拿到我们的对STM32G431RBT6的资源描述 第二件事情,关心我们的GPIO引脚输出 第三件事情:去找对应外设的说明部分 第一点:为什么叫STM32G431RBT6 对于命名规则不太熟悉的朋友看这里…...
物联网(IoT)架构中,平台层的应用与技术
在物联网(IoT)架构中,平台层是连接物理设备(感知层)和应用服务(应用层)的核心部分。它负责数据的采集、处理、存储、分析以及设备管理等功能,是物联网系统的“大脑”。以下是平台层的主要功能及其技术实现手段: 平台层的主要功能 设备管理: 功能:管理物联网设备的注…...
大语言模型的压缩技术
尽管人们对越来越大的语言模型一直很感兴趣,但MistralAI 向我们表明,规模只是相对而言的,而对边缘计算日益增长的兴趣促使我们使用小型语言获得不错的结果。压缩技术提供了一种替代方法。在本文中,我将解释这些技术,并…...
JVM 2015/3/15
定义:Java Virtual Machine -java程序的运行环境(java二进制字节码的运行环境) 好处: 一次编写,到处运行 自动内存管理,垃圾回收 数组下标越界检测 多态 比较:jvm/jre/jdk 常见的JVM&…...