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

Unity任务系统笔记

概述任务系统一般基于事件的发布-监听架构。玩家的某些行为发布事件任务对象监听事件且需要传递一些参数不同类型的任务传递的参数不同不同类型任务参数类的字段包括共用字段和专用字段。参数一般包括任务类型对象Id数量更多数据根据任务类型不同数据类型也不同会用一个父类装然后有一些设计细节不同类任务是发布不同的事件名称还是发布同一个事件把任务类型作为事件参数的一部分任务完成的条件类型之前射击游戏任务完成的方式有对话拾取任务物品仅完成任务用无其他作用击杀敌人进入区域之前发布的事件名是写在对话数据类、任务物品、敌人都是写在场景里检查器上。且事件都没有参数完全靠事件名的匹配完成任务。然后又回到上面的问题事件分为事件名和事件参数本质上都是参数信息可以放事件参数也可以玩家操作时把操作类型、物品Id、数量动态生成一个事件名。射击游戏完全靠事件名匹配因为射击游戏的任务通常靠特殊NPC、特殊物品、任务包含的敌人推进进度。而到了经营、生存类游戏的任务有一个很大的不同就是很多任务要做的事是后面要重复做很多次的事不具有特殊性完全是一般操作。在射击游戏的一关中一个对话任务完成了就无法再次触发也无法再次发布事件而生存游戏像捡木材、砍树、种植这些操作一直能做事件是一直在发布的只是有没有任务监听的问题。这导致不可能只用事件名做匹配必须事件名参数任务收到事件还要使用参数判定是否满足更新、完成条件。对于经营、生存类游戏基本的任务完成条件是操作了Id匹配的对象。然后任务系统的进阶功能会需要完成条件有一些更复杂的条件《或》条件比如拾取一个萝卜或玉米的种子条件不是对象的Id而是配置里的其他字段比如拾取一个种子判断种子的条件是选项列表里有Sow选项那么必须设计从Excel表、任务参数到判定程序的一系列设计。首先想到把支持的完成条件类型定义枚举判定方法里switch条件类型执行与条件可以拆成多个任务。一个RPG游戏任务有最基本的任务名称详细描述目的地坐标此外在任务开启、完成时可能触发多种多样的效果对NPC的操作显示、隐藏、移动位置、注入对话且注入的对话会推进任务进度激活敌人或者激活敌人生成器任务相关道具的激活开启下一个任务每种效果要执行不同对象的不同函数且可能有数量、类型不确定的参数。然后面临选择这些是在场景里配置还是在配表配置制作关卡任务的工作流编辑器vsExcel制作关卡任务需要精确放置NPC、敌人、任务等不可能不用编辑器。编辑器和Excel同时用流程又比较复杂。最终选择了编辑器制作导出json。消除任务对其他对象的引用任务会触发多种效果会影响到各种对象但是如果让任务直接引用对象引用是无法序列化的。任务不能持有任何引用只能有string、int、float、bool等简单数据及其嵌套。那么一切调用其他对象的效果都必须通过发布事件。任务类的数据结构设计基本字段string 任务标题任务目的地Vector3或transformtransform更直观string 任务详细描述基本方法开启任务把这个任务加入任务列表完成任务把这个任务移出任务列表触发、完成的条件任务触发和完成的条件都很多样对话、战斗、取得物品、到达地点、刺杀等。要触发任务需要那些可能触发任务的行为能指向任务这些行为都要加上可能触发的任务字段。触发任务可能是特定行为也可能是一个任务完成。也就是说任务系统不是只加一个系统还需要对其他系统的行为加回调。触发、完成的效果开启和完成任务会有各种效果某些NPC的出现、消失、移动位置某些NPC更新可触发的对话、开启下一个任务、生成敌人。讨论到这里可以发现触发、完成任务很相似所以能不能把它们做成相同的结构把可能的效果都包括进去[Serializable] public class MissionEffects{ [Tooltip(要更新对话的NPC)] public NPCTalk npcTalk; [Tooltip(相关NPC要说的对话)] public TalkData triggerTalk; [Tooltip(要移动的NPC)] public ListMoveNPC moveNPCs; [Tooltip(要触发的无线电通话)] public ListMonologData radioTalk; };对对话系统的修改对话可能完成任务任务开启后玩家找相关NPC触发对话时完成任务且把这个任务变量置空防止再次对话再次完成任务。对话也可能开启任务需要在对话结束后开启任务然后NPC不能再触发这段对话可能是触发任务进行中的对话或者没有对话。和上面触发对话完成任务加起来对话的开始和结束都要加一个UnityEvent。消灭名单所有敌人完成的任务字段要消灭的敌人列表敌人列表的每个敌人也记录自己所属的任务每个敌人死时把敌人移出敌人列表然后判断列表是否为空若是则任务完成。有一个列表记录此关依次要执行的任务对象关卡流程会清楚很多但是多任务分支用列表就不行了。消灭指定个数敌人完成的任务敌人有一个字符串列表记录自己死时分发的事件。然后需要一个监听者监听到敌人死亡后计数1达到需要数量后任务完成。为了减少类数量就让任务对象来监听。总结任务的开启、完成可能被场景里的任意方法触发开启效果、完成效果可能会执行场景里的任意方法。两种对话对话分为两类能反复触发的对话对关卡没有推进的对话简称氛围对话对关卡有推进不同阶段触发不同对话的npc简称推进对话。对于推进对话在关卡不同阶段有不同对话在一个任务进行中触发同一个对话如“拜托你了”实际上出现了完成任务和进行中的多分支。这么多对话的存储位置有几种方案。1.用List全部记录在NPC对象上。由任务对象指定完成后NPC该说哪一段对话。这样NPC对象脚本的检查器上会存一大堆对话数据。也难以看出一段对话对应哪个任务是触发任务的对话还是任务进行中的对话。2.NPC上只记录一段对话数据就是当前去找ta会触发的对话。任务对象上记录两段对话任务触发、进行中要说的对话。当关卡进度管理器显示该触发一个任务时任务对象把触发任务对话写入npc脚本的对话变量任务触发后把任务进行中对话写入npc对话变量。这样氛围npc因为没有任务系统修改ta们的对话数据自然就一直触发同一段对话不用修改。很明显2是最优方案既防止推进进度的npc的脚本里的对话数据过多又兼容两种npc而且不推进进度的npc只有一段对话给ta们声明一个一段对话的List完全是浪费。总之对于氛围NPC只有一个一段对话变量对于推进NPC不同任务阶段对话不同对话应该记录在任务对象。问题回复时开启任务 直接把下一个任务NPC要说的话写入了NPC的对话数据导致当前对话变成下一个任务阶段的需要在回复时记下要触发任务这段对话结束后再开启任务。所以在一段对话数据结构里放一个ListUnityEvent回复的结构体里有一个UnityEvent用于在检查器配置回调函数选择该回复时把这个UnityEvent加入列表对话结束后执行。问题如何标记一段对话是氛围的还是推进的氛围对话可以反复触发一般没有回调。推进对话只能触发一次触发后执行回调。那么有没有回调能作为一段对话是氛围还是推进的标记吗会遇到一些问题如果回调是通过unityEvent.AddListener()添加的非永久监听怎么知道有没有非永久监听查了一下要自己记录。unityEvent没有添加过监听也不一定是null无法通过不添加监听然后判断unityEventnull判定没有回调综上没有准确方法通过UnityEvent判断有没有回调。最终我选择规定不使用AddListener()添加非永久监听一律使用检查器添加永久监听使用GetPersistentEventCount()0判断有回调。这意味着不能用代码写“对话完成任务”的功能而必须在检查器配置来完成。然后“对话型任务”这个任务子类也没有必要存在了。任务和对话的关系然后我们发现任务触发可以更新对话、任务完成可以更新对话、对话可以触发任务、对话可以完成任务还有对话的回调在对话开始还是结束时执行的问题。二者可以调用对方现在是任务更新对话对话要触发的下一个任务也记在任务里。面临一些选择问题比如一个任务会给NPC写入一段对话触发对话会在对话开始或结束时完成这个任务完成任务的函数是写在任务完成的UnityEvent还是对话开始或结束的UnityEvent如果还要开启下一个任务那么就是有两个函数要填入两个可能的的UnityEvent选项变多了。有多个子任务的任务每完成一个子任务提示一下任务界面显示X/Y。比如子任务是移动到某区域子任务需要触发器完成后通知父任务更新完成的子任务数任务面板提示一下更新任务列表显示。父任务要能显示X/Y要有子任务的列表检查里面完成的数量和总数。基于事件中心的设计想象关卡开始时开启任务1为一个NPC注入对话和ta发起对话后完成任务1对话结束时开启任务2。任务为NPC注入对话并且让对话开始时完成任务结束时开启下一个任务。那么任务有2个字符串列表分别指定对话开始和结束时触发哪些事件。[Serializable] public class TalkWithEvents { public string talkID; public Liststring startEvents; public Liststring endEvents; }任务记录自己要监听开启和完成的事件名if (!string.IsNullOrEmpty(openEffects.listenToEvent)) { MyEventCenter.Instance.AddListener(openEffects.listenToEvent, Open); } if (!string.IsNullOrEmpty(completeEffects.listenToEvent)) { MyEventCenter.Instance.AddListener(completeEffects.listenToEvent, Complete); }销毁前要解除监听private void OnDestroy() { if (!string.IsNullOrEmpty(openEffects.listenToEvent)) { MyEventCenter.Instance.RemoveListener(openEffects.listenToEvent, Open); } if (!string.IsNullOrEmpty(completeEffects.listenToEvent)) { MyEventCenter.Instance.RemoveListener(completeEffects.listenToEvent, Complete); } }Excel配表设计任务的有一些成员是和场景分不开的包括目的地位置、要注入对话的NPC、各种回调。配表里适合记录一些简单类型数据任务名称、任务描述等。一个游戏有多个关卡一个关卡有多个任务Excel有多个Sheet。我们用一个sheet存一个场景的任务一个游戏用一个Excel存所有任务。sheet名字标记关卡。任务开启、完成效果中赋予对话的NPC、移动NPC的信息、回调都不能拖对象需要用简单数据类型标记然后面临选择每类效果是各用一个字段记录还是所有效果共用一个字段各类效果的参数数量、类型不同需要制定一个指令格式以及解析指令的程序。为了简单可以只记录一个事件名字场景里的管理器维护一个名字-UnityEvent列表。任务列表要完成的功能有按一个键显示当前开启的任务列表再按一次隐藏选中一个任务时该任务选项高亮显示任务详细描述并把目的地标记设为显示为该任务的目的地开启任务时把该任务加入列表任务完成时把该任务移除开启任务时弹出一个提示对追踪中任务的管理对追踪中任务的管理完成的任务是追踪中任务时追踪中任务要更新任务列表有任务则把第一个设置为追踪中任务没有则设null接取任务时如果没有追踪中任务则把这个设为追踪中任务任务对象在hierarchy里的层级所有任务对象放在一个父对象下面比较清楚。但是一些任务在某目标对象的同一位置作为目标对象的子对象然后reset位置比较方便。可以给任务加一个public Transform targetStart()时把自己的位置设置到目标处。问题协程冲突在修改NPC位置等突变操作时我写了一个画面渐变为黑色执行操作再变透明的函数public UnityAction blackoutCallback; [ContextMenu(画面变黑)] public void Blackout(){ StartCoroutine(BlackoutCoroutine(blackoutCallback)); } float fadeSpeed.04f; IEnumerator BlackoutCoroutine(UnityAction callbacknull){ while(blackBack.color.a1){ blackBack.colornew Color(0,0,0,fadeSpeed); yield return 0; } if(callback!null){ callback.Invoke(); } while(blackBack.color.a0){ blackBack.color-new Color(0,0,0,fadeSpeed); yield return 0; } }然后这个函数在ContextMenu调用时正常但是完成任务调用时画面就不变透明了。NPC被正确移动了。然后在第二个while循环里加了个Debug.Log()发现第二个while循环一直在执行但是alpha值没有变。然后又在第一个while循环加了个打印发现两个while循环都在一直执行。在协程开头加打印发现协程被执行了两次。因为一个很笨的错误。这说明写淡入淡出时如果以imag.color.a作为循环条件如果在一个淡入淡出完成前开始另一个两个协程就会打架淡入淡出永远完不成。实际开发中如果无法避免一个淡入淡出进行中开始另一个就根据计算好的循环次数或者直接规定循环次数并且循环结束后直接把alpha值写成目标值因为如果不这么做就算循环能结束最终的alpha会是一个半透明值。改进后的淡入淡出int fadeStep10; IEnumerator BlackoutCoroutine(UnityAction callbacknull){ for(int i0;ifadeStep;i){ blackBack.colornew Color(0,0,0,1/(float)fadeStep); yield return 0; } blackBack.colorColor.black; if(callback!null){ callback.Invoke(); } for(int i0;ifadeStep;i){ blackBack.color-new Color(0,0,0,1/(float)fadeStep); yield return 0; } blackBack.colornew Color(0,0,0,0); }对话完后要让屏幕渐变黑把NPC移到下一个位置并能触发新对话但是现在对话完后立即就打开交互能触发下一段对话了根据设计对话后这一段对话失效应该在屏幕变黑、把NPC移到新位置后再让下一个任务把对话赋值给NPC。当前的设计是对话结束后执行回调。需要改成对话结束后当前对话立即失效而新对话在屏幕变黑、移动NPC后生效。又不能给对话数据设null使对话失效因为对话数据里包含对话结束的回调里面是下一个任务和对话数据。我选择只把对话数据里的句子列表设null而对话数据里的对话结束回调保留。触发对话时也判断对话数据的句子列表长度是否大于0。为此给对话结束回调加一个选项是直接执行回调还是屏幕变黑执行回调。excel配置游戏任务时任务的目的地在场景里的位置是相对于场景的Vector3很不方便获取怎么办稍微复杂的任务完成逻辑我们会遇到这种情况玩家需要去3个可疑地点搜索在任意一个地点找到目标物都算任务完成。玩家可以选择追踪3个地点中的任意一个同时开启3个任务玩家需要都完成才开启后面的任务基于MVC的任务管理器和面板数据比较简单就都放在Controller里了。Controller不引用View数据变化时发布事件。/// summary /// 任务系统控制器 /// /summary public class MissionManager : MonoSingletonMissionManager{ public const string showMissionListshowMissionList; public ListMissionBase initMissions; public MissionBase chasingMission; PlayerCharacter player; Vector3 targetDir; public ListMissionBase missionList; Coroutine coShowMarker; WaitForSeconds waitUpdateMarker new WaitForSeconds(.07f); Rect scale; Rect canvasRT; bool showPanel; //控制器不要去调用面板让面板监听控制器 public event UnityActionVector2,string onUpdateMarker; public event UnityActionMissionBase onMissionOpen;//需要传入任务名称 public event UnityActionMissionBase onMissionDone; public event UnityAction onChasingChanged; public event UnityActionbool onToggleShowMissions; protected override void Awake() { base.Awake(); } void Start() { player MyInput.Single.player; //画布的rect宽高固定为1920*1080即使分辨率只是自由169 //用于解决分辨率不是1920*1080时任务目的地标记位置错误的问题 canvasRT (GameSceneManager.Single.canvas.transform as RectTransform).rect; scale.width canvasRT.width / Screen.width; scale.height canvasRT.height / Screen.height; coShowMarker StartCoroutine(ShowMissionMarkIE()); } IEnumerator ShowMissionMarkIE() { while (true) { if (chasingMission ! null !chasingMission.hideMark) { GetMarkerPos(); } yield return waitUpdateMarker; } } void OnDisable() { if (coShowMarker ! null) { StopCoroutine(coShowMarker); } } public void MissionComplete(MissionBase mission) { if (!missionList.Contains(mission)) { return; } missionList.Remove(mission); if (chasingMission mission)//完成的是正在追踪的任务追踪任务更新 { if (missionList.Count 0) { SetChasing(0); } else { SetChasing(-1); //missionMarker.gameObject.SetActive(false); } } onMissionDone?.Invoke(mission); } void GetMarkerPos() { Vector3 posCamera.main.WorldToScreenPoint(chasingMission.transform.position); if (pos.z 0) { pos.x Mathf.Clamp(pos.x,0, Screen.width); pos.y Mathf.Clamp(pos.y,0, Screen.height); } else { pos.x pos.x Screen.width / 2 ? Screen.width : 0; pos.yScreen.height / 2; } pos new Vector2(pos.x * canvasRT.width / Screen.width, pos.y * canvasRT.height/Screen.height); string distanceHint ((int)Vector3.Distance(player.transform.position, chasingMission.transform.position)).ToString() m; onUpdateMarker?.Invoke(pos, distanceHint); } public void SetChasing(int index) { if (index 0 index missionList.Count) { chasingMission missionList[index]; } else { chasingMission null; } onChasingChanged?.Invoke(); } public void ToggleMissionList(){ showPanel !showPanel; onToggleShowMissions?.Invoke(showPanel); } public void HideMissionList(){ if (showPanel) { ToggleMissionList(); } } public void OpenMission(MissionBase mission){ if (missionList.Contains(mission)) { return; } missionList.Add(mission); if (!chasingMission) { SetChasing(missionList.IndexOf(mission)); } onMissionOpen?.Invoke(mission); } public bool GetMissionPanelOn() { return showPanel; } /// summary /// 把当前任务列表清空开启注入的任务 /// /summary public void InjectMissions(ListMissionBasemissions) { } }View监听Controller的事件。收到输入时调用Controller的public class PanelMission : PanelBase { public const string showMissionList showMissionList; [SerializeField] RectTransform marker; [SerializeField] Text textDistance; Animator animator; [SerializeField] VerticalLayoutGroup missionListRoot; [SerializeField] ListButton missionEntries new(); [SerializeField] VerticalLayoutGroup missionHint; [SerializeField] Button entryPrefab; Button buttonOn; [SerializeField] Image imageDesc; [SerializeField] Text textDesc; [SerializeField] Text missionHintPrefab; const float hintLifeTime 2.5f; protected override void Awake() { base.Awake(); animator GetComponentAnimator(); } protected override void Init() { base.Init(); MissionManager.Single.onUpdateMarker SetMarkerPos; MissionManager.Single.onToggleShowMissions ToggleMissionList; MissionManager.Single.onMissionOpen MissionOpen; MissionManager.Single.onMissionDone MissionDone; } protected override void OnDestroy() { base.OnDestroy(); if (MissionManager.Single) { MissionManager.Single.onUpdateMarker - SetMarkerPos; MissionManager.Single.onToggleShowMissions - ToggleMissionList; MissionManager.Single.onMissionOpen - MissionOpen; MissionManager.Single.onMissionDone - MissionDone; } } /// summary /// 控制任务目的地标志的位置 /// /summary public void SetMarkerPos(Vector2 pos,string distanceHint) { marker.anchoredPosition pos; textDistance.textdistanceHint; } public void RefreshMissionList() { for (int i 0; i missionEntries.Count; i) { Destroy(missionEntries[i].gameObject); } ListMissionBase missions MissionManager.Single.missionList; for (int i 0; i missions.Count; i) { Button mission Instantiate(entryPrefab, missionListRoot.transform); Text desc mission.GetComponentInChildrenText(); desc.text missions[i].missionContent; Button button mission.GetComponentButton(); int index i; button.onClick.AddListener(() { imageDesc.gameObject.SetActive(true); //改变追踪的任务需要VCV MissionManager.Single.SetChasing(index); //这里改一下监听控制器 textDesc.text missions[index].missionDetail; }); } } void UpdateButtonOn(Button button) { if (buttonOn button) { return; } if (buttonOn) { buttonOn.GetComponentImage().color Color.gray; } buttonOn button; buttonOn.GetComponentImage().color Color.white; } /// summary /// 在上方显示一个任务开启、完成的提示。 /// 有多条提示时自动上下排布 /// /summary /// param namemission/param public void ShowMissionOpen(MissionBase mission) { Text hint Instantiate(missionHintPrefab, missionHint.transform); hint.text mission.missionContent; Destroy(hint.gameObject, hintLifeTime); } void ShowMissionDone(MissionBase mission) { Text hint Instantiate(missionHintPrefab, missionHint.transform); hint.text mission.missionContent 完成; Destroy(hint.gameObject, hintLifeTime); } public void ToggleMissionList(bool show) { if (show) { ShowMissionList(); } else { HideMissionList(); } } /// summary /// 开启的任务列表显示出来 /// /summary public void ShowMissionList() { animator.SetBool(showMissionList, true); Cursor.lockState CursorLockMode.None; MyInput.Single.playerInput.SwitchCurrentActionMap(MyInput.actionMapMissionPanel); //int i missionList.IndexOf(chasingMission); //if (i 0) //{ // Button button missionListRoot.transform.GetChild(i).GetComponentButton(); // UpdateButtonOn(button); //} } public void HideMissionList() { animator.SetBool(showMissionList, false); Cursor.lockState CursorLockMode.Locked; MyInput.Single.playerInput.SwitchCurrentActionMap(MyInput.actionMapPlayer); imageDesc.gameObject.SetActive(false); } /// summary /// 有任务开启时做两件事 /// 刷新任务列表上方弹出提示 /// /summary void MissionOpen(MissionBase mission) { RefreshMissionList(); ShowMissionOpen(mission); } void MissionDone(MissionBase mission) { RefreshMissionList(); ShowMissionDone(mission); } }

