[UE]InputSystem基础框架
InputSystem基础框架
Key
flowchart LR
Input(PlayerController::UpdateInput)
Input
-->InputProcesssor::Tick
Input
-->InputHandle::Tick
Input
-->InputCollector::Tick
InputProcessor
对于 InputProcessor,进行按键的原始输入处理,调用 InputKey 将将数据传递到 InputCollector,继续后续的操作;
通过监听引擎原始的按键数据 APlayerController::IsInputKeyDown(const FKey Key);
允许外部调用输入,执行 InputKey (比如某个 UI 点击触发输入);
特别地,在 Tick 中进行原始数据处理;
由于一般按键输入支持 Ctrl / Shit / Alt / Cmd + Key,需要对这种情况适配,同时防止按键冲突:对于KeySetting(KeyType - 具体按键配置 映射) 额外维护 bCtrl (需要与 ctrl 组合)、Must ...
[UE]CharacterMovement源码浅析
CharacterMovement源码浅析
Base
classDiagram
direction LR
class UMovementComponent {
UpdatedComponent : TObjectPtr~USceneComponent~ (处理空间位置)
UpdatedPrimitive : TObjectPtr~UPrimitiveComponent~ (处理渲染物理)
}
%% -------------
UMovementComponentCheckJumpInput
-.->ScaleInputAcceleration
-.->ComputeAnalogInputModifier
ControlledCharacterMove
-->|ROLE_Authority|PerformMovement
-->Start(StartNewPhysics)
ControlledCharacterMove
-->|ROLE_AutonomousProxy & IsClient|ReplicateMoveToServer
Start-->MOV ...
[UE]ToString解决方案
ToString解决方案
背景
提供一个通用机制 UStringUtils::ToString(Value) 将其 String 化。
其中 Value 包括:
Base:基础类型(int、bool、float、FString 等);
Enum;
包含 ToString 或 GetUID 方法的类型、指针;
Pointer:TStrongPtr、TShaerdPtr、TWeakPtr、TUniquePtr;
Variant;
Container:包括 Array、Set、Map 等;
实现
基础类型
123456789101112131415161718192021222324252627282930313233343536template<typename T>static typename TEnableIf<TIsIntegral<T>::Value, FString>::Type ToString(const T& Value){ return FString::FromInt(static_cast<int ...
[UE]UnLua & C++ 交互
UnLua & C++ 交互
在 Lua 中调用一般的 UFUNCTION 反射比较简单直接,这里以从 Lua 中调用 CFUNCTION 为例简单介绍两端交互。
具体为在 Lua 中的调用:local Table = UE4.UTestUtils.LuaCFunction(Val0, Val1),并返回一个 Lua Table : { "Val0" = Val0, "Val1" = Va1 }。
定义
首先通过 ADD_STATIC_CFUNCTION 静态导出这个原生的 FGlueFunction ;
具体的实现可以在 UnLuaEx.h 中找到。
1234567891011// Test.hstruct lua_State;UCLASS()class UTestUtils : public UBlueprintFunctionLibrary{ GENERATED_BODY()public: static int LuaCFunction(lua_State* L);}
12345// Test ...
[UE]PlayerInfo高频同步解决方案
PlayerInfo高频同步解决方案
描述
需求目的
分析一个常见的需求: “在 1P 客户端显示 3P 的 Transform ”。
显然,在客户端存在 3P 的 Pawn 时,可以直接取 Pawn 的 Transform;但出于性能考虑,会进行各种 AOI 机制,在较远距离时客户端会将 3P 的 Pawn 裁剪掉,只留下 PlayerState(或者某个不被剪裁的数据 Channel) 用于同步。
一个直观的想法是将 Transform 直接通过对应的 PlayerState 属性同步给所有客户端;但出于性能考虑,对于同步一般会开启 PushModel;这种高频字段会频繁将 PlayerState 对应 ActorChannel 给 MarkDirty,导致 PushModel 功能基本失效,频繁进行同步的 Diff 等大开销的操作;
所以需要一个机制对这种情况进行优化。
核心思路
对于 DS,创建一个 Channel 专门用于同步 Player 的高频变化信息,如 Location、Rotation 等;
对于同步的信息,进行适当的同步降频(不需要每帧同步)、字节压缩(舍弃部分精 ...
ACT浅思
ACT浅思
ACT 表现
动作
动作节奏:
flowchart LR
前摇--->攻击判定--->后摇-->后摇-可打断
需要控制好每个阶段的时间分配,表现不同的节奏;
较长的后摇可以方便玩家明确下一步操作(不攻击、打断后摇继续攻击),判定更明确;
较短的后摇可以增加动作连续性连续,提升手感;
动画配合:
动画曲线配合:从动画中提取曲线,配合曲线调整位移;比如移动,需要在脚落下的那一刻位移速度最大,其余阶段几乎不位移;
攻击方、受击方动画、位移需要匹配;
动作设计:
Anticipation & Follow Through:预期、跟随;在确定性的时间做更多奖励性的动作演出,此时玩家会更加专注,比如支援突击等玩家主动触发的明确时刻;利用跟随增强动画流畅感和力量感,比如格挡时的强化慢镜头,利用一些跟随,同时提供反应时间;再比如局外人物展示界面,在结束阶段利用 衣物飘带、尾巴 等动力学变化强化演出效果;
Slow In / Slow Out:慢入、快速表演、慢出;同时可以增加蓄力抖动等加强压迫感;
Exaggeration & Strong Posing: ...
[UE]Networking源码浅析
Networking源码浅析
定义
Bunch:表示一组相关的网络数据,包含 RPC / 属性同步 等信息,UE 中 DS/Client 通信的基本单位。
Packet:UDP 的基本传输单位,可以打包一个或多个 Bunch,在接受端进行解析。
NetDriver:管理网络通信,比如管理连接、处理数据包的发送和接收、处理网络事件。
NetConnection:表示一个网络连接,与一个 NetDriver 关联,并通过 NetDriver 进行实际的网络通信。
Channel:管理网络传输,进行数据分类,提供 SendBunch、ReceivedRawBunch 方法,由 NetConnection 管理,一个 NetConnection 可以包含多种 Channel。
FObjectReplicator:处理对象的网络同步,保存属性快照,进行状态改变发送、更新同步状态、接受与发送消息。
ActorChannel:关联特定的 Actor 负责其同步,包含多个 FObjectReplicator 用于复制其 Actor、ActorComponent 。
FRepLayout:管理复制的 ...
[UE]弱网工具Clumsy的使用
弱网工具Clumsy的使用
Clumsy 用于弱网测试时,进行本地弱网环境的模拟,基于 WinDivert 实现,可以出模拟延迟、丢包等网络状态。
Downloads
下载地址:Clumsy;官方文档:Clumsy Manual
下载后的几个重点文件:
打开 Clumsy.exe 可以看到以下内容:
可以看出这里有几个重点的 Function,一般重点使用 Lag 延迟、Drop 丢包。
在 Filtering 填入对应的 Command 后,设置 Functions,点击 Start 即可开始模拟。
同时可以在 Config.txt 中,预设一些 Presets 方便下次使用。
UE DS 中的使用
对于 UE的 DS 环境,首先为了具体到某一个 Client / DS,采用 Filter Port 的机制,对某个具体的端口号进行操作。
用 netstat -aon\Findstr 进程ID,查询 DS/Client 进程,通过 UDP 进行链接。
DS 的 port 一般可以在启动命令中找到 -port=17777;
Client 的 port 可以在 DS 的 Log 中, ...
[UE]夺旗模式框架
夺旗模式框架
描述
夺旗模式:
场景里会按照一定的规则刷新出不同类型的旗帜(不同类型的旗帜有不同的得分、血量、表现等);
玩家会被分成若干个队伍,抢夺刷新出来的旗帜,将旗帜带到自己队伍目标点进行销毁,则可以获得分数;
玩家持有旗帜时,旗帜可能会掉落或被抢夺:被其它玩家撞击到则旗帜被抢夺到其它玩家身上;旗帜的血量归零则会掉落回场景;
有正式赛与加时赛两种类型的比赛,首先会开启正式赛;对于正式赛,率先达到目标分的队伍获胜;如果平局则开启加时赛,否则进行结算;对于加时赛,率先得分的队伍获胜,如果平局则以两队平局进行结算;
要点总结:
旗帜实体:旗帜本身有自己的类型、得分、血量;
旗帜刷新:场景内根据一定规则(倒计时刷新、旗子上缴)会刷出不同类型旗帜;
旗帜传递:玩家可以拾取场景里的旗帜、相互抢夺旗帜、掉落旗帜(持有旗帜血量归零)、将旗帜送给终点得分等;玩家可以组队,共享队伍得分;同队伍之间的玩家可以传递旗帜;
单局流程:所有玩家就绪分队后,传送到起始点准备开赛;如果一局比赛平分,一定条件下可以触发下一场比赛继续;
模式基础
单局流程
首先,一个完整的夺旗赛,由若干个子比赛构成,子比赛 ...
[UE]CommonParams解决方案
CommonParams解决方案
在实现业务框架的时候,经常需要支持传参的功能(比如 Buff 系统中,AddBuff 的时候,通常需要支持外部传入一个 BuffParams ,在内部解析出各种 Param 使用。)
这个参数需要支持基本的数据保存、同步等。
初始的想法
一个最简单的想法,是打包一个结构体,支持各种类型的传入,比如:
12345678910USTRUCT()struct Params{ UPROPERTY() uint64 uVar0; UPROPERTY() int iVar0; UPROPERTY() float fVar0;}
这样虽然很简单,同时可以通过反射来同步。
但是有一个巨大的问题,那就是在解析参数的时候,只知道 Var0 这种没有名字的抽象的概念,使用者需要记住 Var0 对应的是什么数据,很不直观。
CommonVariantParams
维护一个 CommonVariantParams,通过 TMap <FString, FVariant> ValueMap 来保存数据。
为了方便使 ...