BlueRose
文章92
标签23
分类7
GAS中的传递数据与解耦方法

GAS中的传递数据与解耦方法

一种将所有逻辑都写进Ability的GAS Combo方案

一种将所有逻辑都写进Ability的GAS Combo方案

前言

使用GAS实现Combo技能,本人所知道的有两种思路:

第一种:为每一段Combo创建一个单独的Ability;定制自定义Asset与编辑器,之后再通过自定义编辑器进行编辑。

  • 优点:最高的自由度,不容易出问题。
  • 缺点:如果有大量多段或者派生复杂的Combo,那工作量将会相当爆炸。可以说除了工程量大,管理麻烦没有别的缺点。

第二种:根据GameplayEvent直接在Ability里直接实现Combo切换逻辑

https://zhuanlan.zhihu.com/p/131381892

在此文中,我分析了ActionRPG的攻击逻辑的同时自己也提出一种通过GameplayEvent实现Combat的方法。这个方法理论上没问题,但实际落地的时候发现存在一个问题:里面使用的PlayMontageAndWaitEvent是GameplayTasks是异步运行的,而通过AnimNotify发送的SendGameplayEvent的函数确是同步函数。所以会导致PlayMontageAndWaitEvent节点接收不到任何事件的问题。经过一段事件的探索,本人摸索到了另一种方案:

  • 优点:一个起点(这个Combo树)一个Ability,方便管理。可以尽可能地把Combo相关的逻辑都整合到一个Ability里。
  • 缺点:自由度会有一定的限制;因为采用异步函数来管理事件,会导致一定的延迟。不适于格斗游戏这种对低延迟要求比较高项目。

2021.7.30更新

如果你使用GAS的输入绑定系统,即在GiveAbility()注册时进行输入绑定(参考GASDocument的4.6.2章节)。可将后面介绍的ListenPlayerInputAction节点换成GAS自带的WaitInputPress或WaitInputRelease。

在联机项目中使用GAS的注意点

在联机项目中使用GAS的注意点

前言

大多数人应该是会通过学习UE4的ActionRPG项目来入门GAS框架的。但在最近自己做Demo的过程中才发现里面的部分不适用网络联机。比如ActionRPG将Character与Controller的指针存在GameMode,因为Server与Client只有一个GameMode的关系,就不符合多人联机游戏的规则。所以在经过实践之后这里我分享一些要点仅供抛砖引玉。这里我再推荐各位读者去看一下GASDocument以及附带的工程,它展现了正确的设计思路。

Slate学习笔记(一):Slate动态控制与其他技巧

Slate学习笔记(一):Slate动态控制与其他技巧

前言

最近在写MessageBox控件,想兼容UMG与c++中调用Slate。略有心得,遂有此文。

为Qt中的SQLite添加密码并加密

为Qt中的SQLite添加密码并加密

前言

因为Sqlite的源代码中只提供了Sqlite3_key()的接口,没有实现。所以Qt中的Sqlite没有密码功能。于是我找了一下资料,,并且总结一下思路。现成的方法在最后。

在Ue4中实现对二次元模型进行透视校正

在Ue4中实现对二次元模型进行透视校正

前言

之前想使用UE4实现IOchair通过Blender晶格变形,实现的二次元角色面部透视矫正效果。在使用HLSL写了1/3晶格效果和IOchair沟通后,才发现这个功能只需要通过在摄像机坐标系下调整模型顶点的Z值即可。但要在Ue4的材质编辑器中实现这个功能就必须知道Ue4的VertexShader处理过程,于是我花了些时间研究了一下。

效果实现思路
一句话解释就是在模型的顶点坐标转换到摄像机坐标后,在乘以投影矩阵前对其Z值进行调整,以实现纸片人的效果。

image

参考了以下这篇文章:
https://zhuanlan.zhihu.com/p/268433650?utm_source=ZHShareTargetIDMore

UE4剖切效果实现

UE4剖切效果实现

前言

思路是使用平面方程来判断模型裁切,之后在另一面使用UnLit的自发光材质显示剖面。但Ue4的BlendingMaterialAttributes不能指定UnLit作为ShaderModel。所以可以使用我之前开发的多Pass插件搞定。

UE4.25传统渲染方式的代码迁移指南

UE4.25传统渲染方式的代码迁移指南

前言

4.25的GlobalShader的调用代码发生了一下变化,我在写完RDG例子后顺便写了一下GlobalShader的使用案例。具体的可以参考我的插件:

https://github.com/blueroseslol/BRPlugins

代码位于SimpleGlobalShader.cpp中。

变量使用LAYOUT_FIELD宏进行包裹

对于新定义用于设置变量的GlobalShader基类使用,需要使用DECLARE_INLINE_TYPE_LAYOUT(FYourShaderName,NonVirtual)宏进行声明。另外还有DECLARE_TYPE_LAYOUT(FYourShaderName,NonVirtual)宏,不太清楚差别,但作用应该是一样的。

除此之外还有

