皮皮网

【lol瞎子连招源码】【ios猜拳源码】【ramfs 源码分析】虚化4.26源码_虚化模拟

来源:如何自制指标源码 时间:2024-12-23 21:52:35

1.UE4-Slate源码学习(二)slate事件触发
2.UE4.26(5.0)后的虚化虚化Sequence系统
3.Ubuntu20.04源码编译CARLA0.9.14全过程记录
4.UE4-Slate源码学习(四)FSceneViewport
5.UE4 LevelSequence源码解析
6.UE 八叉树Octree2源码分析

虚化4.26源码_虚化模拟

UE4-Slate源码学习(二)slate事件触发

       在探讨UE4-Slate源码学习中,首先进入概念理解阶段,源码虚拟触摸的模拟开启会将鼠标左键操作转化为OnTouchStarted事件,使得编辑器下通过鼠标也能触发UI的虚化虚化触摸相关事件。实现这一功能的源码关键在于

       FSlateApplication类中两个方法:IsFakingTouchEvents()用于判断是否开启虚拟触摸,SetGameIsFakingTouchEvents()用于设置虚拟触摸状态。模拟lol瞎子连招源码

       在平台调用Slate时,虚化虚化根据不同事件类型创建FPointerEvent对象,源码作为事件处理的模拟载体,其包含触发事件的虚化虚化按键信息、鼠标位置、源码索引、模拟是虚化虚化否为触摸事件等数据,用于后续事件的源码精确处理。

       Slate用户类FSlateUser包含了索引、模拟鼠标位置、聚焦对象、捕获状态和WidgetPath等信息,通过实例化多个FSlateUser对象,程序可以追踪多个用户输入,例如在多人游戏场景中,能够精准识别当前谁触发了A键。

       聚焦和捕获功能分别通过Widget的聚焦和捕获机制实现,当聚焦后,事件将被相应Widget接收,并触发一系列聚焦相关的事件,如OnFocusReceived、OnFocusChanging、OnFocusLost等。以按钮点击为例,点击按钮触发OnMouseDown事件,若按钮被捕获,则移动到按钮外松开鼠标仍会触发按钮的OnMouseUp事件。

       在处理输入事件时,会涉及多种策略,如FArrangedWidget、FArrangedChildren和FWidgetPath等,用于确定事件处理的路径和流程。FEventRouter类根据输入事件和用户输入策略(FDirectPolicy、FToLeafmostPolicy、FTunnelPolicy、FBubblePolicy)来组织和分发事件。

       处理鼠标和触摸输入的流程分为OnMouseDown和OnTouchStarted,通过Route函数根据策略处理事件,实现事件的触发和响应。移动事件则通过OnMouseMove和OnTouchMoved处理,根据输入类型和用户状态执行相应操作。拖拽事件OnDragDetected则在拖拽开始时触发,允许开发者自定义拖拽行为和数据传递。

       最终,事件处理完成后,将调用相关函数清理记录,包括更新用户位置和路径,以及触发OnMouseUp或OnTouchEnded等事件。ios猜拳源码

       UE4-Slate源码的学习涵盖了事件触发、用户输入处理、事件路由策略等多个方面,理解这些机制和流程对于深入掌握Slate框架至关重要。源码版本4..2提供了丰富的功能和细节,为开发者提供了一套强大且灵活的UI管理解决方案。

