UE5 C++ TPS开发 学习记录(10
p22
这节课把创建,查找,加入游戏房间的菜单类,以及插件内的系统类给补完了.说实话这节课有点绕,因为需要一直使用委托进行传值,先由菜单类Menu向系统类Subsystem发送函数传值请求,然后监听Subsystem的委托回调,同时系统类Subsystem向Session的工具发送请求,监听回调,再返回给Menu类进行传值.
MultiPlayerSessionSubsystem.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Subsystems/GameInstanceSubsystem.h" #include "Interfaces/OnlineSessionInterface.h" #include "MultiPlayerSessionSubsystem.generated.h" /** * 这里是我们自定义的委托 */ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiPlayerOnCreateSessionComplete ,bool, bWasSuccessful); DECLARE_MULTICAST_DELEGATE_TwoParams(FMultiPlayerOnFindSessionComplete, const TArray<FOnlineSessionSearchResult>& SessionSearchResult , bool bWasSuccessful); DECLARE_MULTICAST_DELEGATE_OneParam(FMultiPlayerOnJoinSessionComplete, EOnJoinSessionCompleteResult::Type Result); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiPlayerOnDestroySessionComplete ,bool, bWasSuccessful); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMultiPlayerOnStartSessionComplete ,bool, bWasSuccessful); UCLASS() class UMultiPlayerSessionSubsystem : public UGameInstanceSubsystem { GENERATED_BODY() public: UMultiPlayerSessionSubsystem(); /* * 这里是一个句柄,让菜单类可以访问Subsystem */ void CreateSession(int32 NumPublicConnections,FString MatchType); void FindSession(int32 MaxSearchResults); void JoinSession(const FOnlineSessionSearchResult& SessionResults); void DestroySession(); void StartSession(); /* * 这是给菜单类做的回调委托 */ FMultiPlayerOnCreateSessionComplete MultiPlayerOnCreateSessionComplete; FMultiPlayerOnFindSessionComplete MultiPlayerOnFindSessionComplete; FMultiPlayerOnJoinSessionComplete MultiPlayerOnJoinSessionComplete; FMultiPlayerOnDestroySessionComplete MultiPlayerOnDestroySessionComplete; FMultiPlayerOnStartSessionComplete MultiPlayerOnStartSessionComplete; protected: /* * 这里是委托 */ void CreateSessionComplete(FName SessionName, bool bWasSuccessful); void FindSessionsComplete(bool bWasSuccessful); void JoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result); void DestroySessionComplete(FName SessionName, bool bWasSuccessful); void StartSessionComplete(FName SessionName, bool bWasSuccessful); private: //查找会话设置 TSharedPtr<FOnlineSessionSearch> LastSessionSearch; IOnlineSessionPtr OnlineSessionInterface; TSharedPtr<FOnlineSessionSettings> LastSessionSettings; /* * 添加OnlineSession委托到列表内 * 我们的游玩系统内部回调绑定到这里 * */ FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate; FDelegateHandle CreateSessionCompleteDelegate_Handle; FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate; FDelegateHandle FindSessionsCompleteDelegate_Handle; FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate; FDelegateHandle JoinSessionCompleteDelegate_Handle; FOnDestroySessionCompleteDelegate DestroySessionCompleteDelegate; FDelegateHandle DestroySessionCompleteDelegate_Handle; FOnStartSessionCompleteDelegate StartSessionCompleteDelegate; FDelegateHandle StartSessionCompleteDelegate_Handle; };
MultiPlayerSessionSubsystem.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "MultiPlayerSessionSubsystem.h" #include "OnlineSessionSettings.h" #include "OnlineSubsystem.h" #include "Online/OnlineSessionNames.h" UMultiPlayerSessionSubsystem::UMultiPlayerSessionSubsystem(): CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this,&ThisClass::CreateSessionComplete)), FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this,&ThisClass::FindSessionsComplete)), JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this,&ThisClass::JoinSessionComplete)), DestroySessionCompleteDelegate(FOnDestroySessionCompleteDelegate::CreateUObject(this,&ThisClass::DestroySessionComplete)), StartSessionCompleteDelegate(FOnStartSessionCompleteDelegate::CreateUObject(this,&ThisClass::StartSessionComplete)) { IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get(); if(OnlineSubsystem) { OnlineSessionInterface = OnlineSubsystem->GetSessionInterface(); } } void UMultiPlayerSessionSubsystem::CreateSession(int32 NumPublicConnections, FString MatchType) { if(!OnlineSessionInterface.IsValid()) { return; } auto ExistingSession = OnlineSessionInterface->GetNamedSession(NAME_GameSession); if(ExistingSession != nullptr) { OnlineSessionInterface->DestroySession(NAME_GameSession); } //存放创建委托 CreateSessionCompleteDelegate_Handle = OnlineSessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate); LastSessionSettings = MakeShareable(new FOnlineSessionSettings()); LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true:false; //最多4人 LastSessionSettings->NumPublicConnections =NumPublicConnections; //允许其他玩家加入 LastSessionSettings->bAllowJoinInProgress = true; //允许好友加入 LastSessionSettings->bAllowJoinViaPresence = true; //线上公开 LastSessionSettings->bShouldAdvertise = true; //显示用户状态 LastSessionSettings->bUsesPresence = true; //使用第三方平台 LastSessionSettings->bUseLobbiesIfAvailable = true; LastSessionSettings->Set(FName("MatchType"),MatchType,EOnlineDataAdvertisementType::ViaOnlineServiceAndPing); const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); if(OnlineSessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession , *LastSessionSettings)) { /*这里是创建失败*/ OnlineSessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate_Handle); /*在这里广播*/ MultiPlayerOnCreateSessionComplete.Broadcast(false); } } void UMultiPlayerSessionSubsystem::FindSession(int32 MaxSearchResults) { if(!OnlineSessionInterface.IsValid()) { return; } //这里将我们的委托设置成SessionInterface的句柄使用 FindSessionsCompleteDelegate_Handle = OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate); //添加查询委托 OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate); //设置查找 LastSessionSearch = MakeShareable(new FOnlineSessionSearch()); LastSessionSearch->MaxSearchResults = 10000; LastSessionSearch->bIsLanQuery= LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true:false; //设置查询设置 LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE,true,EOnlineComparisonOp::Equals); //获得本地的第一个玩家 const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); //使用本地的第一个玩家的URL和查找设置进行查找,当查找为false或者空的时候删除句柄 if(!OnlineSessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(),LastSessionSearch.ToSharedRef())) { //删除掉句柄 OnlineSessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate_Handle); MultiPlayerOnFindSessionComplete.Broadcast(TArray<FOnlineSessionSearchResult>(),false); } } void UMultiPlayerSessionSubsystem::JoinSession(const FOnlineSessionSearchResult& SessionResults) { if(!OnlineSessionInterface.IsValid()) { MultiPlayerOnJoinSessionComplete.Broadcast(EOnJoinSessionCompleteResult::UnknownError); return; } JoinSessionCompleteDelegate_Handle = OnlineSessionInterface->AddOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegate); //获得本地的第一个玩家 const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); //调用JoinSession,并且加入的时候调用OnJoinSessionCompleteDelegate这个委托 if(!OnlineSessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(),NAME_GameSession,SessionResults)) { MultiPlayerOnJoinSessionComplete.Broadcast(EOnJoinSessionCompleteResult::UnknownError); } } void UMultiPlayerSessionSubsystem::DestroySession() { } void UMultiPlayerSessionSubsystem::StartSession() { } void UMultiPlayerSessionSubsystem::CreateSessionComplete(FName SessionName, bool bWasSuccessful) { /*当成功创建房间的时候,删除创建房间的句柄*/ if(OnlineSessionInterface) { OnlineSessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate_Handle); } MultiPlayerOnCreateSessionComplete.Broadcast(bWasSuccessful); } void UMultiPlayerSessionSubsystem::FindSessionsComplete(bool bWasSuccessful) { if(OnlineSessionInterface) { OnlineSessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate_Handle); } if(LastSessionSearch->SearchResults.Num()<=0) { //找到了玩家后删除掉句柄 OnlineSessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate_Handle); return; } MultiPlayerOnFindSessionComplete.Broadcast(LastSessionSearch->SearchResults,bWasSuccessful); } void UMultiPlayerSessionSubsystem::JoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result) { if(OnlineSessionInterface) { OnlineSessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegate_Handle); } MultiPlayerOnJoinSessionComplete.Broadcast(Result); } void UMultiPlayerSessionSubsystem::DestroySessionComplete(FName SessionName, bool bWasSuccessful) { } void UMultiPlayerSessionSubsystem::StartSessionComplete(FName SessionName, bool bWasSuccessful) { }
BaseMenu.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" #include "Interfaces/OnlineSessionInterface.h" #include "BaseMenu.generated.h" /** * */ class UButton; UCLASS() class MULTIPLAYERSESSION_API UBaseMenu : public UUserWidget { GENERATED_BODY() protected: virtual bool Initialize() override; virtual void NativeDestruct() override; /*这里创建用来对应MultiPlayerOnCreateSessionComplete的函数*/ UFUNCTION() void OnCreateSession(bool bWasSuccessful); void OnFindSession(const TArray<FOnlineSessionSearchResult>& SessionSearchResult , bool bWasSuccessful); void OnJoinSession(EOnJoinSessionCompleteResult::Type Result); UFUNCTION() void OnDestroySession(bool bWasSuccessful); UFUNCTION() void OnStartSession(bool bWasSuccessful); public: UFUNCTION(BlueprintCallable) void MenuSetup(int SetupNumPublicConnections = 4,FString SetupMatchType = TEXT("FreeForAll")); void _DebugLog(FColor DisplayColor, const FString& DebugMessage); private: //将指针与按钮绑定起来,这里的绑定必须要指针变量名称和UMG的名称完全一样 UPROPERTY(meta=(BindWidget)) UButton* HostButton; UPROPERTY(meta=(BindWidget)) UButton* JoinButton; UFUNCTION() void HostButtonClicked(); UFUNCTION() void JoinButtonClincked(); UFUNCTION() void MenuTearDown(); class UMultiPlayerSessionSubsystem* MultiPlayerSessionSubsystem; int32 NumPublicConnections{4}; FString MatchType{TEXT("FreeForAll")}; };
.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "BaseMenu.h" #include "OnlineSessionSettings.h" #include "MultiPlayerSession/Public/MultiPlayerSessionSubsystem.h" #include "Components/Button.h" bool UBaseMenu::Initialize() { if(!Super::Initialize()) { return false; } if(HostButton) { HostButton->OnClicked.AddDynamic(this,&UBaseMenu::HostButtonClicked); } if(JoinButton) { JoinButton->OnClicked.AddDynamic(this,&UBaseMenu::JoinButtonClincked); } return true; } void UBaseMenu::NativeDestruct() { Super::NativeDestruct(); } void UBaseMenu::OnCreateSession(bool bWasSuccessful) { if(bWasSuccessful) { _DebugLog(FColor::Green,TEXT("CreateSession Successful")); } UWorld* World = GetWorld(); if(World) { World->ServerTravel("/Game/ThirdPerson/Maps/Lobby?listen"); } } void UBaseMenu::OnFindSession(const TArray<FOnlineSessionSearchResult>& SessionSearchResult, bool bWasSuccessful) { if(MultiPlayerSessionSubsystem==nullptr) { return; } for(auto Result : SessionSearchResult) { FString SettingValue; Result.Session.SessionSettings.Get(FName("MatchType"),SettingValue); if(SettingValue == MatchType) { MultiPlayerSessionSubsystem->JoinSession(Result); return; } } } void UBaseMenu::OnJoinSession(EOnJoinSessionCompleteResult::Type Result) { //加入游戏 IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get(); if(OnlineSubsystem) { IOnlineSessionPtr OnlineSessionInterface = OnlineSubsystem->GetSessionInterface(); if(OnlineSessionInterface.IsValid()) { FString Address; // if(OnlineSessionInterface->GetResolvedConnectString(NAME_GameSession,Address)) { APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController(); if(PlayerController) { PlayerController->ClientTravel(Address,ETravelType::TRAVEL_Absolute); } } } } } void UBaseMenu::OnDestroySession(bool bWasSuccessful) { } void UBaseMenu::OnStartSession(bool bWasSuccessful) { } void UBaseMenu::MenuSetup(int SetupNumPublicConnections ,FString SetupMatchType) { NumPublicConnections = SetupNumPublicConnections; MatchType = SetupMatchType; AddToViewport(); SetVisibility(ESlateVisibility::Visible); bIsFocusable = true; UWorld* World = GetWorld(); if(World) { APlayerController* PlayerController = World->GetFirstPlayerController(); if(PlayerController) { FInputModeUIOnly InputModeUIOnly; InputModeUIOnly.SetWidgetToFocus(TakeWidget()); InputModeUIOnly.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock); PlayerController->SetInputMode(InputModeUIOnly); PlayerController->SetShowMouseCursor(true); } } UGameInstance* GameInstance = GetGameInstance(); if(GameInstance) { MultiPlayerSessionSubsystem = GameInstance->GetSubsystem<UMultiPlayerSessionSubsystem>(); } if(MultiPlayerSessionSubsystem) { MultiPlayerSessionSubsystem->MultiPlayerOnCreateSessionComplete.AddDynamic(this,&ThisClass::OnCreateSession); /*当委托是静态的时候需要使用 AddUObject */ MultiPlayerSessionSubsystem->MultiPlayerOnFindSessionComplete.AddUObject(this,&ThisClass::OnFindSession); MultiPlayerSessionSubsystem->MultiPlayerOnJoinSessionComplete.AddUObject(this,&ThisClass::OnJoinSession); MultiPlayerSessionSubsystem->MultiPlayerOnDestroySessionComplete.AddDynamic(this,&ThisClass::OnDestroySession); MultiPlayerSessionSubsystem->MultiPlayerOnStartSessionComplete.AddDynamic(this,&ThisClass::OnStartSession); } } void UBaseMenu::_DebugLog(FColor DisplayColor, const FString& DebugMessage) { if(GEngine) { GEngine->AddOnScreenDebugMessage(-1,15.f,DisplayColor,DebugMessage); } } void UBaseMenu::HostButtonClicked() { if(MultiPlayerSessionSubsystem) { MultiPlayerSessionSubsystem->CreateSession(NumPublicConnections,MatchType); } _DebugLog(FColor::Blue,FString::Printf(TEXT("Create Session Success"))); } void UBaseMenu::JoinButtonClincked() { //点击加入按钮 if(MultiPlayerSessionSubsystem) { MultiPlayerSessionSubsystem->FindSession(10000); } } void UBaseMenu::MenuTearDown() { UWorld* World = GetWorld(); RemoveFromParent(); APlayerController* PlayerController = World->GetFirstPlayerController(); FInputModeGameAndUI InputModeGameAndUI; PlayerController->SetInputMode(InputModeGameAndUI); PlayerController->SetShowMouseCursor(false); }
相关文章:
UE5 C++ TPS开发 学习记录(10
p22 这节课把创建,查找,加入游戏房间的菜单类,以及插件内的系统类给补完了.说实话这节课有点绕,因为需要一直使用委托进行传值,先由菜单类Menu向系统类Subsystem发送函数传值请求,然后监听Subsystem的委托回调,同时系统类Subsystem向Session的工具发送请求,监听回调,再返回给M…...
ES6(一):let和const、模板字符串、函数默认值、剩余参数、扩展运算符、箭头函数
一、let和const声明变量 1.let没有变量提升,把let放下面打印不出来,放上面可以 <script>console.log(a);let a1;</script> 2.let是一个块级作用域,花括号里面声明的变量外面找不到 <script>console.log(b);if(true){let b1;}//und…...
Docker使用及部署流程
文章目录 1. 准备Docker环境2. 准备应用的Docker镜像3. 在服务器上运行Docker容器方法一:Docker Hub方法二:从构建环境传输镜像4. 管理和维护使用Docker Compose(可选)主要区别步骤 1: 安装Docker ComposeLinuxWindowMac步骤 2: 创建docker-compose.yml文件步骤 3: 使用Doc…...
Nginx的日志怎么看,在哪看,access.log日志内容详解
Nginx 的日志文件通常位于服务器的文件系统中,具体位置可能因配置而异。以下是查看 Nginx 日志的几种方法: 1、查看访问日志:在默认配置下,Nginx 的访问日志文件路径为 /var/log/nginx/access.log。您可以通过命令 sudo cat /var…...
Windows Server 各版本搭建终端服务器实现远程访问(03~19)
一、Windows Server 2003 左下角开始➡管理工具➡管理您的服务器,点击添加或删除角色 点击下一步 勾选自定义,点击下一步 点击终端服务器,点击下一步 点击确定 重新登录后点击确定 点击开始➡管理工具➡计算机管理,展开本地用户…...
Node.js入门基础—day01
个人名片: 😊作者简介:一名大二在校生 🤡 个人主页:坠入暮云间x 🐼座右铭:给自己一个梦想,给世界一个惊喜。 🎅**学习目标: 坚持每一次的学习打卡 文章目录 初识node.js什…...
基于FPGA的PSRAM接口设计与实现
该系列为神经网络硬件加速器应用中涉及的模块接口部分,随手记录,以免时间久了遗忘。 一 PSRAM与HyperRAM 1、概述 2、异同 接口协议不同,因此在IP设计时需要注意。 Hyperram(Winbond):HyperBus协议 PSRAM(AP公司):X…...
OpenCV 图像的几何变换
一、图像缩放 1.API cv2.resize(src, dsize, fx0,fy0,interpolation cv2.INTER_LINEAR) 参数: ①src :输入图像 ②dsize:绝对尺寸 ③fx,fy:相对尺寸 ④interpolation:插值方法 2.代码演示 import cv2 …...
鸿蒙 - 读取 rawfile 中的 json 文件
一、说明 在以下目录中存放了一份地区 json 文件。 我想要将其读出来,并且转为我的实体类。 二、技术实现 import common from ohos.app.ability.common import { CityEntity } from ./entity/CityEntity import util from ohos.util;/*** App 内置的地区数据* r…...
【Stable Diffusion】入门-02:AI绘画提示词+参数设置攻略
目录 1 提示词1.1 分类和书写方式1.1.1 内容型提示词1.1.2 标准化提示词1.1.3 通用模板 1.2 权重1.2.1 套括号1.2.2 数字权重1.2.3 进阶语法 1.3 负面提示词 2 参数详解2.1 Sampling steps2.2 Sampling method2.3 Width, Height2.4 CFG Scale2.5 Seed2.6 Batch count, Batch si…...
Spring Boot启动时执行初始化操作的几种方式
场景 项目中,经常需要在启动过程中初始化一些数据,如从数据库读取一些配置初始化,或从数据库读取一些热点数据到redis进行初始化缓存。 方式一:实现CommandLineRunner 接口重写run方法逻辑 CommandLineRunner是Spring提供的接口࿰…...
考研失败, 学点Java打小工——Day3
1 编码规范——卫语句 表达异常分支时,少用if-else方式。 比如成绩判断中对于非法输入的处理: /*>90 <100 优秀>80 <90 良好>70 <80 一般>60 <70 及格<60 不及格*/Testpu…...
【Stable Diffusion】入门-01:原理简介+应用安装(Windows)+生成步骤
【Stable Diffusion】入门:原理简介应用安装(Windows)生成步骤 原理简介应用安装 原理简介 稳定扩散生成模型(Stable Diffusion)是一种潜在的文本到图像扩散模型,能够在给定任何文本输入的情况下生成照片般逼真的图像。 应用安…...
VueX详解
Vuex 主要应用于Vue.js中管理数据状态的一个库通过创建一个集中的数据存储,供程序中所有组件访问 使用场景 涉及到非父子关系的组件,例如兄弟关系、祖孙关系,甚至更远的关系组件之间的联系中大型单页应用,考虑如何更好地在组件外部…...
2023 年 9 月青少年软编等考 C 语言一级真题解析
目录 T1. 日期输出思路分析 T2. 计算 (a b) (c - b) 的值思路分析 T3. 有一门课不及格的学生思路分析 T4. 特殊求和T5. 比 n 小的最大质数 T1. 日期输出 给定两个整数,表示一个日期的月和日。请按照 "MM-DD" 的格式输出日期,即如果月和日不…...
避免阻塞主线程 —— Web Worker 示例项目
前期回顾 迄今为止易用 —— 的 “盲水印“ 实现方案-CSDN博客https://blog.csdn.net/m0_57904695/article/details/136720192?spm1001.2014.3001.5501 目录 CSDN 彩色之外 📝 前言 🚩 技术栈 🛠️ 功能 🤖 如何运行 ♻️ …...
matlab 基操~
MATLAB基本操作 1. 对象定义 使用sym定义单个对象、使用syms定义多个对象 2. 使用limit求极限 $$ \lim_{v \rightarrow a} f(x) $$ limit(f,v,a) % 使用limit(f,v,a,left)可求左极限 3. 导数 使用diff(f,v,n)对$ f(v)v^{t-1} $求 $ n $ 阶导 $ \frac{d^nf}{d^nv} $…...
HTML5、CSS3面试题(一)
1、H5 的新特性有哪些?C3 的新特性有哪些?(必会) H5 新特性 1、拖拽释放(Drap and drop) API ondrop 拖放是一种常见的特性,即抓取对象以后拖到另一个位置 在 HTML5 中,拖放是标准的一部分,任…...
图片压缩神器源码系统:无损画质 带完整的代码安装包以及搭建教程
在数字化时代,图片已经成为我们日常生活和工作中不可或缺的一部分。然而,随着图片数量的增加和质量的提升,存储空间的问题也日益凸显。如何在保证图片质量的前提下,有效减少图片的大小,成为了一个亟待解决的问题。罗峰…...
探索SOCKS5代理、代理IP、HTTP与网络安全
在这个数字化时代,网络安全已成为我们日常生活中不可或缺的一部分。作为一名软件工程师,深入理解网络通信的核心技术,如SOCKS5代理、代理IP、HTTP协议,以及它们在网络安全中的应用,对于设计和实施安全的网络应用至关重…...
Unity ShaderGraph设计思维:从示例资源读懂URP渲染管线
1. 这不是“示例资源包”,而是一套可复用的ShaderGraph设计思维训练集很多人点开Unity官方ShaderGraph示例资源(Samples for Shader Graph)时,第一反应是:“哦,又是一堆预设效果——水、玻璃、溶解、描边……...
LLM结构化输出工程:让AI返回你想要的格式
为什么结构化输出是工程化的核心需求 “直接问模型,它会告诉你答案”——这在原型阶段没问题。但在生产系统中,你的下游代码需要的不是一段流畅的自然语言,而是可解析的、格式固定的结构化数据。一个用户信息提取API,调用方期望拿…...
对比体验使用Taotoken聚合接口与直连原厂API的延迟与稳定性差异
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比体验使用Taotoken聚合接口与直连原厂API的延迟与稳定性差异 1. 引言 在集成大模型能力到实际业务时,开发者除了关…...
感知机为什么必须加偏置?从数学本质到工程落地全解析
1. 为什么感知机神经元必须带偏置输入?——从数学本质到工程实践的全链路拆解“Why Perceptron Neurons Need Bias Input?” 这个标题看似简单,实则直击人工神经网络最基础却最容易被忽略的底层设计逻辑。我在带高校AI实验课、指导工业界图像分类项目落…...
抖音无水印下载器:5分钟掌握高效批量下载的完整指南
抖音无水印下载器:5分钟掌握高效批量下载的完整指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support…...
嵌入式开发硬件生态构建:MIPI屏、UVC摄像头与4G模块的选型与集成实战
1. 项目概述:一次面向嵌入式开发者的硬件生态补全最近,我们团队负责的睿擎派(一个基于瑞芯微RK3566/RK3588等主流芯片的嵌入式开发板品牌)项目,迎来了一次重要的硬件配件更新。这次上新不是简单的“换个壳”࿰…...
Microsoft Defender双零日在野利用全解析:从BlueHammer到RedSun的终端沦陷之路
前言 2026年5月20日,微软安全响应中心(MSRC)发布紧急安全公告,承认旗下Microsoft Defender存在两个已被野外利用超过一个月的零日漏洞——CVE-2026-41091与CVE-2026-45498。同日,美国国土安全部下属的网络安全与基础设施安全局(CISA)将这两个…...
终极指南:如何通过WeChatIntercept插件彻底解决Mac微信消息撤回问题
终极指南:如何通过WeChatIntercept插件彻底解决Mac微信消息撤回问题 【免费下载链接】WeChatIntercept 微信防撤回插件,一键安装,仅MAC可用,支持v3.7.0微信 项目地址: https://gitcode.com/gh_mirrors/we/WeChatIntercept …...
用Python和OpenCV实现人脸微调:从仿射变换到TPS薄板样条实战
PythonOpenCV人脸微调实战:从仿射变换到TPS薄板样条全解析 当我们需要将一张人脸自然地调整到另一张人脸的形状时,传统仿射变换的局限性就会暴露无遗。本文将从实际应用出发,带你深入理解TPS(Thin Plate Spline)薄板样…...
5分钟掌握Pandoc:终极文档格式转换神器完全指南
5分钟掌握Pandoc:终极文档格式转换神器完全指南 【免费下载链接】pandoc Universal markup converter 项目地址: https://gitcode.com/gh_mirrors/pa/pandoc 你是否曾经为文档格式转换而烦恼?需要将Markdown转换为Word,或者将HTML转换…...
