An Introduction to UE4 Plugins

2023-10-29

An Introduction to UE4 Plugins

Rate this Article:
3.67
  (3 votes)

Approved for Versions:4.2, 4.3, 4.4, 4.5

Overview

The goal of this tutorial is to show you how to create a new plugin, exercising the basic concepts and giving you a platform on which you can build your own projects out.

For examples sake, I will be creating a bundle called "Bob's Bundle" and it will do little more than expose an interface to call into a protected method that will output to the console.

Scope & Notes

  • A "Plugin" is the wrong term to use in describing what we are doing. Instead we will refer to it as a bundle from now on. This is discussed in the next section - Concepts and Limitations.
  • You will be able to create a new bundle of your own by the end
  • I expect you to have, at the very least, a more than cursory level of knowledge about C++, and the UE4 Build System
  • All Code paths provided, unless noted otherwise, are from the UE4 Project's base directory.
  • Any time a file is added to the project, you should regenerate your project files.

Concepts & Limitations

The general idea behind a bundle is to wrap up a set of functionality that can be treated as a self contained group, transplanted as needed, adding functionality to UE4. There are three types of bundle:

  1. Non-Game Module - Extension or Creation of a set of code that exposes an interface to internal code, allowing other modules and game modules to depend upon its functionality.
  2. Stand Alone Plugin - Extension or Creation of a set of code that does not allow exterior modules to modify its contents.
  3. Content Module - Contains content that is available to developers in the editor, as well as in the game.

As the designer you are free to include any number of these you wish in your bundle, and in fact - you can include them all in the same bundle. They are simply used as encapsulation tools.

Note Your bundle should not include a primary game module.

Note Your bundle may not have configurations in the config directory of your project.

Engine vs. Installed

An engine plugin is one that resides in the Plugin directory of your UE4 install. It will show up as Built In when looking at the plugin listing in the editor. An Installed plugin is only available or loaded for a particular Project.

To see a list of the plugins that are already available to you (Enabled and Disabled) open the editor and in the menu bar, selectWindow > Plugins. From here you can load or unload any plugins by checking the Enabled checkbox.

If you wish to see any of the modules, including your game and plugins, that are available, select Window > Developer Tools >Modules. From here you can load, unload, reload and or recompile any of the modules currently available to the editor.

First Steps

To begin, you will need to create a new project from the UE4 Editor. I recommend a code project, so you are able to exercise the interface of your module, given that you create one. I am exporting a Basic Code project called BobsPlayground.

File Structure

Once Visual Studio (VS) has finished spinning up open up the project path in the windows file explorer. Here, create a new folder - Plugins, which should reside at MyProject/Plugins. In my example it is called BobsPlayground/Plugins.

This is the directory that will house all of our further development, until we return to UE4 to confirm that we have the ability to add a dependency between our project and our plugin.

Content Module

Figure 1. A peek into the plugin UI in the UE4 editor.

Within the Plugins directory, add a new folder - Content. This will house our Content modules assets. Within this directory add a Content.uplugin file. This will be thedescriptor for our plugin, so UE4 can find it, load it up and knows what to do with it.

Here is the sample I am using for my content module. Feel free to copy it.

{
    "FileVersion" : 3,
    "FriendlyName" : "Bob's Content",
    "Version" : 1,
    "VersionName": "1.0",
    "EngineVersion" : 1579795,
    "Description" : "Here I describe the content.",
    "Category" : "Bobs.Content",
    "CreatedBy" : "Bob Chatman",
    "CreatedByURL" : "http://gneu.org",
    "CanContainContent" : "true"
}

This provides the plugin system with everything short of an icon to show in the UI View. To add an icon, create a Resources directory within your plugin folder, and create a PNG in there called Icon128.png.

Note As the name implies, it should be 128x128 px

You should also be aware of the Category. It provides a way for you to filter your plugins by type, developer or whatever you choose. Each sub category is separated by a period character. Above, Bobs.Content becomes Bobs > Content in the plugin listing in the editor, as shows in Figure 1, above.