相关文章:

Unity任务系统笔记

概述任务系统一般基于事件的发布-监听架构。玩家的某些行为发布事件,任务对象监听事件,且需要传递一些参数,不同类型的任务传递的参数不同,不同类型任务参数类的字段包括共用字段和专用字段。参数一般包括:任务类型&am…...

Ambar API 集成指南:RESTful接口的完整使用方法

Ambar API 集成指南:RESTful接口的完整使用方法 【免费下载链接】ambar :mag: Ambar: Document Search Engine 项目地址: https://gitcode.com/gh_mirrors/am/ambar Ambar 作为一款强大的文档搜索引擎,提供了丰富的 RESTful API 接口,…...

Bottleneck完全指南:5个核心概念让你成为速率限制专家

Bottleneck完全指南:5个核心概念让你成为速率限制专家 【免费下载链接】bottleneck Job scheduler and rate limiter, supports Clustering 项目地址: https://gitcode.com/gh_mirrors/bo/bottleneck Bottleneck是一款强大的作业调度器和速率限制器&#xff…...

SmartOnmyoji:阴阳师全自动代肝脚本的终极解决方案

SmartOnmyoji:阴阳师全自动代肝脚本的终极解决方案 【免费下载链接】SmartOnmyoji 阴阳师后台代肝脚本,支持所有类似阴阳师的卡牌游戏(点点点游戏)自动找图-点击…(支持后台运行、支持多开、支持模拟器) …...

