[{"data":1,"prerenderedAt":180},["ShallowReactive",2],{"\u002F2018-07-28-ue4-tick-note":3},{"id":4,"title":5,"body":6,"date":156,"description":12,"extension":157,"meta":158,"navigation":161,"path":173,"seo":174,"stem":175,"tags":176,"__hash__":179},"blogs\u002F_legacy\u002F2018\u002F2018-07-28-ue4-tick-note.md","UE4中Tick使用小结",{"type":7,"value":8,"toc":143},"minimark",[9,13,16,20,23,26,29,32,36,39,42,45,48,52,55,58,63,66,69,72,76,79,82,93,96,100,103,107,110,113,116,122,125,131,134,140],[10,11,12],"p",{},"Tick在UE4的逻辑中是最基本的单元之一，不过也有些地方需要注意的。",[10,14,15],{},"当前使用的UE4版本为4.18。",[17,18,19],"h2",{"id":19},"并行",[10,21,22],{},"Tick是可以打开并行的，对于一些和主要逻辑没有耦合的逻辑，可以打开该Object的并行Tick：bRunOnAnyThread来进行运行优化。",[10,24,25],{},"实际并行的执行方式可以到FTickTaskSequencer::ReleaseTickGroup中去查看。",[10,27,28],{},"并行只在TickGroup内部执行，但是要小心多线程同步问题，考虑到加锁的成本，还是只对独立的逻辑进行异步比较好。",[10,30,31],{},"在优化上，还有一个bAllowTickOnDedicatedServer的选项，不过具体与使用_Server宏来屏蔽代码相比哪个更好些并没有测试过~",[17,33,35],{"id":34},"actualtickgroup","ActualTickGroup",[10,37,38],{},"每个TickFunc都可以指定TickGroup，但是这个TickGroup并不代表最终实际执行的TickGroup。",[10,40,41],{},"根据每个Tick注册的Prerequisite不同，Tick的执行Group会被延迟。",[10,43,44],{},"例如，如果TickFunc要求的Prerequisite是在PostPhiscs中的，那么即便它自己是注册为PrePhyiscs，也会被推迟到Post才能执行。",[10,46,47],{},"这个时候可以看到TickFunc的ActualStartTickGroup会变成实际的Tick执行组。",[17,49,51],{"id":50},"自定义tick","自定义Tick",[10,53,54],{},"可以通过自定义TickFunc来构建自己的Tick逻辑，相比TimerManager最大的优势就是这样可以在原有的Tick之外获得自己需要的逻辑执行时间。",[10,56,57],{},"引擎内部有一些额外定义的TickFunc，以前似乎是有SecondaryTick的，不过后来弃用了。",[59,60,62],"h3",{"id":61},"uworld","UWorld",[10,64,65],{},"作为PhsxScene的维护者，拥有额外的三个TickFunc：FStartPhysicsTickFunction、FEndPhysicsTickFunction、FStartAsyncSimulationFunction。",[10,67,68],{},"都是用于对物理世界进行操作的Tick，其中StartAsyncSimulation是用于cloth的模拟的，注册在EndPhysicsTickFunction之后。而StartPysics是用于启动物理模拟，EndPhysics则是物理模拟结束的。",[10,70,71],{},"所以如果要保证物理处理已经完成，最好是注册到PostPhysics。",[59,73,75],{"id":74},"uskeletalmeshcomponent","USkeletalMeshComponent",[10,77,78],{},"FSkeletalMeshComponentEndPhysicsTickFunction是注册在EndPhysics的，用于骨骼动画的状态同步等操作，没有仔细的看过，详情参考USkeletalMeshComponent::EndPhysicsTickComponent。",[10,80,81],{},"这个Tick是要求在关卡完成物理结算之后的：",[83,84,89],"pre",{"className":85,"code":87,"language":88},[86],"language-text","EndPhysicsTickFunction.AddPrerequisite(World, World->EndPhysicsTickFunction);\n","text",[90,91,87],"code",{"__ignoreMap":92},"",[10,94,95],{},"FSkeletalMeshComponentClothTickFunction则是负责对Cloth进行更新的，它被添加到了SkeletalMesh的EndPhysicsTickFunction之后，保证物理更新完成之后再进行衣服的演算更新。",[59,97,99],{"id":98},"ucharactermovmentcomponent","UCharacterMovmentComponent",[10,101,102],{},"FCharacterMovementComponentPostPhysicsTickFunction这个是在角色移动中，执行PostPhysicsTickComponent，当bDeferUpdateBasedMovement打开了的话，会在这里进行一次移动更新。",[59,104,106],{"id":105},"uprimitivecomponent","UPrimitiveComponent",[10,108,109],{},"FPrimitiveComponentPostPhysicsTickFunction，这个是用来执行每个Component的PostPhysicsTick的，按照官方注释已经弃用。",[59,111,112],{"id":112},"自定义",[10,114,115],{},"参照上面的TickFunc的用法，自定义比较简单",[83,117,120],{"className":118,"code":119,"language":88},[86],"USTRUCT()\nstruct FMyCustomTick : public FTickFunction\n{\n  GENERATED_USTRUCT_BODY()\n\n  class UVehicleSyncComponent*    Target;\n\n  FMyCustomTick();\n\n  virtual void ExecuteTick(float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) override;\n  \u002F** Abstract function to describe this tick. Used to print messages about illegal cycles in the dependency graph **\u002F\n  virtual FString DiagnosticMessage() override;\n};\n\ntemplate\u003C>\nstruct TStructOpsTypeTraits\u003CFMyCustomTick> : public TStructOpsTypeTraitsBase2\u003CFMyCustomTick>\n{\n  enum\n  {\n    WithCopy = false\n  };\n};\n",[90,121,119],{"__ignoreMap":92},[10,123,124],{},"其中，下面的宏是必须的，否则会导致编译出错。因为TickFunc是不允许复制的。之后再对函数进行实现：",[83,126,129],{"className":127,"code":128,"language":88},[86],"FMyCustomTick::FMyCustomTick()\n{\n  TickGroup = ETickingGroup::TG_PostPhysics;\n  bCanEverTick = true;\n}\n\nvoid FMyCustomTick::ExecuteTick(float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent)\n{\n  FActorComponentTickFunction::ExecuteTickHelper(Target, \u002F*bTickInEditor=*\u002F false, DeltaTime, TickType, [this](float DilatedTime) { Target->PostPhysicsTick(*this); });\n}\n\nFString FMyCustomTick::DiagnosticMessage()\n{\n  return Target->GetFullName() + TEXT(\"[UMyComp::PostPhysxTick]\");\n}\n",[90,130,128],{"__ignoreMap":92},[10,132,133],{},"对于Component，定义了FMyCustomTick的变量PostPhysxComponentTick之后，在其Tick注册函数RegisterComponentTickFunctions中继续注册就可以了，可以使用的帮助函数SetupActorComponentTickFunction来进行注册，以及注意解注册：",[83,135,138],{"className":136,"code":137,"language":88},[86],"if (bRegister)\n{\n  if (SetupActorComponentTickFunction(&PostPhysxComponentTick))\n  {\n    PostPhysxComponentTick.Target = this;\n\n    UWorld* World = GetWorld();\n    if (World != nullptr)\n    {\n      PostPhysxComponentTick.AddPrerequisite(World, World->EndPhysicsTickFunction);\n    }\n  }\n}\nelse\n{\n  if (PostPhysxComponentTick.IsTickFunctionRegistered())\n  {\n    PostPhysxComponentTick.UnRegisterTickFunction();\n  }\n}\n",[90,139,137],{"__ignoreMap":92},[10,141,142],{},"TickFunc的自定义还是比较简单的 ，不明白的地方可以参考上面那些引擎内部用法。",{"title":92,"searchDepth":144,"depth":145,"links":146},2,3,[147,148,149],{"id":19,"depth":144,"text":19},{"id":34,"depth":144,"text":35},{"id":50,"depth":144,"text":51,"children":150},[151,152,153,154,155],{"id":61,"depth":145,"text":62},{"id":74,"depth":145,"text":75},{"id":98,"depth":145,"text":99},{"id":105,"depth":145,"text":106},{"id":112,"depth":145,"text":112},"2018-07-28","md",{"layout":159,"status":160,"published":161,"author":162,"author_login":164,"author_email":165,"wordpress_id":166,"wordpress_url":167,"date_gmt":168,"excerpt":169},"post","publish",true,{"display_name":163,"login":164,"email":165,"url":92},"风铃","flinkor","flinkor@foxmail.com",2409,"\u002F?p=2409","2018-07-28 02:03:37 +0000",{"type":7,"value":170},[171],[10,172,12],{},"\u002F2018-07-28-ue4-tick-note",{"title":5,"description":12},"_legacy\u002F2018\u002F2018-07-28-ue4-tick-note",[177,178],"UE4","Tick","WcoVUqA7rnnKC0CuEd2pU1q4cND6cJ72eY60f8a31Hc",1788763179127]