Note As of UE4.0.1, Content bundles dead end here. Adding content to your bundle is a planned feature, but is not yet functional.

Archive Manifest

  • Content/*
  • Resources/Icon128.png
  • Content.uplugin

Stand Alone Plugin

Although not quite as straight forward as content, the Stand Alone plugin is a hundred times more interesting, technically speaking. These plugins exist for no other purpose than to extend and create new unreal editor classes. A prime example of such a plugin is the Vertex Snap Editor Extension byRama, which adds the ability for you to vertex snap meshes together, but also details out how his plugin works. Seeing as this is an introduction to plugins, I will only show you how to configure your plugin, what you do with it afterwards is on you =).

File Structure

We will, once again, add a uplugin plugin descriptor. This time we will make a modification to it though, adding in a modules listing parameter to allow us to configure the plugin and the declare the contexts that we wish for our standalone plugin to be loaded.

Inside /Plugins/StandAlone/StandAlone.uplugin

{
    "FileVersion" : 3,
 
    "FriendlyName" : "Bob's Plugin",
    "Version" : 1,
    "VersionName": "1.0",
    "EngineVersion" : 1579795,
    "Description" : "Here I describe the capabilities of the plugin.",
    "Category" : "Bobs.Stand Alone",
    "CreatedBy" : "Bob Chatman",
    "CreatedByURL" : "http://gneu.org",
 
    "Modules" :
    [
        {
            "Name" : "StandAlone",
            "Type" : "Developer"
        } 
    ]
}


Note The "Type" parameter in the "Modules" section takes in the following values: "Developer", "Runtime", "Editor". All of these will generate an Editor DLL when compiled against the editor, but when you compile the plugin for a standalone game, make sure that your "Type" value is set to "Runtime" otherwise Unreal will not generate the Static.lib file needed by the standalone game.


The modules section accepts any number of entries, as a JSON array of objects. Name is the name of the module you are creating - this is likely to be same as the folder you put your module into. Type is one of three values, Developer, Runtime or Editor. Editor is loaded at editor load time, Runtime is loaded in all contexts, and Developer is loaded at any time where you are loading a Development build and never for Shipping builds. There is one final optional parameter to include, but it doesn't exactly mean much in a stand alone plugin. We will return to it in the next section.

With the descriptor in place, we can dive into the guts.

Note As with the content example, you are able to include a 128x128 px png to be loaded into the UI of the editor.

Create the following path: /Plugins/StandAlone/Source/StandAlone/

Within this directory you will begin working on your plugin. You will need a Build.cs file to declare dependencies, include paths or handle linking of an external library.

inside /Plugins/StandAlone/Source/StandAlone/StandAlone.Build.cs

using UnrealBuildTool;
using System.IO;
 
public class StandAlone : ModuleRules
{
    public StandAlone(TargetInfo Target)
    {
        PrivateIncludePaths.AddRange(new string[] { "StandAlone/Private" });
        PublicIncludePaths.AddRange(new string[] { "StandAlone/Public" });
 
        PublicDependencyModuleNames.AddRange(new string[] { "Engine", "Core" });
    }
}

Yep, at this point everything you see will be very similar to what you have already seen. I try to stick to the standard folder structure for my files, so I am following the coding guidelines that Epic has set out for us. In this directory you will want to create a Classes directory, for your UE4 related header files, and a Private folder to house your plugins implementations. There is no need for a public folder, as there is no public API to your plugin to be providing.

inside /Plugins/StandAlone/Source/StandAlone/Private/StandAlone.h

#pragma once
 
#include "ModuleManager.h"
 
class StandAloneImpl : public IModuleInterface
{
public:
	/** IModuleInterface implementation */
	void StartupModule();
	void ShutdownModule();
};

inside /Plugins/StandAlone/Source/StandAlone/Private/StandAlone.cpp

