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

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开发2D类银河恶魔城游戏学习笔记目录


文章目录

  • Unity开发2D类银河恶魔城游戏学习笔记
  • 前言
  • 一、概述
  • 二、创建骷髅攻击动画
  • 三、骷髅攻击的实现
    • (1)整理代码
    • (2)创建SkeletonAttackState
    • (3)触发器的实现
    • (4)攻击的实现
  • 四、骷髅攻击的冷却
  • 总结 完整代码
    • EnemyState.cs
    • Enemy.cs
    • Enemy_SkeletonAnimationTriggers.cs
    • Enemy_Skeleton.cs
    • SkeletonBattleState.cs
    • SkeletonAttackState.cs
    • SkeletonMoveState.cs


前言

本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记,如有错误,欢迎指正。

本节实现敌人的攻击状态。

Udemy课程地址

对应视频:
Enemy’s Attack State


一、概述

在骷髅进入战斗状态并走到距离玩家很近的距离时,就要进入攻击状态攻击玩家。本节中我们就实现骷髅的攻击状态。
这一部分状态转换条件较多,如下图:
在这里插入图片描述
在这里插入图片描述

二、创建骷髅攻击动画

我们创建动画skeletonAttack
层次面板中选中Enemy_skeleton下的Animator,在Animation面板中创建动画
将精灵表SkeletonAttack内容全部拖入,采样率改为15
动画创建的更详细讲解见Unity教程(零)Unity和VS的使用相关内容
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

连接状态机,并添加过渡条件Attack,并修改过渡设置
添加bool型条件变量Attack,并连接过渡
在这里插入图片描述
Entry->skeletonAttack的过渡,加条件变量
在这里插入图片描述

skeletonAttack->Exit的过渡,加条件变量,并更改设置
在这里插入图片描述

三、骷髅攻击的实现

(1)整理代码

上一节我们用到了很多次骷髅的速度,所以我们在敌人状态中创建刚体,使代码更简洁。

protected Rigidbody2D rb;public virtual void Enter(){rb = enemyBase.rb;triggerCalled = false;enemyBase.anim.SetBool(animBoolName, true);}

SkeletonBattleState状态Update函数中改为

    public override void Update(){base.Update();if (enemy.IsPlayerDetected()){if (enemy.IsPlayerDetected().distance < enemy.attackDistance){stateMachine.ChangeState(enemy.attackState);}}if(player.position.x > enemy.transform.position.x)moveDir = 1;else if(player.position.x < enemy.transform.position.x)moveDir = -1;enemy.SetVelocity(enemy.moveSpeed * moveDir, rb.velocity.y);}

SkeletonMoveState状态Update函数中改为

    public override void Update(){base.Update();enemy.SetVelocity(enemy.moveSpeed*enemy.facingDir,rb.velocity.y);if(!enemy.isGroundDetected() || enemy.isWallDetected()){enemy.Flip();stateMachine.ChangeState(enemy.idleState);}}

(2)创建SkeletonAttackState

首先创建SkeletonAttackState,它继承自EnemyState,通过菜单生成构造函数和重写。
在这里插入图片描述
添加Enemy_Skeleton变量,并修改构造函数中传入值

    protected Enemy_Skeleton enemy;public SkeletonAttackState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton _enemy, string _animBoolName) : base(_stateMachine, _enemyBase, _animBoolName){enemy = _enemy;}

(3)触发器的实现

和Player一样,敌人攻击的结束也要借助触发器来实现。
详细讲解请见Unity教程(八)角色基本攻击的实现
我们在状态基类EnemyState中添加改变参数的函数,若触发器被调用,则triggerCalled置为真。添加代码:

    //修改触发器参数public virtual void AnimationFinishTrigger(){triggerCalled = true;}

在Enemy中进行调用

    //设置触发器public virtual void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();

我们创建骷髅的触发器脚本Enemy_SkeletonAnimationTriggers。获取Animator的父组件Enemy_Skeleton,并调用其中的AnimationTrigger()

//Enemy_SkeletonAnimationTriggers:触发器组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy_SkeletonAnimationTriggers : MonoBehaviour
{private Enemy_Skeleton enemy => GetComponentInParent<Enemy_Skeleton>();private void AnimationTrigger(){enemy.AnimationTrigger();}
}

