unity 3D RPG教程(四)

2023-11-03

目录

声明

16:AttackData 攻击属性

17:Execute Attack 实现攻击数值计算

18:Guard & Dead 守卫状态和死亡状态

19:泛型单例模式 Singleton

20:Observer Pattern 接口实现观察者模式的订阅和广播


声明

本教程学习均来自U3D中文课堂麦扣老师

16:AttackData 攻击属性

将人物攻击的数值也写成ScriptObject,在Scripts文件夹中创建一个与攻击相关的文件夹Combat,创建脚本AttactData_SO:写一些基本的数值

AttactData_SO:

[CreateAssetMenu(fileName = "New Attack",menuName ="Attack/Attack Data")]
public class AttactData_SO : ScriptableObject
{
    public float attackRange;//攻击距离

    public float skillRange;//远程攻击距离

    public float coolDown;//冷却时间

    public float minDamge;//最小攻击数值

    public float maxDamge;//最大攻击数值

    public float criticalMultiplier;//暴击加成

    public float criticalChance;//暴击率
}

创建PlayerBaseAttack Data ,设置数值

 创建好了需要在CharacterStats代码中进行调用,这样人物可以读到攻击数值:

 创建 AttactData_SO变量即可:   public AttactData_SO attactData;

在PlayerController中补充未做的修改攻击范围参数:

 //修改攻击范围参数
while(Vector3.Distance(attackTarget.transform.position,transform.position)>characterStats.attactData.attackRange)
{
  agent.destination = attackTarget.transform.position;
  yield return null;
}

  在EnemyController中完善Chase状态:在攻击范围内则攻击

    先定义CharacterStats 变量,     private CharacterStats characterStats;

    在Awake中初始化:characterStats = GetComponent<CharacterStats>();

写2个方法判断是否在攻击范围内:

    bool TargetInAttackRange()//是否能进行近距离攻击
    {
        if (attackTarget != null)
            return Vector3.Distance(attackTarget.transform.position, transform.position) <= characterStats.attactData.attackRange;
        else 
            return false;
    }

    bool TargetInSkillRange()//是否能进行远距离攻击
    {
        if (attackTarget != null)
            return Vector3.Distance(attackTarget.transform.position, transform.position) <= characterStats.attactData.skillRange;
        else
            return false;
    }

    定义攻击时间间隔:   private float lastAttackTime;

在Update中进行计时:    lastAttackTime -= Time.deltaTime;

                //TODO: 在攻击范围内则攻击
                if(TargetInAttackRange()||TargetInSkillRange())//在攻击范围内
                {
                    isFollow = false;
                    agent.isStopped = true;

                    if(lastAttackTime < 0)//攻击
                    {
                        lastAttackTime = characterStats.attactData.coolDown;
                        //暴击判断

                    }
                }

进行暴击判断:在CharacterStats创建一个布尔值判断是否暴击:public bool isCritical;上一行加上  [HideInInspector]让它不在Inspector面板显示

回到EnemyController:

进行暴击判断:

//暴击判断
 characterStats.isCritical = Random.value < characterStats.attactData.criticalChance;

写一个执行攻击的方法:

    void Attack()//执行攻击
    {
        transform.LookAt(attackTarget.transform);//看着攻击目标
        if(TargetInAttackRange())
        {
            //近身攻击动画
        }
        if(TargetInSkillRange())
        {
            //技能攻击动画
        }
    }

 为Slime添加Attack Data:

添加攻击动画:

敌人跑到人物Player面前要停止移动:回到IdleBattle的状态下,然后进行暴击攻击和普通攻击的判断:

    void SwitchAnimation()//切换动画
    {
        anim.SetBool("Walk",isWalk);
        anim.SetBool("Chase",isChase);
        anim.SetBool("Follow",isFollow);
        anim.SetBool("Critical", characterStats.isCritical);
    }

    void Attack()//执行攻击
    {
        transform.LookAt(attackTarget.transform);//看着攻击目标
        if(TargetInAttackRange())
        {
            //近身攻击动画
            anim.SetTrigger("Attack");
        }
        if(TargetInSkillRange())
        {
            //技能攻击动画
            anim.SetTrigger("Skill");
        }
    }