#include "StandAlonePrivatePCH.h"
 
#include "StandAlone.h"
 
void StandAloneImpl::StartupModule()
{
}
 
void StandAloneImpl::ShutdownModule()
{
}
 
IMPLEMENT_MODULE(StandAloneImpl, Module)

StandAlonePrivatePCH.h is an empty file, currently. It is there for you to stick your own PreCompiled Header references and include them in one lump, as you do with the MyProject.h file in your standard game.

The startup and shutdown module methods are available for you to be able to hook in and handle events that come with the loading of and unloading of the modules. This is likely a good place to handle opening or closing of data stores, handles and the like. I use this as the point when my V8 plugin is initialized to ensure that it is available globally.

Archive Manifest

  • Binaries/Win64/UE4Editor-StandAlone.dll
  • Resources/Icon128.png
  • StandAlone.uplugin

Non-Game Module

And finally, the pièce de résistance, a module exposing functionality. When this type of bundle comes into a party, everyone turns to look. There is one key element of this module, and that is the public facing interface and the importance of the load time. Everything else is as it was with a stand alone plugin. First, lets examine the addition to our plugin descriptor.

{
    "FileVersion" : 3,
 
    "FriendlyName" : "Bob's Module",
    "Version" : 1,
    "VersionName": "1.0",
    "EngineVersion" : 1579795,
    "Description" : "Here I describe the capabilities of the module.",
    "Category" : "Bobs.Module",
    "CreatedBy" : "Bob Chatman",
    "CreatedByURL" : "http://gneu.org",
    "CanContainContent" : "true",
 
    "Modules" :
    [
        {
            "Name" : "Module",
            "Type" : "Developer",
            "LoadingPhase" : "PreDefault"
        } 
    ]
}

The addition of the LoadingPhase allows our module to be loaded prior to the standard load time, which would allow any module that is loaded afterwards to be able to include it as a dependency. Let's look at what options we have for that.

Inside /Source/BobsPlayground/BobsPlayground.Build.cs

using UnrealBuildTool;
 
public class BobsPlayground : ModuleRules
{
    public BobsPlayground(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore"});
 
        PrivateDependencyModuleNames.AddRange(new string[] { "Module" });
 
        DynamicallyLoadedModuleNames.AddRange(new string[] { "StandAlone" });
    }
}

There are three noteworthy ways to declare a dependency. Public and Private dependencies are staticly linked into your project and visible to public and or private code, respectively. Public implies that you may also expose such functionality to whatever tools, editors or plugins are dependent on your game/module. It is also important to keep in mind that with the static linking, the header files are included. Dynamically loaded modules do not include the header files at link time, and instead should be treated as an external dll, loaded when needed. The key difference is that because of the static linking, if the module is missing your code will fail out. If you are using a dynamic link your code will be able to recover, in the event that the module is not found.

With this, all that remains is exposing our interface and writing a short test to confirm that it works. Create the public interface:/Plugins/Module/Source/Module/Public/IModule.h

Inside /Plugins/Module/Source/Module/Public/IModule.h

#pragma once
 
#include "ModuleManager.h"
 
/**
* The public interface to this module.  In most cases, this interface is only public to sibling modules
* within this plugin.
*/
class IModule : public IModuleInterface
{
 
public:
 
	/**
	* Singleton-like access to this module's interface.  This is just for convenience!
	* Beware of calling this during the shutdown phase, though.  Your module might have been unloaded already.
	*
	* @return Returns singleton instance, loading the module on demand if needed
	*/
	static inline IModule& Get()
	{
		return FModuleManager::LoadModuleChecked< IModule >("Module");
	}
 
	/**
	* Checks to see if this module is loaded and ready.  It is only valid to call Get() if IsAvailable() returns true.
	*
	* @return True if the module is loaded and ready to use
	*/
	static inline bool IsAvailable()
	{
		return FModuleManager::Get().IsModuleLoaded("Module");
	}
 