Uncertainty Toolbox高级应用:对抗性群体校准与重新校准技术

Uncertainty Toolbox高级应用:对抗性群体校准与重新校准技术 【免费下载链接】uncertainty-toolbox Uncertainty Toolbox: a Python toolbox for predictive uncertainty quantification, calibration, metrics, and visualization 项目地址: https://gitcode.com…...

Fiddler弱网测试全攻略

利用Fiddler进行弱网测试 弱网测试是模拟网络延迟、丢包或带宽限制等不良网络条件的过程,用于评估应用在真实环境中的性能和稳定性。Fiddler是一个强大的网络调试工具,支持通过自定义规则模拟弱网环境。以下是逐步指南,帮助您实现弱网测试&a…...

TypeScript异步迭代器资源释放终极指南:Dispose机制深度解析

TypeScript异步迭代器资源释放终极指南:Dispose机制深度解析 【免费下载链接】TypeScript TypeScript is a superset of JavaScript that compiles to clean JavaScript output. 项目地址: https://gitcode.com/GitHub_Trending/ty/TypeScript TypeScript作为…...

7个技巧彻底搞懂esbuild中switch语句的解析机制

7个技巧彻底搞懂esbuild中switch语句的解析机制 【免费下载链接】esbuild An extremely fast bundler for the web 项目地址: https://gitcode.com/GitHub_Trending/es/esbuild esbuild作为一款超快速的Web打包工具,其高效的JavaScript解析能力是实现极速构建…...