UE4.(5.0)后的Sequence系统

       在虚幻引擎4.版本后,Sequence系统的计算方式进行了调整,具体详情可参考《大规模内容的性能保障:虚幻引擎4.中的Sequencer》一文。阅读后,您能大致理解ECS(Entity Component System)在源码层面的实现方式。本文使用的原生引擎版本为5.0.3,相较于4.版本,UE5中接入了更多Section,系统得到了补充,但本文不介绍具体系统功能。

       要了解ECS的入口点,可以创建LevelSequence资产,添加任意Actor及轨道,然后在求值或ImportEntityImpl函数中设置断点,观察堆栈内容。在MovieSceneEntitySystemRunner中,可以看到UE实现的入口点注释。对照官方介绍,Sequence的四个更新阶段均在GameThread_...Phase形式的类中记载,这些类包含代码Linker->SystemGraph.ExecutePhase(ESystemPhase, Linker, AllTasks),这是各系统执行的入口。

       为了详细介绍流程,需要了解类的持有关系和简单功能。主要围绕以下结构展开:Linker及其初始化过程、Linker相关的类型关系、Entity的引入、System图构造及使用、System执行以及实际执行。

       在初始化阶段,首先打开LevelSequence资产,FSequencer作为默认编辑器,调用InitSequencer方法进行初始化,创建全局UMovieSceneCompiledDataManager并持有RootEvaluationTemplateSequence。这个类在ECS过程中主要用于将整个Sequence划分为多个求值区间。RootEvaluationTemplateSequence用于整体调度工作成员,并为外部提供数据访问接口。初始化过程中,创建Linker与Runner,并将其互相绑定。Linker的位置可以根据IMovieScenePlayer的指定或直接在临时包下创建。Linker的全局变量GComponentRegistry持有FComponentRegistry类型,EntityManager提供其指针。新的FInstanceRegistry被创建,并记录RootSequence信息。Sequence实例化参数可用于获取全部Sequence信息,委托指示此Sequence绑定丢失时标记Guid。在Invalidate函数内,ramfs 源码分析由CompiledDataManager进行区间划分并掌握轨道与段落信息,为SequenceUpdater赋值。

       初始化完成后,后续将在FSequencer::Tick或UMovieScenePlayer::Play中执行。此时Runner将调用Linker各个阶段的系统执行。从Runner::GameThread_SpawnPhase开始介绍Linker相关的类型结构。

       Linker主要执行了链接系统与执行系统的工作。在GameThread_SpawnPhase阶段,通过全局变量GlobalDependencyGraph获取保存的Class ID,这些ID是在Init阶段通过UMovieSceneEntitySystem构造函数保存的。GlobalDependencyGraph在系统初始化时保存了所有系统的依赖关系,随后Linker->LinkRelevantSystems遍历整个GlobalDependencyGraphClass数组,如果系统通过relevant判断则执行Linker->LinkSystem。在此过程中,系统被分配至执行数组并安排好执行顺序,通过DFS检测依赖关系是否构成环。

       在执行System阶段,通过FMovieSceneEntitySystemGraph::ExecutePhase,系统按照顺序装入列表并依次调用其OnRun方法执行每个System。System执行的流程涉及Component类型匹配、执行逻辑得出结果并写入目标位置。具体实现细节包括Builder构建任务、匹配Entity、执行操作等。System类型多样,本文仅介绍System与Entity的交互,而非特定功能实现。

       系统实际执行时,组件与系统交互关系复杂,特别是对于具体轨道如平移Actor等操作。理解这部分需要详细了解组件和系统之间的交互。

       本文仅浮于表面,深入理解需要参考官方文档。写此文的目的是记录对虚幻引擎Sequencer系统学习的感悟。如果有空,可能会继续挖掘更多相关内容。

Ubuntu.源码编译CARLA0.9.全过程记录

       本文详尽记录了在Ubuntu .上通过源码编译CARLA 0.9.的全过程,特别强调了Linux系统环境的配置以支持与ROS和Autoware的协同仿真,并且允许自定义场景和车辆配置。

       步骤一:系统基础配置

       首先,确保安装Ubuntu .并配置Nvidia显卡驱动,参考链接:win + Ubuntu . LTS 双系统安装(UEFI + GPT)。

       步骤二:安装依赖

       参考Linux build - CARLA Simulator -branch 0.9.,逐步安装必要的软件,如遇到下载问题,可考虑使用阿里源或新华源,推荐查阅:ubuntu安装软件依赖问题。

       步骤三:Unreal Engine 4. 安装与配置

       由于CARLA 0.9.以上版本使用UE4.,需先安装并编译。确保Github账户已与Unreal Engine账户关联,如需Personal Access Token,参考Github - 使用新的Personal Access Token进行仓库认证。

       步骤四:下载与编译CARLA

       从官方仓库下载CARLA源代码,lmshop 源码下载更新时可能遇到官方资产Url变化,需修改Update.sh文件。编译过程中,PythonAPI部分网络需求较高,make launch可能需要设定UE4_ROOT环境变量,具体步骤见BuildCarlaUE4.sh。

       步骤五:运行测试

       在完成上述步骤后,进行测试并欢迎在评论区交流问题,如有任何疑问,欢迎留言。如果你对内容满意,请别忘了收藏和关注。