	virtual bool IsThisNumber42(int32 num) = 0;
};

There are two static methods, and an instance method to test that a number is 42. The two methods provide us the ability to 1) Confirm that the module is loaded and available, and 2) get a reference to the plugin to be referenced in our game/module. Note the use of a pure virtual function here. Unreal uses classes and multiple inheritance to provide the contract of an interface, but that doesn't mean you have to provide implementations for your functions/methods. I prefer to keep my interfaces pure virtual because it ensures that I have to implement methods.

Inside /Source/BobsPlayground/BobsPlayground.cpp

void FBobsPlaygroundModule::StartupModule()
{
	if (IModule::IsAvailable())
	{
		UE_LOG(BobsPlayground, Log, TEXT("%s"), IModule::Get().IsThisNumber42(42) ? TEXT("True") : TEXT("False"));
		UE_LOG(BobsPlayground, Log, TEXT("%s"), IModule::Get().IsThisNumber42(12) ? TEXT("True") : TEXT("False"));
	}
}

Lastly, we will need to define our module implementation, defining our pure virtual function above.

Inside /Plugins/Module/Source/Module/Private/Module.h

#pragma once
 
class ModuleImpl : public IModule
{
public:
	/** IModuleInterface implementation */
	void StartupModule();
	void ShutdownModule();
 
	bool IsThisNumber42(int32 num);
};

Inside /Plugins/Module/Source/Module/Private/Module.cpp

#include "ModulePrivatePCH.h"
 
#include "Module.h"
 
void ModuleImpl::StartupModule()
{
}
 
void ModuleImpl::ShutdownModule()
{
}
 
bool ModuleImpl::IsThisNumber42(int32 num)
{
	return num == 42;
}
 
IMPLEMENT_MODULE(ModuleImpl, Module)

Note the reference to the header here. It is convenient for a complicated plugin to include it because common header files are able to be used there.

Inside /Plugins/Module/Source/Module/Private/ModulePrivatePCH.h

#include "IModule.h"
 
// You should place include statements to your module's private header files here.  You only need to
// add includes for headers that are used in most of your module's source files though.

If you compile this out, drop a break point in the startmodule routine for your game you will be able to step through and see the something like the following output to your logs.

[2095.04.01-06.15.29:347][  0]BobsPlayground: True
[2095.04.01-06.15.30:290][  0]BobsPlayground: False

Archive Manifest

  • Binaries/Win64/UE4Editor-Module.dll
  • Source/Module/Public/IModule.h
  • Resources/Icon128.png
  • Module.uplugin

Distribution

Now that we have completely built a new bundle, the question is - how do we get it into the hands of a developer interested in its cause? Until the market place is here and we have firm details on EULAs and such, the following will be of great help.

We are going to create an archive, zip or 7zip if you wish. It is likely easier for you to make a zip as that is a default tool in the windows file explorer.

In each of the above sections an Archive Manifest section has been included, listing important or key files to be included for distribution.

Within each archive it is a good idea to include a Readme.md file to detail out the Installation, Contact and key elements of your bundle. This would also be a good place to include any licensing or changelog information that an interested party could review before installation.

Sample ReadMe.md

Installation
-------------
Unzip the package into the Plugins directory of your game. To add it as an engine plugin you will need to unzip the module into the plugin directory under where you installed UE4.


Contact
-------------
If you have any Questions, Comments, Bug reports or feature requests for this plugin, or you wish to contact me you can and should email me - me@myemail.com

More Information

If you are interested in the plugin system, its capabilites or the descriptor file standard, details can be found in the UE4 Documentation. There are a hundred examples you can pull from, included in the source, under the plugins directory of the UE4 project.

If you found this tutorial useful, you may also find the Static Linking Tutorial beneficial, as it walks through how to load and link a static library. I am using a derivative of these two as the base for my V8 Plugin.

You can read more about me on my User Page

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