现在敌人可以攻击了,但是拉托敌人后敌人不动了,要把 agent.isStopped = false;加上让敌人可以继续移动

                if(!FoundPlayer())
                {
                    //拉托回到上一个状态
                    isFollow = false;
                    if(remainLookAtTime > 0)
                    {
                        agent.destination = transform.position;
                        remainLookAtTime -= Time.deltaTime;
                    }

                    else if(isGuard)
                    {
                        enemyStates = EnemyStates.GUARD;
                    }
                    else
                    {
                        enemyStates = EnemyStates.PATROL;
                    }

                }
                else
                {
                    isFollow = true;
                    agent.isStopped = false;
                    agent.destination = attackTarget.transform.position;//追Player
                }

17:Execute Attack 实现攻击数值计算

添加Player暴击动画:

 代码当中保持同步:

        //Attack
        if(lastAttackTime < 0)
        {
            anim.SetTrigger("Attack");
            anim.SetBool("Critical", characterStats.isCritical);
            //重置冷却时间
            lastAttackTime = characterStats.attactData.coolDown;
        }

接下来就可以写受伤的计算公式了,受伤部分的计算放在CharacterStats里面,因为这里面读取了最基本的每一个人物的数值,

    #region Character Combat
    public void TakeDamage(CharacterStats attacker, CharacterStats defener)
    {
        int damage = Mathf.Max(attacker.CurrentDamage() - defener.CurrentDefence,0);//保证伤害不会是负值
        CurrentHealth = Mathf.Max(CurrentHealth - damage, 0);//保证血量不会是负值

        //TODO:Update UI
        //TODO:经验Update
    }

    private int CurrentDamage()//当前伤害
    {
        float coreDamage = UnityEngine.Random.Range(attactData.minDamge, attactData.maxDamge);//核心伤害

        if(isCritical)//暴击
        {
            coreDamage *= attactData.criticalMultiplier;
        }

        return (int)coreDamage;
    }

    #endregion

下面回到界面,

 在动画的位置执行一个事件,事件来调用一个函数方法来计算它们2个之间的生命,

先在PlayerController中补充暴击布尔值代码:

    private void EventAttack(GameObject target)
    {
        if(target != null)
        {
            attackTarget = target;
            characterStats.isCritical = UnityEngine.Random.value < characterStats.attactData.criticalChance;
            StartCoroutine(MoveToAttackTarget());//协程:攻击敌人
        }
    }

 写Hit事件:

    //Animation Event
    void Hit()
    {
        var targetStats = attackTarget.GetComponent<CharacterStats>();//临时变量

        targetStats.TakeDamage(characterStats,targetStats);
    }

添加事件: 

 

 同样,在EnemyController中添加事件方法:

    //Animation Event
    void Hit()
    {
        if(attackTarget != null)
        {
            var targetStats = attackTarget.GetComponent<CharacterStats>();//临时变量
            targetStats.TakeDamage(characterStats, targetStats);
        }
    }

发现敌人的动画都是Read——Only的 

 如何解决FBX导入动画无法编辑的问题:将FBX文件里的动画Ctrl+D复制一份出来并更换掉之前的就可以了

 现在就可以添加事件了

现在就可以造成伤害了

18:Guard & Dead 守卫状态和死亡状态

ScriptableObject一个特性就是在你打包好了游戏后只要游戏不退出,ScriptableObject也会一直保留你的数据,所以每次试玩结束后要记得把数值该回去

进入EnemyController当中写一下另外的几个状态:

            case EnemyStates.GUARD:
                isChase = false;
                if(transform.position != guardPos)
                {
                    isWalk = true;
                    agent.isStopped = false;
                    agent.destination = guardPos;//回到站桩点
                    if(Vector3.SqrMagnitude(guardPos - transform.position)<= agent.stoppingDistance)//判断两点之间的距离
                    {
                        isWalk = false;
                    }
                }

要使得Slime回去能转向回原来的方向,创建一个四元数变量来存储原来的rotation

                                  private Quaternion guardRotation;//初始旋转角度

在Awake中初始化: guardRotation = transform.rotation;

缓慢转回原来的角度:

            case EnemyStates.GUARD:
                isChase = false;
                if(transform.position != guardPos)
                {
                    isWalk = true;
                    agent.isStopped = false;
                    agent.destination = guardPos;//回到站桩点
                    if(Vector3.SqrMagnitude(guardPos - transform.position)<= agent.stoppingDistance)//判断两点之间的距离
                    {
                        isWalk = false;
                        transform.rotation = Quaternion.Lerp(transform.rotation, guardRotation, 0.01f);
                    }
                }

添加死亡动画:

为Slime创建一个Death Layer,

 同样给Player添加动画:

 先来制作Enemy死亡的有关部分:

创建bool变量  bool isDead;