class FSimpleGlobalShader : public FGlobalShader
{
    DECLARE_INLINE_TYPE_LAYOUT(FSimpleGlobalShader, NonVirtual);
public:
    static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
    {
        return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
    }

    static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
    {
        FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
        OutEnvironment.SetDefine(TEXT("TEST_MICRO"), 1);  
    }

    FSimpleGlobalShader(){}

    FSimpleGlobalShader(const ShaderMetaType::CompiledShaderInitializerType& Initializer):FGlobalShader(Initializer)
    {
         SimpleColorVal.Bind(Initializer.ParameterMap, TEXT("SimpleColor")); 
         TextureVal.Bind(Initializer.ParameterMap, TEXT("TextureVal"));
         TextureSampler.Bind(Initializer.ParameterMap, TEXT("TextureSampler"));
    }

    template<typename TRHIShader>
    void SetParameters(FRHICommandList& RHICmdList,TRHIShader* ShaderRHI,const FLinearColor &MyColor, FTexture2DRHIRef InInputTexture)
    {
        SetShaderValue(RHICmdList, ShaderRHI, SimpleColorVal, MyColor); 
        SetTextureParameter(RHICmdList, ShaderRHI, TextureVal, TextureSampler,TStaticSamplerState<SF_Trilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), InInputTexture);
    }

private:
    LAYOUT_FIELD(FShaderResourceParameter, TextureVal);
    LAYOUT_FIELD(FShaderResourceParameter, TextureSampler);
    LAYOUT_FIELD(FShaderParameter, SimpleColorVal);
};

第二个形参视类内是否有虚函数,选择Abstract或者NonVirtual。源代码里基本上都是使用NonVirtual的。

另一个不常用的宏是DECLARE_EXPORTED_TYPE_LAYOUT(FYourShaderName, YOUR_API, Virtual),它用于声明需要被其他类继承的基类。具体的使用方法还请参照UE4源码。

Shader变量需要使用LAYOUT_FIELD宏进行包裹,第一个形参为类型,普通类型声明为FShaderParameter,Texture2d与Sampler声明为FShaderResourceParameter。例如:

LAYOUT_FIELD(FShaderParameter, SimpleColorVal);
LAYOUT_FIELD(FShaderResourceParameter, TextureVal);    
LAYOUT_FIELD(FShaderResourceParameter, TextureSampler);

Shader声明改变

声明宏由DECLARE_SHADER_TYPE(FSimplePixelShader, Global)转变为DECLARE_GLOBAL_SHADER(FSimplePixelShader)。

去除序列化相关函数

去掉virtual bool Serialize(FArchive& Ar) override函数。

LAYOUT_FIELD宏会实现这部分功能。

FImageWriteTask

FImageWriteTask现在接受TArray64的数据。而不是 TArray。如果你想传递TArray数据,可以这么写:

TArray<FColor> OutBMP;
// Fill OutBMP somehow
TUniquePtr<TImagePixelData<FColor>> PixelData = MakeUnique<TImagePixelData<FColor>>(DestSize);
PixelData->Pixels = OutBMP;
ImageTask->PixelData = MoveTemp(PixelData);
RenderDependencyGraph学习笔记(三)——在插件中使用PixelShader

RenderDependencyGraph学习笔记(三)——在插件中使用PixelShader

前言

在插件中使用RDG调用ComputeShader的方法,我花了没几天就搞定了。但PixelShader相对来说就麻烦了,怎么搞都没有绘制到RT上。最后还是通过改写DrawFullscreenPixelShader的代码搞定了。

另外说一下PixelShader的调用和传统的GlobalShader调用很相似。

RenderDependencyGraph学习笔记(二)——在插件中使用ComputeShader

RenderDependencyGraph学习笔记(二)——在插件中使用ComputeShader

前言

UE4 RDG(RenderDependencyGraph)渲染框架本质上是在原有渲染框架上基础上进行再次封装,它主要的设计目的就为了更好的管理每个资源的生命周期。同时Ue4的渲染管线已经都替换成了RDG框架了(但依然有很多非重要模块以及第三方插件没有替换),所以掌握以下RDG框架还是十分有必要的。

上一篇文章已经大致介绍了RDG框架的使用方法。看了前文的资料与官方的ppt,再看一下渲染管线的的代码基本就可以上手了写Shader。但作为一个工作与Ue4一点关系的业余爱好者,用的2014年的电脑通过修改渲染管线的方式来写Shader不太现实,编译一次3小时真心伤不起。同时google与Epic论坛也没有在插件中使用RDG的资料,所以我就花了些时间探索了一下用法,最后写了本文。因为非全职开发UE4,时间精力有限,不可避免得会有些错误,还请见谅。 代码写在我的插件里,如果感觉有用麻烦Star一下。位于在Rendering下的SimpleRDG.cpp与SimpleRenderingExample.h中。

https://github.com/blueroseslol/BRPlugins

首先还是从ComputeShader开始,因为比较简单。