UE4-Slate源码学习(四)FSceneViewport

       即视口是引擎中显示游戏画面的SWidget控件,也是编辑器中显示游戏内容的窗口。场景绘制视口(FSceneViewport)与SViewport绑定,用于场景渲染。鼠标捕获模式(EMouseCaptureMode)与鼠标锁定模式(EMouseLockMode)在项目设置中可配置,影响鼠标的交互。FSceneViewport事件处理包括鼠标按下(OnMouseButtonDown)、触摸开始(OnTouchStarted),事件响应后构造FReply,并更新几何体缓存、鼠标位置缓存。鼠标位置由绝对坐标转换为相对于视口的相对坐标。根据捕获状态和输入处理逻辑,事件最终被传递至PlayerController,通过PlayerInput管理。对于触摸输入,处理流程类似,调用InputTouch接口。

       移动事件(OnMouseMove)、触摸移动(OnTouchMoved)记录鼠标的Delta和NumMouseSample累计值,Tick时处理。ProcessAccumulatedPointerInput在Tick阶段调用,处理键盘、鼠标输入,相关流程见第二章。完成输入处理后,FEngineLoop调用FinishedInputThisFrame,最终在ProcessAccumulatedPointerInput中调用InputAxis,处理至PlayerController的InputAxis,存储在PlayerInput中。其他事件如鼠标释放(OnMouseButtonUp)、触摸结束(OnTouchEnded)同样遵循类似流程。

       若SWidget为视口,执行相关事件调用至ViewportClient接口,进而触发输入系统(PlayerController、PlayerInput、InputComponent)。日常游戏开发中,通过视口事件实现如旋转相机、隐藏鼠标等操作。PlayerController提供三种模式(FInputModeUIOnly、明信片素材 源码FInputModeGameAndUI、FInputModeGameOnly),通过调整SViewport和ViewportClient参数,实现不同模式下的捕获、锁定、显隐鼠标功能。所讨论内容基于UE4版本4..2。

UE4 LevelSequence源码解析

       本文旨在总结UE4中LevelSequence工具的学习理解,内容涉及LevelSequence结构、插值数据提取及数据导出实例,同时也提供了一些实用技巧。

       LevelSequence在UE4中分为运行时Runtime和编辑器Editor两部分。Runtime中,主要文件位于/Runtime/MovieScene和/Runtime/MovieSceneTracks文件夹下,包括了LevelSequence资产在关卡中的组成形式和播放设置。在Editor中,文件位于/Editor/Sequencer文件夹下,包含了Sequence的组成部分和通用方法。每个ALevelSequenceActor包含UMovieSceneSequence和ULevelSequencePlayer,前者存储数据,后者负责播放。

       UMovieSceneSequence和ULevelSequencePlayer的结构,展示了Sequence资产与当前场景之间的关系。Sequence数据按Actor组织,每个Actor可以持有多种UMovieSceneTrack,用于记录不同属性,所有Track均继承自UMovieScenePropertyTrack。Track由多个Section组成,Section由UMovieSceneChannel存储关键帧数据。

       LevelSequence的模拟过程由Evaluation实现,现在主要由EntitySystem负责,以支持多线程提高效率,具体解释见文章:Performance at scale: Sequencer in Unreal Engine 4. - Unreal Engine。

       在实际模拟中,关键数据的提取是重点。对于Transform等float类型数据,Sequence编辑器支持以曲线方式灵活调整关键值之间的变化过程。MovieSceneFloatValue结构体用于存储关键帧数据,通过访问该值即可获得对应数据。

       导出数据的实例是将Sequence内属性(如Transform)导出为曲线。首先获取LevelSequence资产,然后获取绑定的Actor。利用获取的Actor,可以进一步获得轨道,并将对应数据存储到曲线中。

       一些技巧包括:某些特殊Component在Sequence中作为同等层级存在,可通过此方式获取Component的Track;相对位置配置在Instance Data中,可通过变量获取对应数据;实践体验Sequence生成过程,建议通过/Editor/SequencerRecord入手,直观看到生成流程。

       参考文章包括:UE4 LevelSequence源码剖析(一)- 知乎、UE4 LevelSequence源码剖析(二)- 知乎、UE4 LevelSequence源码剖析(三)- 知乎、Performance at scale: Sequencer in Unreal Engine 4. - Unreal Engine。