An Introduction to UE4 Plugins 的相关文章

  • 通过wiki进行企业内部的知识共享

    其实企业内部的知识共享是一个很复杂的问题 每个人都有自己的经验和Key Knowledge 每次开发也能积累到很多有用的开发经验或者教训 可是怎样才能进行有效的知识共享呢 一个完善的知识共享系统应该具有以下几种特性 易于使用的界面 好的知识
  • Spring-AOP实践 - 统计访问时间

    公司的项目有的页面超级慢 20s以上 不知道用户会不会疯掉 于是老大说这个页面要性能优化 于是 首先就要搞清楚究竟是哪一步耗时太多 我采用spring aop来统计各个阶段的用时 其中计时器工具为StopWatch 文章结构 遇到的问题 创
  • unity期末个人作品-落笔洞寻宝探险之旅(寻宝游戏)

    落笔洞寻宝探险之旅 unity寻宝游戏 下载链接在文章下方 为了增添生活的乐趣开发的这款落笔洞寻宝游戏 主要内容为人物在落笔山脉寻找金币 右上角有金币计数器 找到所有金币则获胜 山中有障碍物 触碰会掉血50 人物生命值为100 血量为0则游
  • 将onnx的静态batch改为动态batch及修改输入输出层的名称

    文章目录 背景 操作 修改输入输出层 修改输入输出层名称 完整代码 背景 在模型的部署中 为了高效利用硬件算力 常常会需要将多个输入组成一个batch同时输入网络进行推理 这个batch的大小根据系统的负载或者摄像头的路数时刻在变化 因此网
  • 六边形地图生成(1)——基础地形

    看了大佬的六边形地图教程 跟着原教程敲了一遍代码 使用的引擎是unity 想把六边形地形的生成思路记录下来 1 基础六边形网格 基础网格很容易绘制 六个边缘点 一个中心点 如何在引擎中绘制动态网格网上一搜一大把 这里就不介绍了 2 边缘扰动
  • E:Package 'Vim' has no installation candidate问题解决

    不多说 直接上干货 问题描述 root zhouls virtual machine apt get install vim Reading package lists DoneBuilding dependency tree Readin
  • python中,获取字符串的长度

    说明 与其他的语言一样 有时候需要查看或者说计算字符串的长度 在此记录下python中通过哪个函数实现 操作过程 1 通过len 函数返回字符串的长度 gt gt gt text python gt gt gt len text 6 gt
  • SyntaxError: can't assign to operator

    变量名不能有
  • [学习笔记]Matlab(持续更新)

    文章目录 一 Matlab知识学习 1 输入输出语句 注意 Matlab中disp fprintf及sprintf三者之间的区别 2 exist函数的使用 3 matlab中的注释 4 几种常用的清除命令 5 MAT文件如何操作 6 dir
  • 8. UE4的盒体触发器和时间轴(制作感应门)

    一 盒体触发器 Box Trigger 1 创建一个盒体触发器 Box Trigger 拖动到地面上空 按End键 贴近地面 2 选中盒体触发器 在关卡蓝图中添加 On Actor Begin Overlap 事件 进入盒体触发器事件 a
  • tomcat如何配置context的docBase

    docbase是web应用和本地路径 path是tomcat访问这个应用的URL路径 Tomcat的项目部署方式有以下三种 1 直接把项目复制到Tomcat安装目录的webapps目录中 这是最简单的一种Tomcat项目部署的方法 也是初学
  • 使用Idea更新数据库表的数据

    tags IDEA 我们在做案例的时候 经常需要改变数据表中的数据来进行简单测试 那我们在Idea下是如何修改数据表的数据的呢 我们可以看下面的图片 只要选择updata就行了 后面再按自动提交的标志 如果您觉得这篇文章帮助到了您 可以给作
  • Selenium2+python自动化10-登录案例

    前言 前面几篇都是讲一些基础的定位方法 没具体的案例 小伙伴看起来比较枯燥 有不少小伙伴给小编提建议以后多出一些具体的案例 本篇就是拿部落论坛作为测试项目 写一个简单的登录测试脚本 在写登录脚本的时候呢 先要保证流程能跑起来 然后才是去想办
  • java.lang.IllegalAccessError: class javax.activation.SecuritySupport12 cannot access its superclass

    最近加入新的项目组 eclipse tomcat7 spring ibatis restful 遇到了这样的问题 说是不能访问父类 我一开始以为是版本的原因 但是久经更改 错误依然 实在累了 最终的解决办法是我把SecuritySuppor
  • Obsidian 入门使用手册

    文章目录 一 Obsidian 入门 1 1 什么是 Obsidian 1 2 安装 Obsidian 二 Obsidian 配置 2 1 创建第一个笔记 2 2 设置界面语言使用中文 2 3 主题 三 小结 一 Obsidian 入门 1
  • IntelliJ IDEA(Community版本)本地模式的下载、安装及其使用

    对于初学者来说可以先使用免费的社区版本练练手 ideaIC 2017 3 5 gt 社区版 ideaIU 2017 3 5 gt 旗舰版 一 IntelliJ IDEA Community版本 下载 下载链接 https www jetbr
  • Wave x Incredibuild

    Wave 公司简介 Wave 是一家虚拟娱乐公司 致力于帮助艺术家和粉丝通过协作创造出世界上最具互动性的现场表演体验 Wave 整合了最顶尖的现场音乐 游戏和广播技术 将现场音乐表演转化为沉浸式虚拟体验 便于观众通过 YouTube Twi
  • Unity3d 插件 系列——DoTweenPro介绍(图文详细+案例)

    Unity3d 插件 系列 DoTweenPro介绍 图文详细 案例 前言 一 DoTweenPro简介 二 DoTweenPro安装 三 DoTweenPro主要组件 1 DoTweenAnimation 2 DoTweenPath 3
  • 解决:Java source1.5不支持diamond运算符,请使用source 7或更高版本以启用diamond运算符

    Maven默认用的是JDK1 5去编译 diamond运算符 指的是JDK1 7的一个新特性 List
  • mac下搭建cocos2d-x3.2开发环境

    1 软件 Xcode Ant apache ant 1 9 4 bin tar gz Jdk jdk 8u45 macosx x64 dmg 有的mac系统上没有自带 Ndk android ndk r10d darwin x86 64 b