保姆级教程:在Linux服务器上手动编译安装tiny-cuda-nn(含GCC/CUDA版本检查与Gitee镜像加速)

保姆级教程:在Linux服务器上手动编译安装tiny-cuda-nn(含GCC/CUDA版本检查与Gitee镜像加速) 在深度学习领域,tiny-cuda-nn作为NVIDIA官方推出的高性能神经网络库,能够显著加速NeRF等模型的训练过程。然而,在…...

5分钟实战:用VideoDownloadHelper高效下载在线视频的完整指南

5分钟实战:用VideoDownloadHelper高效下载在线视频的完整指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 想要轻松保存网络视…...

Bottleneck实战:从零构建高并发API限流系统

Bottleneck实战:从零构建高并发API限流系统 【免费下载链接】bottleneck Job scheduler and rate limiter, supports Clustering 项目地址: https://gitcode.com/gh_mirrors/bo/bottleneck 在当今高并发的网络环境中,API限流是保障服务稳定性的关…...

vscode-dark-islands的悬停高亮:背景与透明度优化全指南

vscode-dark-islands的悬停高亮:背景与透明度优化全指南 【免费下载链接】vscode-dark-islands VSCode theme based off the easemate IDE and Jetbrains islands theme 项目地址: https://gitcode.com/GitHub_Trending/vs/vscode-dark-islands vscode-dark-…...