UE 八叉树Octree2源码分析

       UE中八叉树Octree2源码分析,本文旨在深入理解UE八叉树的具体实现。八叉树概念广泛熟悉,但初次接触UE实现时仍需思考。UE八叉树简化应用,多数直接使用方便。本文针对UE4.至UE5.1版本八叉树源码进行详细解析。

       UE八叉树主要结构包括:TreeNodes、ParentLinks、TreeElements、FreeList、RootNodeContext和MinLeafExtent。TreeNodes存储节点信息,每个FNode记录当前节点元素数量及子节点Index;ParentLinks记录节点父节点ID;TreeElements存储元素数据;FreeList记录空闲FNode下标;RootNodeContext和MinLeafExtent与八叉树构造相关,用于确定节点半径。

       UE八叉树构造过程依赖AddElement方法,实现在AddElementInternal中。首先判断节点是否为叶子节点。若无子节点且元素数量超过预设阈值,或节点半径小于MinLeafExtent,则创建子节点。否则,直接将元素加入当前节点。若需创建子节点,清空当前节点元素,分配八个子节点,递归处理非叶节点情况。

       RemoveElement方法根据ElementId移除元素。首先在TreeElements中移除元素,然后从节点向上遍历,检查元素数量过少的节点,进行塌缩重构,将子节点元素移入当前节点。

       UE八叉树查询接口包括FindElement、FindElementsWithBoundsTest等,核心目的是遍历节点和子节点以满足查询条件。UE八叉树用于高效空间数据处理,通过Octree2类声明实现。例如,PrecomputedLightVolume类定义ElementType和OctreeSemantics,便于特定应用使用。

       UE八叉树内存管理关键在于TreeElement数组,使用TInlineAllocator或FDefaultAllocator需考虑应用场景。空间数据结构如四叉树、八叉树等在空间划分算法中具有重要应用,优化碰撞检测及实现复杂场景。