随机推荐

  • C++ 随机数的制作

    include
  • Spring security安全登录-当AJAX遇上Redirect

    前言 最近做平台引入spring security做为安全认证框架 在登录的时候使用的ajax的请求方式 最开始的做法是调用登录的接口 成功后再前端使用window location href index html的方式跳转到希望的页面 考
  • kali linux 2020.4 自带浏览器英文改中文

    刚开始用kali linux 可能一些伙伴也会像我一样遇到英文不通的情况 比如 系统自带的火狐浏览器是英文的 要变成中文直接敲入 sudo apt install firefox esr l10n zh cn y 然后重启一下火狐浏览器就可
  • 【Unity+MySQL】实现简单的注册登录系统

    目录 1 安装Unity引擎和Navicat软件 2 安装MySQL8 0数据库 2 1 下载msi文件 2 2 安装MySQL Server 8 0 2 3 配置环境变量 2 4 安装MySQL服务 2 5 开启MySQL服务 2 6 修
  • 软件外包开发项目管理工具

    随着软件项目的规模越做越大 项目管理人员需要使用工具管理项目进度 从而更有成效的管理好软件开发进度 软件开发的进度管理工具有很多 今天和大家分享一些常用的系统工具 希望对大家有所帮助 北京木奇移动技术有限公司 专业的软件外包开发公司 欢迎交
  • Hololens 学习-----1

    ww 学习资料 基本操作 链接 https learn microsoft com zh cn hololens hololens2 basic usage 链接 https learn microsoft com zh cn window
  • Java中Collection集合和Map集合详解(进阶三)

    目录 友情提醒 第一部分 单列集合 第一章 单列集合体系 Collection接口 1 1 单列集合是什么 与数组的区别在哪 1 2 单列集合体系与分类 第二章 单例集合体系Collection下的List接口 Set接口 2 0 List
  • JAVA随机生成十个不重复的整数(Arraylist,Set)

    随机生成十个不重复的整数有许多方法 这里我只写出两种 第一种 Set 先上代码 import java util HashSet import java util Set public class Demo01 public static
  • (Java)leetcode-337 House Robber III(打家劫舍III)

    题目描述 在上次打劫完一条街道之后和一圈房屋后 小偷又发现了一个新的可行窃的地区 这个地区只有一个入口 我们称之为 根 除了 根 之外 每栋房子有且只有一个 父 房子与之相连 一番侦察之后 聪明的小偷意识到 这个地方的所有房屋的排列类似于一
  • CAN芯片_ TJA1051T/3

    前不久画了块板子 STM32F407VET6加CAN芯片的 如下图 这个电路是从正点原子抄过来的 但是板子打出来发现用不了 换上正点原子STM32F429开发板上的CAN芯片后就能正常工作了 仔细观察后发现两个芯片不太一样 我们买的是TJA
  • Windows 10 安装 PostgreSQL 12.x 报错 ‘psql‘ 不是内部或外部命令 & 由于找不到文件libintl-9.dll等问题

    目录 序言 一 问题总结 问题 1 psql 不是内部或外部命令 也不是可运行的程序或批处理文件 问题 2 由于找不到文件libintl 9 dll 无法继续执行代码 重新安装程序可能会解决此问题 1 卸载 2 安装 3 安装 Stack
  • 8年经验之谈 —— 35岁以上的测试开发工程师都去哪里了?

    测试开发工程师就是吃青春饭 35岁就是测试开发工程师的天花板 没有工作机会了 测试开发工程师趁早转行 不然迟早失业 网上对测试开发工程师不友好的言论非常多 真的是这样吗 如果不是这样 那么35岁以上的测试开发工程师去哪里了呢 行业内转岗 一
  • 一篇搞定pandas语法,建议收藏

    导语 如果说大数据里面hive是屠龙刀 那么pandas则是倚天剑 帮助我们对数据数据挖掘 数据分析 数据清洗 本篇介绍了Pandas 一些基础的语法 以及使用技巧 建议收藏 目录 数据准备 Dataframe 基础操作 2 1 查看 2
  • Android App保活的方式

    背景 在Android系统中 当应用程序进入后台或者被用户关闭后 系统会自动回收该应用程序的资源 以达到优化系统性能的目的 但是 有些应用程序需要在后台长时间运行 比如音乐播放器 即时通讯等 这时就需要使用一些技术手段来保持应用程序的运行状
  • JAVA实现文件上传

    利用JAVA实现文件上传 Demo01 servlet下的图片上传功能 前端代码 upload html h3 文件上传 h3
  • C#中按位与,按位或

    在工作中遇到按位或组合权限串 一直不是特别明白 今天终于花了半个下午的时间搞明白其中的道理 首先每一个权限数都是2的N次方数 如 k1 2 添加 k2 4 删除 k3 8 修改 如此定义功能权限数 当需要组合权限时 就需要对各个所拥有的权限
  • JavaScript中使用画布实现笑脸火柴人

    在这之前 根本不知道JavaScript具体到底有多重要 现在才明白JavaScript也很强大 从网上看了几个js写的网页小游戏 我都惊呆了 以后一定要好好学习js
  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • 数据可视化 第4章

    第4章 添加表格QTableView 1 添加table model py 里面子类化QAbstractTableModel 实现自定义table model from PySide2 QtCore import Qt QAbstractT
  • An Introduction to UE4 Plugins

    An Introduction to UE4 Plugins Rate this Article 3 67 3 votes Approved for Versions 4 2 4 3 4 4 4 5 Contents hide