Update中实时监测:

        if(characterStats.CurrentHealth == 0)
        {
            isDead = true;//死亡
        }

 SwitchAnimation()切换动画方法中加入 anim.SetBool("Death", isDead);

    void SwitchStates() //切换状态
    {
        if (isDead)//死亡
            enemyStates = EnemyStates.DEAD;

        //如果发现Player,切换为CHASE
        else if(FoundPlayer())
        {
            enemyStates = EnemyStates.CHASE;
        }
       。。。

补充死亡状态:

 case EnemyStates.DEAD:
          agent.enabled = false;

          Destroy(gameObject, 2f);
   break;

现在就可以杀死敌人了:但是敌人死了之后还能攻击,我们可以消除敌人的Collider

定义   private Collider coll;

Awake初始化:   coll = GetComponent<Collider>();

            case EnemyStates.DEAD:
                coll.enabled = false;
                agent.enabled = false;
                Destroy(gameObject, 2f);
                break;

现在就可以了

下面设置Player的死亡状态:    private bool isDead;

Update:   isDead = characterStats.CurrentHealth == 0;

    private void SwitchAnimation()//实时切换动画
    {
        anim.SetFloat("Speed", agent.velocity.sqrMagnitude);    //sqrMagnitude将velocity转换为浮点数值
        anim.SetBool("Death", isDead);
    }

就完成死亡状态了;

19:泛型单例模式 Singleton

创建GameManager

public class GameManager : MonoBehaviour
{
    public CharacterStats playerStats;

    public void RigisterPlayer(CharacterStats player)//反向注册
    {
        playerStats = player;
    }
}

泛型单例模式 Singleton:创建一个文件夹和脚本

打开Singleton:

泛型类的创建方法:在一个类名后面接上一个尖括号,尖括号里通常写的是它的类型

对MonoBehaviour做一个约束,代表它是Singleton的一个类型:

public class Singleton<T>: MonoBehaviour where T: Singleton<T>
{

}

 这是通常泛型单例的写法,

然后可以将MouseManager当中的初始的Awake方法和创建static静态变量的方法都挪到Singleton里面来写

Singleton:

public class Singleton<T>: MonoBehaviour where T: Singleton<T>
{
    private static T instance;

    public static T Instance
    {
        get{ return instance; }
    }

    protected virtual void Awake()
    {
        if(instance != null)
        {
            Destroy(gameObject);
        }
        else
        {
            instance = (T)this;
        }
    }

    public static bool IsInitialized//判断当前单例模式是否已经初始化生成了
    {
        get { return instance != null; }
    }

    protected virtual void OnDestroy()//销毁单例
    {
        if(instance == this)
        {
            instance = null;
        }
    }
}

改一下MouseManager和GameManager:

public class MouseManager : Singleton<MouseManager>
public class GameManager : Singleton<GameManager>

这样就能直接用了。

接下回到PlayerController注册:

    private void Start()
    {
        。。。

        GameManager.Instance.RigisterPlayer(characterStats);//注册GameManager
    }

20:Observer Pattern 接口实现观察者模式的订阅和广播

创建脚本使用第一个接口IEndGameObserver:当结束游戏给这些观察者们来调用的方法

public interface IEndGameObserver 
{

}

我们要实现的就是接口需要调用的函数方法,在这里我们只写方法的定义,而不写方法里面的实现,也就是接口当中我们只写每一个使用了这个接口的代码一定要调用的一些函数

比如:

public interface IEndGameObserver 
{
    void EndNotify();//结束游戏的广播
}
public class EnemyController : MonoBehaviour,IEndGameObserver

修补接口可以看到:所有调用了这个接口都一定要有这个函数方法在代码当中 

 每一个调用接口的代码才写函数里面具体的方法

那么怎么做观察者模式的订阅和广播呢?以后我们会生成多个不同的敌人,每一个敌人都有这个接口,那么我们可以创建一个列表在GameManager当中去收集所有加载了这个接口的函数方法,那就代表它是一个敌人,需要订阅我的结束游戏的广播

在GameManager中创建一个接口类型的列表:用注册的方式让这些观察者主动添加到我们列表当中,敌人生成的时候添加到列表,死亡的时候从列表删除

public class GameManager : Singleton<GameManager>
{
    public CharacterStats playerStats;

    List<IEndGameObserver> endGameObservers = new List<IEndGameObserver>();//观察者列表

    public void RigisterPlayer(CharacterStats player)//反向注册
    {
        playerStats = player;
    }

    public void AddObserver(IEndGameObserver observer)//让观察者主动添加到列表
    {
        endGameObservers.Add(observer);
    }

    public void RemoveObserver(IEndGameObserver observer)//让观察者移除列表
    {
        endGameObservers.Remove(observer);
    }
}

 EnemyController:

    private void OnEnable()
    {
        GameManager.Instance.AddObserver(this);//让观察者主动添加到列表
    }

    private void OnDisable()//销毁完成之后执行
    {
        GameManager.Instance.RemoveObserver(this);//让观察者移除列表
    }

在GameManager中实现广播:

    public void NotifyObservers()//向所有的观察者广播
    {
        foreach(var observer in endGameObservers)
        {
            observer.EndNotify();
        }
    }

当Player死亡的时候调用这个功能广播:

PlayerController:

    private void Update()
    {
        isDead = characterStats.CurrentHealth == 0;

        if(isDead)
        {
            GameManager.Instance.NotifyObservers();//广播
        }

        SwitchAnimation();//实时切换动画
        lastAttackTime -= Time.deltaTime;
    }

最后在EnemyController当中实现广播内容:

添加Slime胜利动画在Victory Layer上

 现在就实现实现 Player 死亡敌人集体欢呼胜利了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

unity 3D RPG教程(四) 的相关文章

  • 在运行时更改 AR core 中对象的纹理

    我正在创建一个应用程序 我需要在其中更改 3d 对象的纹理 图案 我正在使用 AR Core SDK 和 android 我已经使用了下面的代码 但它不起作用 Texture builder setSource this R drawabl
  • 从绘图 3d 图中抓取相机位置

    我正在绘制 3D 图形并想要调整相机位置 对我来说最好的方法是使用查看器 根据需要缩放和旋转场景 然后以 JSON 形式获取相机位置并将其放入我的脚本中 该脚本生成图片以默认实现相同的位置 根据这条推文 https twitter com
  • 如何旋转 3D 散点图

    下面的代码使用 scatterplot3d 函数来运行高度 重量和体积的 3D 散点图 其中点是 1 6 之间的类值 角度目前为 45 度 我知道我可以通过改变角度来倾斜绘图 我应该使用什么代码将绘图向左或向右旋转 以便我可以提供绘图的多个
  • 计算 3D(或 n 维)质心的最佳方法是什么?

    作为工作项目的一部分 我必须计算 3D 空间中一组点的质心 现在我正在以一种看似简单但天真的方式来做这件事 通过取每组点的平均值 如下所示 centroid average x average y average z where x y a
  • 将点云转换为深度/多通道图像

    我有一个通过使用立体相机扫描平面生成的点云 我已经生成了法线 fpfh 等特征 并使用这些信息我想对点云中的区域进行分类 为了能够使用更传统的 CNN 方法 我想将此点云转换为 opencv 中的多通道图像 我将点云折叠到 XY 平面 并与
  • 编写每个三角形/面具有纯色的 GLSL 片段着色器的方法

    我有顶点和三角形数据 其中包含每个数据的颜色triangle 面 不是每个顶点 即单个顶点由多个面共享 每个面可能具有不同的颜色 我应该如何在 GLSL 中解决这个问题以获得每个的纯色分配face正在渲染 通过平均顶点相邻多边形的颜色来计算
  • 如何在 Three.js 中从三角面获取多边形?

    我在网上查了一下是否有人遇到同样的问题 我正在使用 Three js 我有一个 3DObject 其中可能包含孔 面是三角形的 假设我想从上面看到它 我的目标是获得一个代表顶面周长的多边形 这对我来说意味着不再有三角面 而只有 1 个多边形
  • 提取给定 2D 图像点、深度图和相机校准矩阵的 3D 坐标

    我有一套2D image输出的关键点OpenCV FAST角点检测功能 使用Asus Xtion I还有一个时间同步的深度图 其中所有相机校准参数都是已知的 使用这些信息我想提取一组3D坐标 点云 在OpenCV 任何人都可以给我任何有关如
  • WPF 3D 旋转球体 GUI

    我一直在尝试在 WPF 中为我的课堂作业制作 3D 用户界面 但遇到了一个问题 现在 2 3 天都无法解决 我尝试用谷歌搜索答案 我查看了一些 stackoverflow 帖子 但还没有一个可以帮助我解决问题 情况是这样的 我有一个 3D
  • 如何在Android中渲染OBJ或FBX? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有几个 obj 和 fbx 格式的 3D 对象 其中包含 mtl 和纹理文件 我想知道哪个是在 An
  • 如何在 OpenCV 中绘制图像的 3D 直方图

    更新 我找到更多例子 我现在可以做到 我可以在 3d 中绘制多个直方图吗 https stackoverflow com questions 35210337 can i plot several histograms in 3d 我知道这
  • 点列表的 3D 轮廓(凹壳)

    我有一个 C 中的 Vector3 点列表 我需要计算这些点的凹轮廓 确实有很多参考资料 特别是对于 凸 分辨率 由于格雷厄姆算法 我已经成功实现了 然而 由于我现在需要有效地计算凹轮廓 所以我迷失了 维基百科确实列出了很多用于凸计算的资源
  • 一次性渲染阴影

    考虑到阴影投射的成本 我想知道对于动态定位的静态对象 例如 程序城市 是否有一个功能或可能 实验性的方法可以在 Three js 中仅渲染一次阴影贴图 甚至在 webgl 中 因此 结果可以在静态对象的下一帧中免费使用 仅当物体移动时才会进
  • 简单的线框格式?

    我正在寻找一种用于线框模型的简单文件格式 我知道 VRML u3D 等 但这些对于我的需求来说似乎很重要 我的标准是 必须有明确的规格 要么是开放的 要么是非常完善 记录的 我只需要 想要 简单的模型 顶点和边 我不想处理面孔或物体 如果格
  • GL_CULL_FACE使所有对象消失

    我正在尝试在 openGL3 3 中创建一些简单的多边形 我有两种类型的对象 具有以下属性 对象 1 10 个顶点 按顺序在下面列出 存储在GL ARRAY BUFFER并使用GL TRIANGLE FAN v x y z w v 0 0
  • Matlab:3D 堆积条形图

    我正在尝试创建一个 3D 堆积条形图 如这个问题所示 Matlab 中的 3D 堆叠条形图 https stackoverflow com questions 13156133 3d stacked bars in matlab 5D 然而
  • 在 RGL 中将立方体绘制到 3D 散点图中

    我正在尝试向 3D 散点图添加较小的立方体 网格 具有指定边长 我希望立方体位于原点 我该怎么做呢 我已经玩过cube3d 但我似乎无法将立方体正确定位 也无法使其成为网格 因此我可以看到它包含的数据点 这是我所拥有的 library rg
  • 如何在 React Native 中渲染自定义 3D 对象

    我已经成功使用 Three js expo Three 和 expo gl 在 React Native 中配置了红色立方体的 3D 渲染 但我想让用户渲染他们自己可能拥有的自定义 3D 对象 obj 或 mtl 扩展名 但我不确定如何让他
  • 将 3D 场景导入babylonJS

    所以我今天读到巴比伦JS http blogs msdn com b eternalcoding archive 2013 06 27 babylon js a complete javascript framework for build
  • 如何在不使用 Kinect SDK 函数的情况下将深度空间中的点转换为 Kinect 中的颜色空间?

    我正在做一个增强现实应用程序 将 3D 对象叠加在用户的彩色视频之上 使用 Kinect 1 7 版本 虚拟对象的渲染在 OpenGL 中完成 我已经成功地在深度视频上叠加了 3D 对象 只需使用 NuiSensor h 标头中深度相机的固

随机推荐

  • STM32移植LVGL踩坑集锦

    这篇文章我主要讲解一下我在移植LVGL时所遇到的一些坑以及解决方法 LVGL的移植过程可以参考我前面的文章 http t csdn cn QSVOO 第一个 问题 在lvgl8 1以前的版本可能会出现MY DISP HOR RES 和 MY
  • QtDesigner中如何手动添加工具栏toolBar

    如下图 只需要把Action拖到工具栏中即可
  • Android scroller控件,Android Scroller完全解析

    在Android中 任何一个控件都是可以滚动的 因为在View类当中有scrollTo 和scrollBy 这两个方法 如下图所示 这两个方法的主要作用是将View ViewGroup移至指定的坐标中 并且将偏移量保存起来 另外 mScro
  • ES的基本介绍和使用

    增 删 改 查 全部遵循refult 风格 使用postman来新建一个文档 1 增加 http localhost 9200 blog1 article 1 id 1 title 在弹性搜索中创建索引时 content 为什么呢 因为ma
  • nginx 之 root 和 alias

    目录 1 alias 语法 2 root 语法 3 差别 1 alias 语法 Syntax alias path Default Context location 定义指定location的替换 例如 使用以下配置 location i
  • 计算机网络:流量控制和拥塞控制

    拥塞控制和流量控制 流量控制 如果发送方把数据发送得过快 接收方可能会来不及接收 这就会造成数据的丢失 TCP的流量控制是利用滑动窗口机制实现的 接收方在返回的数据中会包含自己的接收窗口的大小 以控制发送方的数据发送 拥塞控制 拥塞控制就是
  • win10 装MySQL Instance Configuration Wizerd 卡死/未响应问题

    一 若此前安装过MySQL应当先将此前的文件残留清除干净 见链接http blog csdn net aerchi article details 50432934 二 隐藏文件ProgramData MySQL也应当删除 偷懒方法就是在安
  • Linux命令·chmod

    chmod命令用于改变linux系统文件或目录的访问权限 用它控制文件或目录的访问权限 该命令有两种用法 一种是包含字母和操作符表达式的文字设定法 另一种是包含数字的数字设定法 Linux系统中的每个文件和目录都有访问许可权限 用它来确定谁
  • Node Sass could not find a binding for your current environment: Windows 64-bit with Node.js 8.x提示报错

    1 在使用统一脚手架的时候提示了报错信息如下 ERROR in app containers App SiderMenu SiderPanel style scss node modules css loader node modules
  • java实现进程控制块_操作系统:进程管理和IO控制

    一 进程管理 进程管理包括进程控制 进程调度 进程同步与通信 死锁控制四个内容 一 进程控制 进程是操作系统中运行的基本单位 包括程序段 数据段和进程控制段 操作系统通过进程控制块 PCB 管理进程 每一个PCB唯一标示一个进程 它存储进程
  • 沉浮于各种文件型数据库 hsqldb h2 还是derby

    原始发表时间 2009 09 10 经过几天的折腾终于还是心碎了 前前后后为了这个数据库共计花费了约2周的时间 系统采用的是经典技术框架 Spring 2 0 5 Hibernate 3 2 iBatis 2 2 0 用于连接文件型数据库的
  • CI/CD持续集成之git命令

    持续集成主要步骤 持续集成的定义 互联网开发已经形成一套标准的流程 最重要的组成部分就是持续集成 持续集成的好处就是 频繁将代码集成到主干 它的优点 1快速发现错误 2 防止分支大幅度偏离主干 意义 就是让产品进行持续迭代 同时保持高质量交
  • git学习1之基本原理

    2019独角兽企业重金招聘Python工程师标准 gt gt gt Git 基础 那么 简单地说 Git 究竟是怎样的一个系统呢 请注意接下来的内容非常重要 若你理解了 Git 的思想和基本工作原理 用起来就会知其所以然 游刃有余 在开始学
  • R手册(Visualise)--ggplot2

    文章目录 Overview Geoms 基本图形 单变量 双变量 三变量 文本 误差可视化 地图 Stats Scales 常用标尺格式 坐标轴标尺 Color and fill scales Shape and size scales C
  • mysql使用参数

    调优 Show status 动态查看mysql状态 top 同理 Show variables 静态查看 Show processlist 查看运行任务列表 Show status like Com 查看系统参数 Show global
  • 新开ubuntu的必要优化

    博主不是专业的运维人员 有时候新开业务服务器到生产环境忘记配置ubuntu的配置时候 就发生各种奇怪的悲剧比如 redis出现大量TIMEWAIT状态 并且服务器不会收 原因是tcp tw recycle配置为0等等 为避免遗忘记录下新开的
  • 国内可用的css,js,图标字体,等常用前端公共库CDN服务

    CDN的全称是Content Delivery Network 即内容分发网络 其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节 使内容传输的更快 更稳定 通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的
  • 参数校验Jakarta Bean Validation学习

    不断学习更新中 同教程代码 码云 1 背景 我们在平时的学习与工作中 都需要对参数进行校验 比如在注册时 用户名密码不能为空 用户名长度必须小于10等等 虽然有些校验在前端页面会进行验证 但是后端为了增加健壮性也需要对这些参数进行判断 比如
  • mqtt报文逐条解析

    文章目录 1 背景说明 2 mqtt报文解析 3 剩余长度计算 4 构建connect报文 5 CONNACK报文示例 6 心跳PING报文 7 心跳回应PINGRESP报文 8 断开连接DISCONNECT报文 9 订阅请求SUBSCRI
  • unity 3D RPG教程(四)

    目录 声明 16 AttackData 攻击属性 17 Execute Attack 实现攻击数值计算 18 Guard Dead 守卫状态和死亡状态 19 泛型单例模式 Singleton 20 Observer Pattern 接口实现