把触发器脚本挂在Enemy_Skeleton的Animator下面 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/41a27165de72476f966005e4d1ccdc39.png#pic_center) 我们在skeletonAttack的最后一帧设置事件帧,调用触发器函数设置triggerCalled参数。

先把白色竖线拉到最后一帧,点击动画面板左边钉子符号的标志添加事件。
在这里插入图片描述
在这里插入图片描述
点击选中事件帧,在右边面板选中函数AnimationTrigger
Fuction->Enemy_SkeletonAnimationTriggers->Methods->AnimationTrigger()
在这里插入图片描述

(4)攻击的实现

我们要在Enemy_Skeleton中创建骷髅攻击状态。

public SkeletonAttackState attackState { get; private set; }protected override void Awake()
{base.Awake();idleState = new SkeletonIdleState(stateMachine,this,this,"Idle");moveState = new SkeletonMoveState(stateMachine, this,this, "Move");battleState = new SkeletonBattleState(stateMachine, this, this, "Move");attackState = new SkeletonAttackState(stateMachine, this, this, "Attack");
}

在SkeletonBattleState中添加状态转换,当距离过近时转换到攻击状态。

    public override void Update(){base.Update();if (enemy.IsPlayerDetected()){if (enemy.IsPlayerDetected().distance < enemy.attackDistance){stateMachine.ChangeState(enemy.attackState);}}if(player.position.x > enemy.transform.position.x)moveDir = 1;else if(player.position.x < enemy.transform.position.x)moveDir = -1;enemy.SetVelocity(enemy.moveSpeed * moveDir, enemy.rb.velocity.y);}

我们在SkeletonAttackState中实现攻击的具体内容。
首先我们希望骷髅靠近玩家时,先停止移动再攻击,所以我们先把骷髅速度赋零。
在攻击动画播放完触发器被触发时,攻击结束,转换到战斗状态。
在这里插入图片描述
点击Animator也能看到左侧Attack变量在转换(切换很快,不仔细看不清楚)。

四、骷髅攻击的冷却

现在骷髅的攻击是连续不断的,在游戏中通常小怪是按照一定的频率进行的,让玩家有一定的躲避时间。
我们给骷髅小怪加上攻击冷却时间,实现上可以参照Player的连击。
我们在Enemy中添加冷却时间attackCoolDown,记录上次攻击的时间lastTimeAttacked用于实现。

    [Header("Attack Info")]public float attackDistance;public float attackCoolDown;[HideInInspector] public float lastTimeAttacked;

在SkeletonAttackState中,每次退出攻击状态时,更新lastTimeAttacked。

    public override void Exit(){base.Exit();enemy.lastTimeAttacked=Time.time;}

在SkeletonBattleState中添加CanAttack函数,利用现在的时间与上次攻击时间加冷却时间比较,判断冷却时间是否已经过去,骷髅是否处于可攻击状态。
先判断是否能检测到玩家,再判断玩家与骷髅的距离,再做攻击冷却的判断,条件都成立时转到战斗状态。

public override void Update(){base.Update();if (enemy.IsPlayerDetected()){if (enemy.IsPlayerDetected().distance < enemy.attackDistance){if(CanAttack())stateMachine.ChangeState(enemy.attackState);}}if(player.position.x > enemy.transform.position.x)moveDir = 1;else if(player.position.x < enemy.transform.position.x)moveDir = -1;enemy.SetVelocity(enemy.moveSpeed * moveDir, rb.velocity.y);}private bool CanAttack(){if (Time.time >= enemy.lastTimeAttacked + enemy.attackCoolDown)return true;return false;}

设置合适的冷却时间
在这里插入图片描述
效果如下
在这里插入图片描述
我们可以看到骷髅每隔一段时间进行攻击了。但是有个很明显的问题,在攻击的间隙骷髅不会停止移动,玩家会被推着走。这个问题下节我们再来解决。

总结 完整代码

EnemyState.cs

增加刚体和触发函数调用