5个核心功能深度解析:LSLib如何成为《神界原罪》与《博德之门3》MOD开发的瑞士军刀

5个核心功能深度解析:LSLib如何成为《神界原罪》与《博德之门3》MOD开发的瑞士军刀 【免费下载链接】lslib Tools for manipulating Divinity Original Sin and Baldurs Gate 3 files 项目地址: https://gitcode.com/gh_mirrors/ls/lslib LSLib是一个专门为《…...

革命性Ruby安装工具ruby-install:一键安装5种Ruby实现完全指南

革命性Ruby安装工具ruby-install:一键安装5种Ruby实现完全指南 【免费下载链接】ruby-install Installs Ruby, JRuby, TruffleRuby, or mruby 项目地址: https://gitcode.com/gh_mirrors/ru/ruby-install ruby-install是一款功能强大的命令行工具&#xff0c…...

如何让Windows资源管理器原生支持HEIC缩略图预览

如何让Windows资源管理器原生支持HEIC缩略图预览 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC/HEIF files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails 如果你经常在Windows电脑上处理…...

如何使用Newton创建交互式仿真?用户输入与实时控制完整指南

如何使用Newton创建交互式仿真?用户输入与实时控制完整指南 【免费下载链接】newton An open-source, GPU-accelerated physics simulation engine built upon NVIDIA Warp, specifically targeting roboticists and simulation researchers. 项目地址: https://g…...