UE4动画系统播放Montage源码浅析(二)

       在先前的文章中,我们对UE4动画蒙太奇播放过程进行了探讨,本篇将深入解析蒙太奇的其他相关知识,包括蒙太奇插槽、蒙太奇片段和动画片段等。所分析的源码版本为4.。

       关于蒙太奇结构,UAnimMontage蒙太奇动画可视为一种动态表现手段,无需将混合空间或动画序列拖入动画蓝图,只需在动画蓝图里放置一个FAnimNode_Slot动画节点,即可通过montage_play接口播放该插槽下的所有蒙太奇资源。

       这意味着我们无需修改动画蓝图,就可以播放全新的动作。

       蒙太奇动画除了动态播放动作外,还有更多应用。例如,现实中的蒙太奇概念。蒙太奇(montage)在法语中意为“剪接”,但在俄国,它被发展成一种**中镜头组合的理论。例如,将母亲煮菜、洗衣、带小孩、父亲看报等镜头放在一起,会给人一种母亲“忙碌”的感觉,从而产生对比手法,突出人物或事物的具体特征,两个不同的片段之间相互联系,产生意想不到的效果。

       如上所述,这类动画被称为蒙太奇,因为它还包括剪接、片段、组合等特点,可用于循环播放动画、跳转到下一个动画等。

       创建一个动画序列的蒙太奇,会看到如下面板:区域1为蒙太奇插槽,在动画蓝图中也要有对应插槽节点才会播放此蒙太奇;蒙太奇资源中可以添加多个插槽。区域2为蒙太奇片段,蒙太奇资源中可以创建多个片段并设置它们之间的关系,用于动画的跳转、循环等。区域3为动画片段,每个插槽下可以添加多个动画片段。

       蒙太奇片段对应上图示例有三个片段:Default、Loop、End,我们可以设置它们之间的关系。图中Default片段后面的箭头图标表示播放完毕后会接着播放Loop,Loop片段后的循环图标表示循环播放Loop。如果我们显式跳转到End片段,End片段后面没有其他片段,那么播放结束后就结束了。

       蒙太奇片段是独立的,与插槽、动画片段没有任何关系,它只是根据蒙太奇片段之间的关系确定当前播放时间。了解了蒙太奇片段的作用,我们来看具体实现。其数据结构如下:蒙太奇片段由FCompositeSection结构描述,CompositeSections就是蒙太奇资源上序列化的蒙太奇片段数组。

       了解了基本数据结构,再看如何根据动画片段获取蒙太奇姿势。结合上一篇文章,姿势获取最后是调用FAnimInstanceProxy::SlotEvaluatePose函数,并遍历MontageEvaluationData数据(其中包含蒙太奇实例的时间、权重、蒙太奇引用等数据)。

       以上便是关于UE4动画系统播放Montage源码的解析,希望对大家有所帮助。