//EnemyState:敌人状态基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyState
{protected EnemyStateMachine stateMachine;protected Enemy enemyBase;protected Rigidbody2D rb;private string animBoolName;protected float stateTimer;protected bool triggerCalled;//构造函数public EnemyState(EnemyStateMachine _stateMachine, Enemy _enemyBase, string _animBoolName){this.stateMachine = _stateMachine;this.enemyBase = _enemyBase;this.animBoolName = _animBoolName;}public virtual void Enter(){rb = enemyBase.rb;triggerCalled = false;enemyBase.anim.SetBool(animBoolName, true);}public virtual void Update(){stateTimer-= Time.deltaTime;}public virtual void Exit(){enemyBase.anim.SetBool(animBoolName, false);}//修改触发器参数public virtual void AnimationFinishTrigger(){triggerCalled = true;}
}

Enemy.cs

添加攻击相关变量,添加触发函数调用。

//Enemy:敌人基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : Entity
{[SerializeField] protected LayerMask WhatIsPlayer;[Header("Move Info")]public float moveSpeed = 1.5f;public float idleTime = 2.0f;[Header("Attack Info")]public float attackDistance;public float attackCoolDown;[HideInInspector] public float lastTimeAttacked;public EnemyStateMachine stateMachine;protected override void Awake(){base.Awake();stateMachine = new EnemyStateMachine();}protected override void Update(){base.Update();stateMachine.currentState.Update();}//设置触发器public virtual void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();public virtual RaycastHit2D IsPlayerDetected()=>Physics2D.Raycast(transform.position, Vector2.right * facingDir, 50 ,WhatIsPlayer);protected override void OnDrawGizmos(){base.OnDrawGizmos();Gizmos.color = Color.yellow;Gizmos.DrawLine(transform.position, new Vector3(transform.position.x + attackDistance * facingDir, transform.position.y));}
}

Enemy_SkeletonAnimationTriggers.cs

触发器组件

//Enemy_SkeletonAnimationTriggers:触发器组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy_SkeletonAnimationTriggers : MonoBehaviour
{private Enemy_Skeleton enemy => GetComponentInParent<Enemy_Skeleton>();private void AnimationTrigger(){enemy.AnimationTrigger();}
}

Enemy_Skeleton.cs

增加攻击状态创建

//Enemy_Skeleton:骷髅敌人
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy_Skeleton : Enemy
{#region 状态public SkeletonIdleState idleState { get; private set; }public SkeletonMoveState moveState { get; private set; }public SkeletonBattleState battleState { get; private set; }public SkeletonAttackState attackState { get; private set; }#endregionprotected override void Awake(){base.Awake();idleState = new SkeletonIdleState(stateMachine,this,this,"Idle");moveState = new SkeletonMoveState(stateMachine, this,this, "Move");battleState = new SkeletonBattleState(stateMachine, this, this, "Move");attackState = new SkeletonAttackState(stateMachine, this, this, "Attack");}protected override void Start(){base.Start();stateMachine.Initialize(idleState);}protected override void Update(){base.Update();}}

SkeletonBattleState.cs

添加攻击冷却判断条件,修改转到攻击状态的条件,修改刚体速度部分代码

//SkeletonBattleState:骷髅战斗状态
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonBattleState : EnemyState
{private Transform player;private Enemy_Skeleton enemy;private int moveDir;public SkeletonBattleState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton _enemy, string _animBoolName) : base(_stateMachine, _enemyBase, _animBoolName){enemy=_enemy;}public override void Enter(){base.Enter();player = GameObject.Find("Player").transform;}public override void Exit(){base.Exit();}public override void Update(){base.Update();if (enemy.IsPlayerDetected()){if (enemy.IsPlayerDetected().distance < enemy.attackDistance){if(CanAttack())stateMachine.ChangeState(enemy.attackState);}}if(player.position.x > enemy.transform.position.x)moveDir = 1;else if(player.position.x < enemy.transform.position.x)moveDir = -1;enemy.SetVelocity(enemy.moveSpeed * moveDir, rb.velocity.y);}private bool CanAttack(){if (Time.time >= enemy.lastTimeAttacked + enemy.attackCoolDown)return true;return false;}
}

SkeletonAttackState.cs

创建攻击状态,攻击时速度置零,触发器触发转回到战斗状态