agent-skills中的异步编程:提高应用并发性能的实用方法

agent-skills中的异步编程:提高应用并发性能的实用方法 【免费下载链接】agent-skills Production-grade engineering skills for AI coding agents. 项目地址: https://gitcode.com/GitHub_Trending/agentskill/agent-skills 在现代应用开发中,异…...

全栈开发的未来消亡论:2026年技术人该如何重新定位?

在2026年的技术浪潮中,“全栈开发者消亡论”正引发行业内的广泛热议。AI工具的爆发式增长、云原生技术的深度普及,正在以前所未有的速度颠覆传统开发模式。对于软件测试从业者而言,这场变革既是前所未有的挑战,也是实现职业跃迁的…...

从containers-from-scratch看Docker底层:容器运行时技术揭秘

从containers-from-scratch看Docker底层:容器运行时技术揭秘 【免费下载链接】containers-from-scratch Writing a container in a few lines of Go code, as seen at DockerCon 2017 and on OReilly Safari 项目地址: https://gitcode.com/gh_mirrors/co/contain…...

AI工程师职业天花板破解:技术深度与业务广度的平衡艺术

在软件测试行业深耕多年,你或许早已习惯在代码的迷宫中寻找漏洞,在功能的边界处验证逻辑。但当AI技术如潮水般席卷整个IT领域,不少测试从业者开始将目光投向AI工程师这一充满机遇的赛道。然而,看似光鲜的职业背后,却暗…...