UE4-Slate源码学习(六)slate渲染Part2-Paint控件绘制

       上一篇文章介绍了绘制一个SWindow的初期步骤,即计算整个UI树的控件大小,为绘制做准备。文章随后深入探讨了绘制流程的第二步,即执行FSlateApplication::PrivateDrawWindows()后,开始调用SWidget::Paint()函数,每个控件随后实现其虚函数OnPaint()。

       在这一过程中,绘制参数被封装在FPaintArgs中,作为Paint和OnPaint过程中的关键引用参数。FSlateRHIRenderer与FSlateDrawBuffer是继承自FSlateRenderer的类,作为FSlateApplicationBase的全局变量,在构造时创建。在绘制过程中,通过GetDrawBuffer()函数可获取到FSlateDrawBuffer对象。

       FSlateDrawBuffer实现了Slate的绘制缓冲区,内部封装了FSlateWindowElementList数组,用于存储多个SWindow下的绘制元素列表。每个SWindow通过AddWindowElementList()返回一个元素列表。

       FSlateWindowElementList负载了SWindow内的所有图元信息,内部封装了FSlateDrawElement的数组,包含Cached和Uncached元素,以及SWindow的指针和用于渲染的批处理数据FSlateBatchData。

       FSlateDrawElement是构建Slate渲染界面的基本块,封装了UI树节点控件需要渲染的相关信息,如渲染变换、位置、大小、层级ID、绘制效果等,以及后续渲染阶段需要的相关数据。

       在Paint流程中,处理当前传入的SWindow和ChildWindows,首先判断窗口是否可见和是否最小化,然后从参数封装的OutDrawBuffer中获取WindowElementList。调用SWindow的PaintWindow()函数开始绘制窗口,并最终返回所有子控件计算完的最大层级。接着,子窗口递归绘制。

       PaintWindow()函数在绘制窗口时,首先调用SetHittestArea()设置点击区域,HittestGrid会判断窗口大小是否改变,若不变则仅更新窗口在屏幕中的位置。构造FPaintArgs参数后,将其封装到FSlateInvalidationContext中。

       FSlateInvalidationRoot类的PaintInvalidationRoot()函数可以作为控件树的根节点或叶子节点(SInvalidationPanel),构建快速路径避免每次绘制都计算大小和Paint函数,有利于优化。本篇文章主要分析正常慢速路径调用流程,优化相关将另文分析。

       PaintSlowPath()函数从SWindow开始调用Paint()函数,并定义LayerId从0开始作为参数,进行实际的绘制相关计算。

       Paint()函数首先处理裁剪、透明度混合、坐标转换等代码。若SWidget包含NeedsTick掩码,则调用Tick函数,我们在日常开发中通过蓝图或lua使用Tick函数时即调用到这里,通过SObjectWidget::Tick调用到UUserWidget::NativeTick供实现Tick。构造FSlateWidgetPersistentState PersistentState作为SWidget的变量,表示Paint时的状态。

       PersistentState.CachedElementHandle将当前SWidget存储到FSlateWindowElementList中的WidgetDrawStack数组中。

       更新FPaintArgs中的父节点参数和继承可点击测试参数,判断点击测试状态,然后将当前SWidget添加到点击测试中。调用虚函数OnPaint,由控件自己实现。

       OnPaint()函数参数包括绘制参数引用、几何体、裁剪矩形、缓冲元素列表、层级、控件风格、父节点状态等。最后处理重绘标签、延迟绘制相关内容、UpdateWidgetProxy()根据缓存句柄更新快速路径中需要处理标记设置为Volatile不稳定状态的SWidget。

       虚函数OnPaint()由子类自己实现,本文列举了SImage、SButton、SCompoundWidget和SConstraintCanvas的OnPaint()示例代码学习。

       在SImage中,简单判断Brush是否存在以及BrushDrawType的类型,然后调用FSlateDrawElement::MakeBox将控件添加到缓冲区元素列表中。

       SButton继承自SCompoundWidget,GetBorder()根据当前按钮状态返回ui中设置的Enabled、Press、Hover、Disabled等状态的Brush。

       SCompoundWidget作为合成节点,有且只能有一个子节点,且在Paint时强制将子节点的LayerId+1,同时SCompoundWidget可以单独设置混合颜色和透明度,影响子节点。

       SConstraintCanvas作为SWidget的基类对应UMG中常用的UCanvasPanel,通过ArrangeLayeredChildren()对孩子进行层级排序,并根据孩子的层级是否相同存储bool值在ChildLayers中。遍历所有孩子,判断是否开启新层级,递归调用Paint函数,最后返回最大层级。

       SConstraintCanvas::ArrangeLayeredChildren函数中,获取设置bExplicitChildZOrder,表示可以将同层一次渲染,有利于提高渲染器批处理。对所有孩子排序,排序规则为FSortSlotsByZOrder。遍历所有孩子,判断可见性掩码、计算偏移、锚点、位置、拉伸缩放等,封装成FArrangedWidget存储到ArrangedChildren中,用于OnPaint时有序遍历。判断每个孩子ZOrder是否相同,相同则bNewLayer为false,大于LastZOrder则将bNewLayer设置为true,最终存储到ArrangedChildLayers中,用于OnPaint函数判断是否将layerId+1。

       FSlateDrawElement::MakeBox()函数在OnPaint之后调用,将绘制控件的相关信息通过创建FSlateDrawElement绘制元素对象,添加到SWindow管理的FSlateWindowElementList元素列表中。创建Payload用于存储贴图等相关信息,根据控件Paint过程中的参数调用Element.Init初始化绘制元素,得到为该控件绘制创建的FSlateDrawElement对象。

       总结整个Slate绘制流程的第二步,我们没有分析快速处理和优化细节,而是按照正常绘制流程分析代码。通过从PaintWindow开始遍历整个控件树,处理每个空间节点的Paint、OnPaint函数,最终目的是给每个控件创建一个FSlateDrawElement对象,存储渲染线程绘制所需的相关信息,并添加到FSlateWindowElementList中。理解了整个调用流程,整个过程较为清晰,本文基于UE4版本4..2。