//SkeletonAttackState:骷髅攻击状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonAttackState : EnemyState
{protected Enemy_Skeleton enemy;public SkeletonAttackState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton _enemy, string _animBoolName) : base(_stateMachine, _enemyBase, _animBoolName){enemy = _enemy;}public override void Enter(){base.Enter();}public override void Exit(){base.Exit();enemy.lastTimeAttacked=Time.time;}public override void Update(){base.Update();enemy.ZeroVelocity();if (triggerCalled)stateMachine.ChangeState(enemy.battleState);}
}

SkeletonMoveState.cs

修改刚体速度部分代码

//SkeletonMoveState:骷髅移动状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonMoveState : SkeletonGroundedState
{public SkeletonMoveState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton enemy, string _animBoolName) : base(_stateMachine, _enemyBase, enemy, _animBoolName){}public override void Enter(){base.Enter();}public override void Exit(){base.Exit();}public override void Update(){base.Update();enemy.SetVelocity(enemy.moveSpeed*enemy.facingDir,rb.velocity.y);if(!enemy.isGroundDetected() || enemy.isWallDetected()){enemy.Flip();stateMachine.ChangeState(enemy.idleState);}}
}

相关文章:

Unity教程(十六)敌人攻击状态的实现

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…...

​图像超分辨率(ISR)​

图像超分辨率&#xff08;Image Super-Resolution, ISR&#xff09;是一种图像处理技术&#xff0c;旨在通过软件算法从低分辨率的图像中重建出高分辨率的图像。这种技术对于改善图像质量、增加细节清晰度等方面非常重要&#xff0c;特别是在图像放大、卫星成像、医学成像和视频…...

园区网基础组网保姆级(mstp,vrrp,irf,eth-trunk,route-policy,ospf,bgp,rbm,nat,mlag等等)

本文实验使用模拟器:H3C HCL 5.10.2版本 一、园区核心/接入架构1.1.三层架构1.2.二层架构二、园区核心 To 接入实践2.1.MSTP+VRRP派系2.1.1.MSTP+VRRP配置2.1.2.MSTP+VRRP验证2.2.IRF+Eth-Trunk派系2.2.1.IRF+Eth-Trunk配置2.3.两种派系的对比2.4.VXLAN结构三、园区核心/出口架…...

大数据技术原理与应用

第一章、大数据概述 1、大数据时代的特征&#xff0c;并结合生活实例谈谈带来的影响。 &#xff08;一&#xff09;特征 1、Volume 规模性&#xff1a;数据量大。 2、Velocity高速性&#xff1a;处理速度快。数据的生成和响应快 摩尔定律&#xff1a;每两年&#xff0c;数…...

《黑神话悟空》开发框架与战斗系统解析

本文主要围绕《黑神话悟空》的开发框架与战斗系统解析展开 主要内容 《黑神话悟空》采用的技术栈 《黑神话悟空》战斗系统的实现方式 四种攻击模式 连招系统的创建 如何实现高扩展性的战斗系统 包括角色属性系统、技能配置文件和逻辑节点的抽象等关键技术点 版权声明 本…...

网络资源模板--Android Studio 通讯录App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--基于Android studio 通讯录 二、项目测试环境 三、项目详情 首页 MainActivity 类是一个 Android 地址簿应用的核心部分&#xff0c;负责管理联系人列表的显示、搜索和添…...

Spring 出现 No qualifying bean of type ‘com.xxx‘ available 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法4. 彩蛋4.1 bug彩蛋4.2 完整Demo4.3 补充Springboot1. 问题所示 出现如下问题: 19:58:23.476 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean o…...

C# 批量更改文件后缀名称

解决问题思路 解决固定文件夹下更改文件后缀名&#xff0c;采用轮询的方式&#xff0c; 流程如下&#xff1a; 获取当前文件名&#xff08;带后缀的文件名&#xff09;截取文件名称&#xff0c;去掉后缀另存为带更改后的后缀文件 注意&#xff1a;采用第三方插件&#xff0…...

KIC算法介绍及pyrosetta示例代码

Kinetic Loop Closure (KIC) 是 Rosetta 中一种重要的环区(loop region)建模算法,主要用于解决蛋白质中的柔性区域(特别是环区)的重构问题。环区是蛋白质中非常灵活的部分,通常结构不确定。KIC 算法采用基于运动学的解决方案,通过设置特定的几何约束,能够在给定的两端锚…...

