我觉得看视频太慢了,还是看别人源码更快……

1.664235822/DarkSouls-Demo

Github 源码:
https://github.com/664235822/DarkSouls-Demo

其中关于战斗的主要代码:

BattleManager.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[RequireComponent(typeof(CapsuleCollider))]
public class BattleManager : IActorManagerInterface
{private void OnTriggerEnter(Collider other){WeaponController targetController = other.GetComponentInParent<WeaponController>();if (targetController == null) return;GameObject attacker = targetController.weaponManager.actorManager.gameObject;GameObject receiver = actorManager.actorController.model.gameObject;bool attackValid = CheckAngleTarget(receiver, attacker, 45.0f);bool counterValid = CheckAnglePlayer(receiver, attacker, 30.0f);if (other.gameObject.layer == LayerMask.NameToLayer("Weapon")){actorManager.TryDoDamage(targetController, attackValid, counterValid);}}/// <summary>/// 检查格挡/// </summary>/// <param name="player"></param>/// <param name="target"></param>/// <param name="playerAngle"></param>/// <returns></returns>public static bool CheckAnglePlayer(GameObject player, GameObject target, float playerAngle){Vector3 counterDir = target.transform.position - player.transform.position;float counterAngle = Vector3.Angle(player.transform.forward, counterDir);float counterAngle2 = Vector3.Angle(target.transform.forward, player.transform.forward);bool counterValid = (counterAngle < playerAngle && Mathf.Abs(counterAngle2 - 180.0f) < playerAngle);return counterValid;}public static bool CheckAngleTarget(GameObject player, GameObject target, float targetAngle){Vector3 attackingDir = player.transform.position - target.transform.position;float attackingAngle = Vector3.Angle(target.transform.forward, attackingDir);bool attackValid = (attackingAngle < targetAngle);return attackValid;}}

ActorManager.cs

public class ActorManager : MonoBehaviour
{public ActorController actorController;public BattleManager battleManager;public WeaponManager weaponManager;public StateManager stateManager;public DirectorManager directorManager;public InteractionManager interactionManager;public void TryDoDamage(WeaponController target, bool attackValid, bool counterValid){// 如果自己正在无敌状态,那么目标不会受到伤害if (stateManager.isImmortal){}// 如果自己允许使用 counter,并且该次攻击 counter 角度成立,那么目标进入被眩晕流程else if (stateManager.isCounterBack && counterValid){target.weaponManager.actorManager.Stunned();}// 如果自己正在防御,那么自己进入格挡流程// counter 的优先级高于防御else if (stateManager.isDefence){Blocked();}// 以上情况均不成立,进入伤害判断else{// 如果自己血量大于 0,并且攻击有效,那么可以对自己造成伤害if (stateManager.HP > 0 && attackValid){// 思考:这里是在武器伤害的部分检查死亡// 等到流程多了之后,应该在别的地方判断死亡// 比如在 HP 的 setter 的地方判断死亡// 还有就是,之后应该将受到攻击的流程和死亡的流程不放在同一个逻辑层级里面// 对自己造成伤害的值就是目标的武器的伤害值stateManager.AddHP(-1 * target.WeaponData.ATK);// 如果自己血量被扣除之后仍然大于 0,那么自己进入受攻击流程if (stateManager.HP > 0){// 进入被攻击流程Hit();}// 如果自己血量被扣除之后小于 0,那么自己进入死亡流程else{// 死亡流程Die();}}}}private void Blocked(){actorController.IssueTrigger("blocked");}private void Hit(){actorController.IssueTrigger("hit");}public void Stunned(){actorController.IssueTrigger("stunned");}public void SetIsCounterBack(bool value){stateManager.isCounterBack = value;}private void Die(){actorController.IssueTrigger("die");actorController.playerInput.inputEnabled = false;if (actorController.cameraController.lockState){actorController.cameraController.lockState = false;}actorController.cameraController.enabled = false;if (!actorController.cameraController.isAI)StartCoroutine(Reborn());elseStartCoroutine(DestroyCoroutine());}private IEnumerator Reborn(){yield return new WaitForSeconds(3.0f);SceneManager.LoadScene("GameScene");}private IEnumerator DestroyCoroutine(){yield return new WaitForSeconds(3.0f);Destroy(gameObject);}public void Lock(bool value){actorController.SetBool("lock", value);}

这个地方我注释了一下,感觉,诶,好像还挺简单的

但是他动画状态机也是很好的,可以抄一抄hhh


一开始我是
Manager 是 public 的
Controller 是 private 的
ThirdPerson 是包含多个 Manager 和 Controller 的集合
这就保证了必要的数据的共享,以及独立的逻辑的封装

无论在什么地方更改属性,都会触发 UI 更新,这就需要 setter
更进一步,无论在什么地方更改属性,所有 Controller 都能立即收到通知,这就需要基于委托的事件

做事件的时候,我一开始是写成

Assets/MeowACT/Scripts/ThirdPerson/ThirdPersonEventManager.cs

 /// <summary>/// 第三人称事件管理器/// </summary>public class ThirdPersonEventManager{// 事件相关/// <summary>/// 事件委托类型/// </summary>public delegate void ThirdPersonEvent(object[] args);/// <summary>/// 开始冲刺/// </summary>public event ThirdPersonEvent BeginSprintEvent;/// <summary>/// 开始冲刺之后一帧/// </summary>public event ThirdPersonEvent AfterBeginSprintEvent;/// <summary>/// 结束冲刺/// </summary>public event ThirdPersonEvent EndSprintEvent;/// <summary>/// 开始近战攻击/// </summary>public event ThirdPersonEvent BeginMeleeAttackEvent;/// <summary>/// 结束近战攻击/// </summary>public event ThirdPersonEvent EndMeleeAttackEvent;/// <summary>/// 尝试造成伤害/// </summary>public event ThirdPersonEvent TryDoDamageEvent;/// <summary>/// 结束连击/// </summary>public event ThirdPersonEvent EndComboEvent;/// <summary>/// 血量改变/// </summary>public event ThirdPersonEvent OnHPChangeEvent;/// <summary>/// 体力改变/// </summary>public event ThirdPersonEvent OnNRGChangeEvent;/// <summary>/// 开始自动恢复体力/// </summary>public event ThirdPersonEvent BeginNRGRecoverEvent;/// <summary>/// 结束自动恢复体力/// </summary>public event ThirdPersonEvent EndNRGRecoverEvent;/// <summary>/// 第三人称事件管理器的主人/// </summary>public ThirdPerson Owner;/// <summary>/// 第三人称事件管理器的构造函数/// </summary>/// <param name="owner">第三人称事件管理器的主人</param>public ThirdPersonEventManager(ThirdPerson owner){Owner = owner;}/// <summary>/// 触发开始冲刺事件/// </summary>/// <param name="args"></param>public void FireBeginSprintEvent(object[] args){BeginSprintEvent?.Invoke(args);}/// <summary>/// 触发开始冲刺之后一帧事件/// </summary>/// <param name="args"></param>public void FireAfterBeginSprintEvent(object[] args){AfterBeginSprintEvent?.Invoke(args);}/// <summary>/// 触发结束冲刺事件/// </summary>/// <param name="args"></param>public void FireEndSprintEvent(object[] args){EndSprintEvent?.Invoke(args);}/// <summary>/// 触发开始近战攻击事件/// </summary>/// <param name="args"></param>public void FireBeginMeleeAttackEvent(object[] args){BeginMeleeAttackEvent?.Invoke(args);}/// <summary>/// 触发结束近战攻击事件/// </summary>/// <param name="args"></param>public void FireEndMeleeAttackEvent(object[] args){EndMeleeAttackEvent?.Invoke(args);}public void FireOnHPChangeEvent(object[] args){OnHPChangeEvent?.Invoke(args);}public void FireOnNRGChangeEvent(object[] args){OnNRGChangeEvent?.Invoke(args);}/// <summary>/// 由动画触发的动画事件:尝试攻击/// </summary>public void FireTryDoDamageEvent(){TryDoDamageEvent?.Invoke(null);}/// <summary>/// 由动画触发的动画事件:结束连击/// </summary>public void FireEndComboEvent(){EndComboEvent?.Invoke(null);}

这样写写到后面会有很多个 FireXXXEvent 函数,但是我又没办法,因为如果我要使用

Assets/MeowACT/Scripts/ThirdPerson/ThirdPersonEventManager.cs

     public void Fire(ThirdPersonEvent tpEvent, object[] args){tpEvent?.Invoke(args);}

然后在需要激活事件的地方

Assets/MeowACT/Scripts/ThirdPerson/ThirdPerson.cs

        /// <summary>/// 由动画触发的动画事件,还需要在 mgr 中触发事件:尝试攻击/// </summary>public void FireTryDoDamageEvent(){EventManager.Fire(EventManager.TryDoDamageEvent, null);}

的话,就会出现 在定义事件的类的外部,事件只能为左值 的错误

后来根据那个 animator 的 stringtohash 想到了字典hhhh这就简单了

Assets/MeowACT/Scripts/ThirdPerson/ThirdPersonEventManager.cs

// ----------------------------------------------
// 作者: 廉价喵
// 创建于: 26/03/2022 14:46
// 最后一次修改于: 26/03/2022 15:26
// 版权所有: ThinkDifferentStudio
// 描述:
// ----------------------------------------------using System.Collections.Generic;namespace MeowACT
{/// <summary>/// 第三人称事件管理器/// </summary>public class ThirdPersonEventManager{// 事件相关/// <summary>/// 事件委托类型/// </summary>public delegate void ThirdPersonEvent(object[] args);/// <summary>/// 开始冲刺/// </summary>public event ThirdPersonEvent BeginSprintEvent;/// <summary>/// 开始冲刺之后一帧/// </summary>public event ThirdPersonEvent AfterBeginSprintEvent;/// <summary>/// 结束冲刺/// </summary>public event ThirdPersonEvent EndSprintEvent;/// <summary>/// 开始近战攻击/// </summary>public event ThirdPersonEvent BeginMeleeAttackEvent;/// <summary>/// 结束近战攻击/// </summary>public event ThirdPersonEvent EndMeleeAttackEvent;/// <summary>/// 尝试造成伤害/// </summary>public event ThirdPersonEvent TryDoDamageEvent;/// <summary>/// 结束连击/// </summary>public event ThirdPersonEvent EndComboEvent;/// <summary>/// 血量改变/// </summary>public event ThirdPersonEvent OnHPChangeEvent;/// <summary>/// 体力改变/// </summary>public event ThirdPersonEvent OnNRGChangeEvent;/// <summary>/// 开始自动恢复体力/// </summary>public event ThirdPersonEvent BeginNRGRecoverEvent;/// <summary>/// 结束自动恢复体力/// </summary>public event ThirdPersonEvent EndNRGRecoverEvent;/// <summary>/// 事件字典/// </summary>public Dictionary<string, ThirdPersonEvent> EventMap = new Dictionary<string, ThirdPersonEvent>();/// <summary>/// 第三人称事件管理器的主人/// </summary>public ThirdPerson Owner;/// <summary>/// 第三人称事件管理器的构造函数/// </summary>/// <param name="owner">第三人称事件管理器的主人</param>public ThirdPersonEventManager(ThirdPerson owner){Owner = owner;// 初始化事件字典EventMap.Add("BeginSprintEvent", BeginSprintEvent);EventMap.Add("AfterBeginSprintEvent", AfterBeginSprintEvent);EventMap.Add("EndSprintEvent", EndSprintEvent);EventMap.Add("BeginMeleeAttackEvent", BeginMeleeAttackEvent);EventMap.Add("EndMeleeAttackEvent",EndMeleeAttackEvent);EventMap.Add("TryDoDamageEvent", TryDoDamageEvent);EventMap.Add("EndComboEvent", EndComboEvent);EventMap.Add("OnHPChangeEvent", OnHPChangeEvent);EventMap.Add("OnNRGChangeEvent", OnNRGChangeEvent);EventMap.Add("BeginNRGRecoverEvent", BeginNRGRecoverEvent);EventMap.Add("EndNRGRecoverEvent", EndNRGRecoverEvent);}public void Fire(string eventName, object[] args){EventMap[eventName]?.Invoke(args);}}
}

运行之后发现 EventMap 初始化之后值全为 null
很奇怪了,这就说明我放进去的值不是引用类型……但是我也不知道怎么给我的 delegate void 加引用,所以我就用笨方法,每次重设事件的时候我都重新设置一遍 EventMap

Assets/MeowACT/Scripts/ThirdPerson/ThirdPersonEventManager.cs

// ----------------------------------------------
// 作者: 廉价喵
// 创建于: 26/03/2022 14:46
// 最后一次修改于: 26/03/2022 21:26
// 版权所有: CheapMiaoStudio
// 描述:
// ----------------------------------------------using System.Collections.Generic;
using UnityEngine;namespace MeowACT
{/// <summary>/// 第三人称事件管理器/// </summary>public class ThirdPersonEventManager{// 事件相关/// <summary>/// 事件委托类型/// </summary>public delegate void ThirdPersonEvent(object[] args);/// <summary>/// 开始冲刺/// </summary>public event ThirdPersonEvent BeginSprintEvent{add => EventMap["BeginSprintEvent"] = value;remove => EventMap["BeginSprintEvent"] = value;}/// <summary>/// 开始冲刺之后一帧/// </summary>public event ThirdPersonEvent AfterBeginSprintEvent{add => EventMap["AfterBeginSprintEvent"] = value;remove => EventMap["AfterBeginSprintEvent"] = value;}/// <summary>/// 结束冲刺/// </summary>public event ThirdPersonEvent EndSprintEvent{add => EventMap["EndSprintEvent"] = value;remove => EventMap["EndSprintEvent"] = value;}/// <summary>/// 开始近战攻击/// </summary>public event ThirdPersonEvent BeginMeleeAttackEvent{add => EventMap["BeginMeleeAttackEvent"] = value;remove => EventMap["BeginMeleeAttackEvent"] = value;}/// <summary>/// 结束近战攻击/// </summary>public event ThirdPersonEvent EndMeleeAttackEvent{add => EventMap["EndMeleeAttackEvent"] = value;remove => EventMap["EndMeleeAttackEvent"] = value;}/// <summary>/// 尝试造成伤害/// </summary>public event ThirdPersonEvent TryDoDamageEvent{add => EventMap["TryDoDamageEvent"] = value;remove => EventMap["TryDoDamageEvent"] = value;}/// <summary>/// 结束连击/// </summary>public event ThirdPersonEvent EndComboEvent{add => EventMap["EndComboEvent"] = value;remove => EventMap["EndComboEvent"] = value;}/// <summary>/// 血量改变/// </summary>public event ThirdPersonEvent OnHPChangeEvent{add => EventMap["OnHPChangeEvent"] = value;remove => EventMap["OnHPChangeEvent"] = value;}/// <summary>/// 体力改变/// </summary>public event ThirdPersonEvent OnNRGChangeEvent{add => EventMap["OnNRGChangeEvent"] = value;remove => EventMap["OnNRGChangeEvent"] = value;}/// <summary>/// 开始自动恢复体力/// </summary>public event ThirdPersonEvent BeginNRGRecoverEvent{add => EventMap["BeginNRGRecoverEvent"] = value;remove => EventMap["BeginNRGRecoverEvent"] = value;}/// <summary>/// 结束自动恢复体力/// </summary>public event ThirdPersonEvent EndNRGRecoverEvent{add => EventMap["EndNRGRecoverEvent"] = value;remove => EventMap["EndNRGRecoverEvent"] = value;}    /// <summary>/// 事件字典/// </summary>public Dictionary<string, ThirdPersonEvent> EventMap = new Dictionary<string, ThirdPersonEvent>();/// <summary>/// 第三人称事件管理器的主人/// </summary>public ThirdPerson Owner;/// <summary>/// 第三人称事件管理器的构造函数/// </summary>/// <param name="owner">第三人称事件管理器的主人</param>public ThirdPersonEventManager(ThirdPerson owner){Owner = owner;// 事件字典的键初始化EventMap.Add("BeginSprintEvent", null);EventMap.Add("AfterBeginSprintEvent", null);EventMap.Add("EndSprintEvent", null);EventMap.Add("BeginMeleeAttackEvent", null);EventMap.Add("EndMeleeAttackEvent",null);EventMap.Add("TryDoDamageEvent", null);EventMap.Add("EndComboEvent", null);EventMap.Add("OnHPChangeEvent", null);EventMap.Add("OnNRGChangeEvent", null);EventMap.Add("BeginNRGRecoverEvent", null);EventMap.Add("EndNRGRecoverEvent", null);}public void Fire(string eventName, object[] args){Debug.Log(EventMap[eventName] == null);EventMap[eventName]?.Invoke(args);}}
}

后来才知道 Action 和 Func 其实就是匿名的委托
匿名哦匿名
这样我就不用 public delegate void ThirdPersonEvent(object[] args); 了,这个 ThirdPersonEventAction<object[]> 代替了

Assets/MeowACT/Scripts/ThirdPerson/ThirdPersonEventManager.cs

// ----------------------------------------------
// 作者: 廉价喵
// 创建于: 26/03/2022 14:46
// 最后一次修改于: 27/03/2022 9:07
// 版权所有: CheapMiaoStudio
// 描述:
// ----------------------------------------------using System;
using System.Collections.Generic;
using UnityEngine;namespace MeowACT
{/// <summary>/// 第三人称事件管理器/// </summary>public class ThirdPersonEventManager{// 事件相关/// <summary>/// 开始冲刺/// </summary>public event Action<object[]> BeginSprintEvent{add => eventMap["BeginSprintEvent"] = value;remove => eventMap["BeginSprintEvent"] = value;}/// <summary>/// 开始冲刺之后一帧/// </summary>public event Action<object[]> AfterBeginSprintEvent{add => eventMap["AfterBeginSprintEvent"] = value;remove => eventMap["AfterBeginSprintEvent"] = value;}/// <summary>/// 结束冲刺/// </summary>public event Action<object[]> EndSprintEvent{add => eventMap["EndSprintEvent"] = value;remove => eventMap["EndSprintEvent"] = value;}/// <summary>/// 开始近战攻击/// </summary>public event Action<object[]> BeginMeleeAttackEvent{add => eventMap["BeginMeleeAttackEvent"] = value;remove => eventMap["BeginMeleeAttackEvent"] = value;}/// <summary>/// 结束近战攻击/// </summary>public event Action<object[]> EndMeleeAttackEvent{add => eventMap["EndMeleeAttackEvent"] = value;remove => eventMap["EndMeleeAttackEvent"] = value;}/// <summary>/// 尝试造成伤害/// </summary>public event Action<object[]> TryDoDamageEvent{add => eventMap["TryDoDamageEvent"] = value;remove => eventMap["TryDoDamageEvent"] = value;}/// <summary>/// 结束连击/// </summary>public event Action<object[]> EndComboEvent{add => eventMap["EndComboEvent"] = value;remove => eventMap["EndComboEvent"] = value;}/// <summary>/// 血量改变/// </summary>public event Action<object[]> OnHPChangeEvent{add => eventMap["OnHPChangeEvent"] = value;remove => eventMap["OnHPChangeEvent"] = value;}/// <summary>/// 体力改变/// </summary>public event Action<object[]> OnNRGChangeEvent{add => eventMap["OnNRGChangeEvent"] = value;remove => eventMap["OnNRGChangeEvent"] = value;}/// <summary>/// 开始自动恢复体力/// </summary>public event Action<object[]> BeginNRGRecoverEvent{add => eventMap["BeginNRGRecoverEvent"] = value;remove => eventMap["BeginNRGRecoverEvent"] = value;}/// <summary>/// 结束自动恢复体力/// </summary>public event Action<object[]> EndNRGRecoverEvent{add => eventMap["EndNRGRecoverEvent"] = value;remove => eventMap["EndNRGRecoverEvent"] = value;}    /// <summary>/// 事件字典/// </summary>private Dictionary<string, Action<object[]>> eventMap = new Dictionary<string, Action<object[]>>();/// <summary>/// 第三人称事件管理器的主人/// </summary>public ThirdPerson Owner;/// <summary>/// 第三人称事件管理器的构造函数/// </summary>/// <param name="owner">第三人称事件管理器的主人</param>public ThirdPersonEventManager(ThirdPerson owner){Owner = owner;// 事件字典的键初始化eventMap.Add("BeginSprintEvent", null);eventMap.Add("AfterBeginSprintEvent", null);eventMap.Add("EndSprintEvent", null);eventMap.Add("BeginMeleeAttackEvent", null);eventMap.Add("EndMeleeAttackEvent",null);eventMap.Add("TryDoDamageEvent", null);eventMap.Add("EndComboEvent", null);eventMap.Add("OnHPChangeEvent", null);eventMap.Add("OnNRGChangeEvent", null);eventMap.Add("BeginNRGRecoverEvent", null);eventMap.Add("EndNRGRecoverEvent", null);}public void Fire(string eventName, object[] args){eventMap[eventName]?.Invoke(args);}}
}

[Unity] ACT 战斗系统学习 1:基于委托的事件管理器相关推荐

  1. [Unity] ACT 战斗系统学习 5:使用 ScriptableObject 制作角色属性 1

    首先最重要的是属性 // ---------------------------------------------- // 作者: 廉价喵 // 创建于: 29/03/2022 1:19 // 最后 ...

  2. [Unity] ACT 战斗系统学习 2:从 Buff 系统开始的思考

    从零开始写,我希望 Buff 系统由三部分组成 BuffSystemSingleton 用于存 Buff 对象池和 Buff 字典,提供创建 Buff,回收 Buff 的功能 BuffManager ...

  3. [Unity] ACT 战斗系统学习 8:使用 ScriptableObject 制作角色属性 3

    之前看的那个生成泛型物体的包,我用 git 连接装不上去 虽然可以用读文件的方式装--但是想想就觉得有点累 然后我又想,他那里很多东西是我不需要的,我要是加了,又给组内成员安装工程添加一个麻烦 然后我 ...

  4. [Unity] ACT 战斗系统学习 7:使用 ScriptableObject 制作角色属性 2

    本来我是以为泛型 ScriptableObject 是不可能的 但是我之前在制作技能条件时的尝试让我感觉到一个可能性 当时我是做成这样子的 其实这已经很好看了 当时我是实现了获取一个已知物体的所有字段 ...

  5. [Unity] ACT 战斗系统学习 9:Bolt 和 FlowCanvas

    我在 Bolt 里面跑的时候遇到的第一个问题是,他识别不到我的属性--太怪了 我把 value 调成了 public 他居然也没有显示 然后我在 SerializedMonoBehaviour Mon ...

  6. [Unity] ACT 战斗系统学习 4:重构前的第三人称控制器

    重构前,我的控制器是这样子 Assets/MeowACT/Scripts/ThirdPerson/ThirdPerson.cs // --------------------------------- ...

  7. [Unity] ACT 战斗系统学习 3:ScriptableObject

    会议分享的代码 https://github.com/roboryantron/Unite2017 接下来主要研究这个代码 1.FloatVariable 第一个场景,核心是 FloatVariabl ...

  8. 基于Web的Kafka管理器工具之Kafka-manager的编译部署详细安装 (支持kafka0.8、0.9和0.10以后版本)(图文详解)(默认端口或任意自定义端口)...

    不多说,直接上干货! 至于为什么,要写这篇博客以及安装Kafka-manager? 问题详情 无奈于,在kafka里没有一个较好自带的web ui.启动后无法观看,并且不友好.所以,需安装一个第三方的 ...

  9. 基于 Bitwarden 搭建密码管理器(群晖 Docker)

    本文介绍如何在自己的群晖上使用 Docker 对全平台密码管理服务器 Bitwarden 进行私有部署. 目前的密码管理器方案有 1Password,Lastpass,KeePass,Bitwarde ...

最新文章

  1. 分形:一种计算出来的花朵
  2. 半导体二极管的直流电阻和动态电阻如何区别?
  3. python作者龟叔_龟叔和他的Python
  4. 电脑模拟器哪个好_《英雄聯盟:激鬥峽谷》电脑版哪个安卓模拟器好用?《英雄聯盟:激鬥峽谷》手游电脑版怎么玩...
  5. ITK:将标量映射到Jet Colormap中
  6. 2019年湘潭大学程序设计竞赛(重现赛)补题:F.Black White(尺取法)
  7. oracle 子表数据变化时主表也会更新_亿信ABI版本重大更新,新增60余个实用新功能,还有一项黑科技...
  8. WordPress 多媒体库添加分类和标签支持
  9. asp。net中常用的文件操作类
  10. 【Python 标准库学习】系统相关的参数和函数库 — sys
  11. python3 dict 排序_Python 3.9 新增功能展望
  12. 计算机科学中的递归算法是把问题,递归运算法
  13. 利用SCCM 2007 软件分发
  14. 使用PyQt来编写第一个Python GUI程序
  15. matlab编写全置信度函数,Matlab_curve_fitting_tool的用法图文结合
  16. Atitit.故障排除系列---php 程序网站数据库错误排除流程
  17. 计算机考研408每日一题 day158
  18. WAV转MP3格式最简单的方法[zz]
  19. JavaScript JSON 格式操作
  20. dvwa页面打不开的原因_细看网页打不开的解决办法以及原因细看

热门文章

  1. zz Ubuntu常用命令大全
  2. 面试字节跳动测试岗位一般问什么测试点_字节跳动面试问题集合
  3. 测试开发工程师持续更新
  4. 读高利曼昆的经济学原理(二)
  5. 为什么用了大牌工具后报表开发依然头疼
  6. 中心信令服务器编码,信令网的信令点编码
  7. 【Python开发】FastAPI 07:Depends 依赖注入
  8. 计算机存储二进制都是用补码,为什么计算机存储的是二进制补码?
  9. Apache Dubbo系列:泛化调用
  10. Excel怎么自定义表格样式,设置每两行替换颜色