终极容器镜像管理指南:掌握ImagesCommand的完整操作教程

终极容器镜像管理指南:掌握ImagesCommand的完整操作教程 【免费下载链接】container A tool for creating and running Linux containers using lightweight virtual machines on a Mac. It is written in Swift, and optimized for Apple silicon. 项目地址: ht…...

ActiveState Code Recipes项目安全最佳实践:保护你的开源代码仓库

ActiveState Code Recipes项目安全最佳实践:保护你的开源代码仓库 【免费下载链接】code ActiveState Code Recipes 项目地址: https://gitcode.com/gh_mirrors/code1/code 为什么安全最佳实践对ActiveState Code Recipes至关重要 ActiveState Code Recipes…...

手把手教你用FPGA实现“智能”以太网协议栈:自动应答ARP/ICMP,用户只需管UDP

FPGA以太网协议栈的智能封装:让UDP通信像串口一样简单 在物联网和边缘计算爆发的今天,FPGA作为硬件加速的重要载体,正越来越多地需要直接接入网络。但传统FPGA网络协议栈开发存在两大痛点:一是需要手动处理ARP、ICMP等底层协议&am…...

Hermes Agent 云端部署实战:从零到一在 DigitalOcean 上构建 24/7 智能体服务

1. 项目概述与核心价值如果你正在构建一个基于 Claude Code 或 agent-skills 的智能体,并且希望它能像一台永不关机的服务器一样,7x24小时在线,随时响应你的指令,那么将 Hermes Agent 部署到云端虚拟服务器(VPS&#x…...

golang如何压缩和解压文件_golang文件压缩解压步骤

gzip仅压缩单文件流,不处理目录打包;archive/zip支持多文件但需手动路径净化防Zip Slip;tar.gz须先tar后gzip嵌套,顺序错误将导致乱码。gzip 只能压单个文件,别指望它打包目录Go 的 compress/gzip 本质是压缩算法封装&…...

DeepLearningForNLPInPytorch代码解析:深入理解词嵌入与词向量技术

DeepLearningForNLPInPytorch代码解析:深入理解词嵌入与词向量技术 【免费下载链接】DeepLearningForNLPInPytorch An IPython Notebook tutorial on deep learning for natural language processing, including structure prediction. 项目地址: https://gitcode…...

终极分屏游戏解决方案:一台电脑实现多人游戏狂欢

终极分屏游戏解决方案:一台电脑实现多人游戏狂欢 【免费下载链接】UniversalSplitScreen Split screen multiplayer for any game with multiple keyboards, mice and controllers. 项目地址: https://gitcode.com/gh_mirrors/un/UniversalSplitScreen 还在为…...

保姆级教程:用Python复现2023国赛A题塔式光热电站定日镜场建模与优化(附完整代码)

Python实战:塔式光热电站定日镜场建模与优化全流程解析 站在敦煌广袤的戈壁滩上,成排的定日镜阵列如同银色向日葵般追随着太阳轨迹。这些看似简单的镜面背后,隐藏着复杂的光学计算与空间优化算法。本文将带你用Python完整复现2023年全国大学生…...

containers-from-scratch cgroups实战:资源限制与进程管理完整教程

containers-from-scratch cgroups实战:资源限制与进程管理完整教程 【免费下载链接】containers-from-scratch Writing a container in a few lines of Go code, as seen at DockerCon 2017 and on OReilly Safari 项目地址: https://gitcode.com/gh_mirrors/co/c…...

Casbin容量规划:大规模用户权限系统终极设计指南

Casbin容量规划:大规模用户权限系统终极设计指南 【免费下载链接】casbin Apache Casbin: an authorization library that supports access control models like ACL, RBAC, ABAC. 项目地址: https://gitcode.com/GitHub_Trending/ca/casbin 在构建企业级应用…...