【论文串烧】多媒体推荐中的模态平衡学习 | 音视频语音识别中丢失导致的模态偏差对丢失视频帧鲁棒性的影响

文章目录 一、多媒体推荐中的模态平衡学习1.1 研究背景1.2 解决问题1.3 实施方案1.4 文章摘要1.5 文章重点1.6 文章图示图 1&#xff1a;不同模型变体在 AmazonClothing 数据集上的初步研究图 2&#xff1a;CKD模型架构的说明图 3&#xff1a;在 Amazon-Clothing 数据集上训练过…...

【C语言二级考试】循环结构设计

C语言二级考试——循环结构程序设计 五.循环结构程序设计 1.for循环结构 2.while和do-while循环结构 3.continue语句和break语句 4.循环的嵌套 知识点参考【C语言】循环-CSDN博客 文章目录 1.for循环2.while和do-while循环结构3.continue语句和break语句4.循环的嵌套 1.for循环…...

诗文发布模板(python代码打造键盘录入诗文自动排版,MarkDown源码文本)

python最好用的f-string&#xff0c;少量代码打造键盘录入诗文自动排版。 (笔记模板由python脚本于2024年09月19日 19:11:50创建&#xff0c;本篇笔记适合喜欢写诗的pythoner的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&am…...

GO主流开源框架

GO主流开源框架 Go 语言有着丰富的开源框架生态&#xff0c;涵盖了多种应用场景&#xff0c;如 Web 开发、数据库操作、微服务、日志处理等。以下是一些常见的 Go 框架及其典型作用场景&#xff1a; 1. Web 框架 Gin: 作用&#xff1a;一个高性能的轻量级 Web 框架&#xff…...

LeetCode:2398. 预算内的最多机器人数目 双指针+单调队列,时间复杂度O(n)

2398. 预算内的最多机器人数目 today 2398. 预算内的最多机器人数目 题目描述 你有 n 个机器人&#xff0c;给你两个下标从0开始的整数数组 chargeTimes 和 runningCosts &#xff0c;两者长度都为 n 。第 i 个机器人充电时间为 chargeTimes[i] 单位时间&#xff0c;花费 ru…...

oracle 插入date日期类型的数据、插入从表中查出的数据,使用表中的默认数据

date sysdate to_date 插入从表中查出的数据 方式一 方式二 或者指定列名称 下边这个案例的前提是指定列插入&#xff0c;如果不指定&#xff0c;则也是默认的...

物流系统打单软件 佳易王物流运单怎么打印教程

一、前言 物流系统打单软件 佳易王物流运单怎么打印教程 1、佳易王物流管理系统可同时打印物流单和标签 2、如果一台电脑上有多台打印机&#xff0c;软件可以设置物流或标签对应的打印机&#xff0c;系统自动识别打印机。 二、软件程序图文说明 1、上图为 物流单在空白单上打…...

二叉树计算

题目描述 给出一个二叉树&#xff0c;请由该二叉树生成一个新的二叉树&#xff0c;它满足其树中的每个节点将包含原始树中的左子树和右子树的和。左子树表示该节点左侧叶子节点为根节点的一颗新树;右子树表示该节点右侧叶子节点为根节点的一颗新树。 输入描述 2行整数&#…...

Java并发执行举例

在Java中实现并发执行可以通过多种方式&#xff0c;最常见的方式包括使用线程、ExecutorService、ForkJoinPool等。以下是几种常用并发执行的示例&#xff1a; 1. 使用Thread类 这是Java中最基础的并发实现&#xff0c;通过创建一个继承自Thread的类或实现Runnable接口来定义…...

Java 基础知识九(网络编程)

UDP DatagramSocket:通讯的数据管道 -send 和receive方法 -(可选&#xff0c;多网卡)绑定一个IP和Port DatagramPacket -集装箱:封装数据 -地址标签:目的地IPPort package org.example.net;import java.net.DatagramPacket; import java.net.DatagramSocket; import java.n…...

深入解析Go语言的类型方法、接口与反射

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 Go语言作为一门现代编程语言,以其简洁高效的特性受到广大开发者的喜爱。在本文中,我们将深入探讨Go语言中的类型方法、接口和反射机制。通过丰富的代码示例和详尽的解释,帮助您全面理解这些关键概念,并在实际…...

C#中线程池【异步】

在 WinForm 项目中&#xff0c;线程池中的线程主要用于执行异步和并发任务。当你调用某些异步方法或使用并行编程时&#xff0c;线程池中的线程就会被使用。 在以下场景中&#xff0c;线程池的线程会被使用&#xff1a; 使用场景 异步任务执行 当你使用 Task.Run() 或 TaskF…...

OpenAI 刚刚推出 o1 大模型!!突破LLM极限

北京时间 9 月 13 日午夜&#xff0c;OpenAI 正式发布了一系列全新的 AI 大模型&#xff0c;专门用于应对复杂问题。 这一新模型的出现代表了一个重要突破&#xff0c;其具备的复杂推理能力远远超过了以往用于科学、代码和数学等领域的通用模型&#xff0c;能够解决比之前更难的…...

【Vmware16安装教程】

&#x1f4d6;Vmware16安装教程 ✅1.下载✅2.安装 ✅1.下载 官网地址&#xff1a;https://www.vmware.com/ 百度云盘&#xff1a;Vmware16下载 123云盘&#xff1a;Vmware16下载 ✅2.安装 1.双击安装包VMware-workstation-full-16.1.0-LinuxProbe.Com.exe&#xff0c;点击…...

Delphi5利用DLL实现窗体的重用

文章目录 效果图参考利用DLL实现窗体的重用步骤1 设计出理想窗体步骤2 编写一个用户输出的函数或过程&#xff0c;在其中对窗体进行创建使它实例化步骤3 对工程文件进行相应的修改以适应DLL格式的需要步骤4 编译工程文件生成DLL文件步骤5 在需要该窗体的其他应用程序中重用该窗…...

使用JavaWeb开发注册功能时,校验用户名是否已存在的一个思路(附代码)

在开发 Web 应用程序时&#xff0c;用户注册是一个常见的功能。为了确保每个用户都有一个唯一的用户名&#xff0c;我们需要在用户注册时检查数据库中是否已经存在该用户名。本文将详细介绍如何在 Servlet 中使用 JDBC 技术来检查用户名是否存在。 1. JDBC 简介 Java Databas…...

前端常见面试-首页性能提升、项目优化

首页性能提升 Vue 首页性能提升是Vue应用开发中非常重要的一环&#xff0c;它直接影响用户体验和应用的加载速度。以下是一些关键的Vue首页性能提升策略&#xff1a; 1. 代码分割与懒加载 路由懒加载&#xff1a;利用Webpack的动态导入&#xff08;import()&#xff09;特性…...

卷王阿里又开启价格战,大模型价格降价85%!

我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 9月19日&#xff0c;就是昨天&#xff0c;一年一度的云计算盛…...

Java中的异步编程模式:CompletableFuture与Reactive Programming的实战

Java中的异步编程模式&#xff1a;CompletableFuture与Reactive Programming的实战 大家好&#xff0c;我是微赚淘客返利系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在现代Java开发中&#xff0c;异步编程已经成为提高应用性能和…...

7iDU AMP田岛绣花机驱动器维修0J2100400022

7iDU AMP神州田岛绣花机驱动器维修0J2101300000绣花机控制器等全系列型号均可处理。 田岛7iDU AMP是田岛绣花机中使用很广的一种5相驱动器&#xff0c;在田岛平绣车TMEF-H&#xff0c;TMFD中应用&#xff0c;在链条车TMCE112S&#xff0c;和盘带车TMLG中大量使用。其采用的东芝…...

部署自己的对话大模型,使用Ollama + Qwen2 +FastGPT 实现

部署资源 AUTODL 使用最小3080Ti 资源&#xff0c;cuda > 12.0使用云服务器&#xff0c;部署fastGPT oneAPI&#xff0c;M3E 模型 操作步骤 配置代理 export HF_ENDPOINThttps://hf-mirror.com下载qwen2模型 - 如何下载huggingface huggingface-cli download Qwen/Qwen2-…...