粉丝3.8万获赞55.9万

像这样扫描现实、一比一还原的高斯坡键模型,如何导入虚幻引擎?还可以添加完美贴合的碰撞体。首先,我们需要使用 meepermap 软件生成碰撞体网格模型 和高斯波建模型,勾选 fbx 格式网格模型及高斯波建模型后,开始一键重进。重建完成后,可以通过插件将高斯波建模型导入虚幻引擎,再将 fbx 格式网格模型导入虚幻引擎。作为高斯波建模型的碰撞体, 设置碰撞规则为复杂碰撞即可获得精准贴合高斯的碰撞体模型。打开高斯模型的蓝图编辑器,添加静态网格体组建,选择刚刚导入的 fbx 模型,将 fbx 模型调整至与高斯坡键模型贴合。碰撞预设设置为空气墙渲染设置,在游戏中隐藏, 设置完成后即可将模型放进关卡,体验具有真实碰撞的高斯坡建模型场景。仅需一次重建,快速构建具有真实碰撞、一比一还原现实的模型场景。留言分享更多 meepermap 实用功能!

一觉醒来,虚幻引擎迎来了自己的 m c p 时刻。 epic 刚刚发布虚幻引擎五点八,直接把 ai 原声塞进了游戏大作开发流程,不是那种帮你写几行代码的辅助工具,而是通过官方 m c p 接口,让 codex 这类直接接管虚幻编辑器。 你只需要描述一句话,比如生成一座赛博朋克城市, ai 就 能自动摆放道具、生成街区规划建筑,甚至连灯光氛围和场景美术风格都能一起完成。 epic 还首次公开了通往虚幻引擎六的路线图,未来的大模型生成是 ai 以及 cloud、 codex 等工具真正参与到三 a 游戏制作当中。



抠打持家虚幻引擎,尝试做一个游戏出来,配置优异。五点八工具链官方 imovie 创建蓝图工程设置默认地图渲染分析上一期 bruno 的 赛博朋克场景设计,搭建三个街区的赛博朋克城市,导入并优化本地建筑、车辆、店面、 h v a c 消防地等模型,补充材质碰撞完成预约。灯光思路反射霓虹招牌布校与粒子。这里发现他不会主动调用虚幻中的资产,怎么人物还是个耗炭感呢?场景还是比较粗糙的, 教他调用本地资产,更换人物还行,那再加个 f b s 的 设定吧。哎哎,怎么无法造成伤害呢?下一期解决,下一期解决!关注我,学习更多 web 扣定案例。

想学虚幻引擎?认准这五位 up 主,想自己独立做出可运行的小游戏,就看他蓝图罗姐讲的通俗落地零基础也能跟着做完完整项目。打算做大型野外游戏场景搭建环境观卡就看他 植被布置,光影调节贴合企业上班标准,用来完善作品级,特别的合适。励志做三 a 宏大场景世界观规划,就看他带着学习海外大省的创作思路,开阔你的设计眼界。眼睛基础杂乱,材质灯光一直搞不懂的来就找他 把 ue 五的基础内容掰开拆解,帮新手呢夯实基本功。偏爱二次元角色,想做元神风格三选二效果的认准他角色材质渲染讲的通透,很适合想做二次元美术的同学。

每天一张图,人人都是顶级地编师。今天我们讲一张 a 站的高分风格画作品,深度剖析为什么他能拿高分,以及给大家总结一个可以照着抄的套路。我们开始这张图,我给他打九十二分, 扣掉的八分里三分是前景。植物分布,太君云象复制粘贴,五分是部分石头和地面交界处的接触,阴影偏弱,物体有点飘。 除此之外,他在地边的几个核心维度上都做到了位。先说空间结构,这个微型峡谷不管镜头怎么转,都成立。左右两侧的岩石和树干定义了一个明确的视觉走廊,你的眼睛只能沿着它往里走。前景的草叶遮挡限定了观察位置,让你知道自己是从一个低矮的入口往里看。 这不是某一个角度碰巧好看,是背后有一整套空间逻辑在支撑。好的地边,不管镜头怎么摆,空间关系都站得住。 色彩在做的事情是标记优先级,近景暖绿,中景暖橙,远景冷紫,暖色往前跳,冷色往后退。人眼会本能的先处理暖色区域,地边市要做的就是顺应这个极致,把重要的信息放在暖色区域,次要的推到冷色里去。 很多新人把所有东西做的一样鲜艳,结果视觉权重平均分布,观众的眼睛不知道往哪落。光影在做的事是导航。 那树从峡谷上方打下来的光照亮了河面和路,你的本能反应就是那边可以走主光源角度压的很低,几乎贴着地平线,光沿着地面扫过来,把路径整个洗亮。如果太阳在正上方,光从头顶灌下来,地面和墙面几乎没有明暗差异,路径就消失了。 太阳角度的选择本质上是在选择。我要让玩家看到什么往哪走。材质方面,这张图的磨损逻辑是对的。 苔藓只长在潮湿的墙角和排水口下方,草纸从铺装裂缝和沟槽里冒,干燥的高处反而干净。这些痕迹可能是顶点汇聚混合材质层,也可能是贴花叠上去的。具体怎么做不重要,重要的是每处脏都能解释来源。 你能不能用一句话说清楚场景里每一处磨损的理由?这是一个很好的自检标准,说不上来的就删掉。 植被分布也是同理,植物集中在河边阴影里,低洼处、干燥的高处比较稀疏。植被在这里不只是装饰,它是地形的二次说明。植被的密度和方向应该跟着地形和水流走,不是跟着笔刷半径走。那只鹿的作用是锁定尺度, 没有它,你很难判断峡谷有多大。石头可能半米,也可能五米,有了它,尺度瞬间确定。同时它是一个活物信号,告诉观众这个空间有生物活动,不是死寂的。在地边里放一个角色或生物的剪影,成本很低,但信息量很大。最后,给你一个能照着抄的四部框架。 第一,先用简单几何体把空间走廊入口焦点位置定出来,确保从多个角度都成立,而不只是某一个镜头好看。第二,主光源只放一个角度压低,让他沿着地面走,明确告诉观众往哪看往哪走, 不要开多余的补光和点光源。第三,材质每加一处磨损或脏迹,问自己他为什么在这里, 答不上来就删。第四,放一个尺度参照物、角色、动物、载具都行,让你的空间有一个可以丈量的精准。 这四句话对应空间规划、光照设计、材质逻辑和尺度意识。每次做完一个场景,拿它们逐条过一遍,哪里答不上来就改哪里。每天一张图,人人都是顶级地编师,今天这张就讲到这里,我们下期见!

本周交通系统更新,对多项功能进行了优化改进,其中包括车辆现在会等待前方车辆通过路口之后才开始行 驶,并会通知后方车辆可以走了准备出发向前行驶,后续会自动停车等待,直到轮到下一辆车通过。整个流程按预期运行。当然还有其他改进,同时也有一些地方仍需继续调整, 尚未达到完美状态。我们会持续迭代,直到达到目标效果。首先回到我们的原始项目, 当前这个是绿灯,这个是红灯,也就是说这个结束后应该变红,但实际并没有变红的,反而是这个仍然是绿灯。需要修几个 bug, 同时做一些优化改进。先从修复路口逻辑开始 执行顺序搞反了。为此打开 traffic intersection blueprint, 就是 这个里面有 drive 和 stop 两个分支。问题在于,我是在 stop 分 支里执行了交通灯的自灯加加操作,实际上应该在 drive 分 支里执行, 因为我希望先把绿灯切换为红灯,然后让下一个方向变为绿灯。我们这里顺序写反了常见的小错误。好在修复也很简单,具体做法是在这之后 断开这里的连线,将这一段整体移动放到上方,下方。同理,这一整段从录不起的部分需要移到下方,全部移下来接好连线,这段也连到这里。这样操作等效率交换了 stop 和 drive 的 位置, 因此只需更新注视,让这里显示 drive 标为绿色,下面那个标为红色。好了,这样其实更直观、更准确地反映了实际逻辑。还需要做一件事,在 drive 分 支处添加一个短暂延迟, 在红灯触发停车后,给一点时间让路口内的车辆完成通过,然后再让下一个方向变绿。这也符合现实逻辑,现实中通常有一段时间所有方向都是红灯, 至少我观察到的是这样。实现方法就是加一个底位节点,放在 drive 之前。延迟设为两秒,先等待两秒,再继续直行。没问题,因为 timer 的 总时长更长, 当前是六秒,这意味着绿灯实际持续时间变为四秒,因为这里扣掉了两秒, 但四秒我认为太短,所以将总时长调整为七秒,这样等效于绿灯。 drive 阶段实际持续五秒。注意,交通灯总时长减去 d 类才是实际绿灯时长。更简洁的做法是 可以设定绿灯时长为五秒, light duration 设为五,然后在上方将 traffic light duration 加上两秒 delay 作为 timer 总时长, 当然可以把 delay 提升为变量,在两处都引用该变量,方便统一修改。目前这样就够用了。看一下当前状态,这里是红灯,这里是绿灯。这个马上要变红, 变了,已变为红灯,下一个变绿正确。这边还有一些问题,但我们接下来会逐一修复路口一的信号灯逻辑已修复,接下来要处理的是 离开 spline 后,不在 spline 上时,不再持续搜索下一条 spline, 改为直行一次远距离 trace, 找到 spline, 然后引导车辆对齐到该 spline 点, 几乎确保能精准吸附到 spline 上,效果更好,同时无需持续检测。这是优化。这里有一个 transfer new path 函数,将其转换为 event, 右键选择 convert function to event, 原因是需要添加一个 delete, 这样找到 spline 后,可以先等待已找到目标, 等车辆靠近后再激活 spline 来修改这里。这部分没问题,但检测距离不再急于速度, 而是使用固定距离。删掉。这里的 current speed 的 相关节点全部移除,改用 forward vector 乘以一个固定距离。右键移除该引角,右键点击这个引角转换为 float。 检测距离设为前方一万单位。 这个值比较大,仅用于测试阶段。实际项目中通常不需要如此大的检测距离。这里使用大值只是为了方便在场景中放置较远的起始位置。从当前位置向前检测一万单位。 仍然检测 traffic road 的 碰撞通道。 sphere trace 半径需要加大,设为两百应该足够了,允许左右方向有一定偏差,可以酌情调大这个值。如果可以接受车辆末端有轻微转向的话,两百的效果已经不错。假设以命中目标, 未命中的情况需要处理。若未命中,需要输出提示。添加一个 print string, 颜色设为红色, 显示五秒以便察觉。文本内容为 could not find new spline。 理论上应该始终能找到新的 spline, 找不到就说明存在问题。假设找到了,在下方留出空间,暂时折叠这部分。首先让 actor 朝向命中的 hit actor。 确切来说是 hit component 找到了 spline, 找到了路径。调整车辆朝向,使其更好地对齐 并靠近该路径点。为此需要知道 hit component 的 位置。从 hit component 调用 get award location 获取命中目标的世界坐标,即被 trace 命中的目标,也就是该路径的碰撞和 即路径的起始点,需要知道应该朝向哪里。调用 get actor location 获取自身当前位置,计算需要旋转的方向, 从 get actor location 拖出,搜索 find look at rotation, 目标点就是 hit component the world location。 有 了旋转之后,从处分支连出, set actor rotation target 为自身,将自身旋转到该朝向,如此车辆会自动朝向命中的 component, 这样就不需要手动对齐,也能上路行驶, 但还需要确认距离足够近。加一个距离判断需要检测车辆与命中位置之间的距离。拖出连线,使用 distance factor 节点连接如下,即检测 hit component 与 actor 之间的距离。 该值基于当前速度判断,只要距离小于等于 current speed 乘以帧率, 使用 get frame rate 节点获取帧率接入即可。只要在一帧内的行驶距离内即可完成 spline 的 衔接,可以正常工作。当然可以在这里加一个倍数。比如说如果可以接受轻微的位移跳变, 因为最终判断在该距离范围内时可以修复一些问题。大多数情况下,保持默认值即可直接移除该引角。偶尔还是会出现未能吸附到 spline 的 情况。 这个问题我还需要深入排查,但不想用上面那种方式修复,因为那个跳变效果不好看,后续可能会做一些调整来优化。目前先记录这个现象,原因还未找到,因为所有数据看起来都是正常获取的,发生频率不高,但即使是百分之一的概率也值得修复。 好的,现在确认距离在正常行驶速度范围内,那么可以直行进行 spline 衔接,设置相关参数。 这里原本做了什么?做了很多事情,基本上就是我们现在正在做的这些,所以不必重复做,无需再做一遍,直接拿这里的 get component by class 随机选举 spline 的 设置逻辑,因为其余部分已经在这里处理了,只是稍微有些不同。 实际上只需把这个 d 类也复制过来,连同这部分一起复制替换。这里粘贴进来,连接到这个接口, 重新整理节点,布局。这里的 get component by class, 从这个 hit actor 获取连接所有引脚。现在与之前一样,检测距离。 同时执行 find look at rotation, 调整车辆朝向目标方向,判断是否足够近。若足够近则设置 spline。 还需要设置几个附加条件,例如不允许重复执行。在 transfer new path 这里拖出连线,使用 do once 节点, 确保整个逻辑只执行一次,只有当完整执行完成后才允许再次出发。之后 reset do once, 允许再次寻找新路径,因为此时已经切换到新路径了,重置后即可再次出发,允许再次执行。若在这里失败,则存在其他问题,需要输出记录, 便于后续定位修复。将这部分全部添加注视,命名为 do once trace for new path。 当前启动时,由于不从 spline 出发,需要通知车辆先寻找第一条路径, 等有 spawn 系统时,直接在 spawn 上生成,会自动完成 spline 分 配,目前尚无预分配,针对这点做一下调整。在 drive 事件处检查 current follow spline 是 否有效, 拖出,引用右键 convert to validate get 判断是否有效,若无效则执行 trace for new path, 因为此时已收到 drive 指令,但不知道要开往哪里。无效时搜索 new path, 调用 trace for new path, 仅在无效时执行。这样很好,但原有系统仍然存在。在 drive forward 函数里, 每帧都在执行 trace for new path, 现在不再需要了,将其移除,只保留 trace for car。 后续有时间再统一优化。等功能稳定之后,至少对我来说,先跑通后优化, 先跑通逻辑再说。来看看效果。车辆应当可以正常行驶,前方这些车辆与之前一致。走起来了,变绿了,这辆右转,这辆直行。这辆变绿后,应该跟随 s p i n 行驶。 把这个 trace for new path 的 debug duration 打开,显示测试持续时间,方便可释缓。运行 simulate 可以 看到每辆车都已找到路径,现在绿灯时只重新执行一次 trace。 还有一些问题正在修复。启动时只执行一次, 然后持续行驶。之后当某条车道变绿时,再直行一次。可以看到右转一辆,直行一辆,持续循环这辆也一样。这辆找到路径后继续行驶,不再持续执行 trace, 离开 spline 时也不再触发。 很好,这是一个不错的优化。关闭 debug duration 显示还发现了另一个问题,在 get future position and rotation along spline 函数里,内部使用了 get distance along spline at location。 这个节点存在问题, 当 spline 存在弯曲时,它很难准确判断车辆当前在 spline 上的具体位置。解决方案是,不再每帧计算,改为存储为一个简单的 float 变量,按需更新和读取, 新建一个变量,命名为 current distance along spline 类型设为 float, 获取该变量,替换掉原来的 get distance along spline at location 节点,距离值直接从这里读取,可以删掉这个节点了。每次获取到位置信息后需要回血。更新为最新的距离值。在这个 start 节点之后, set current distance along spline 负值为刚刚计算出的结果。基于加法运算得出的新距离。整理完毕,现在逻辑更清晰了。 current distance along spline 加上本次行驶的距离,得到新的 distance 并回血。这同时意味着其他地方也需要维护该值,例如这个 trace 函数内部。当赋值新 spline 时, 需要确保从起点开始,因此重置该值。将 current distance 时执行进行设置, 同时在这里也做同样处理。在 set current spline component 旁边,目前仍在使用,后续会移除这套系统,目前暂时保留在这里。同样将 current distance along spline 在 复制新 spline 时重置为零。来看看效果功能是否仍然正常。出现了轻微的传送跳帧,为什么会直接跳到末端?原因是这里运行 simulate 可以看到车辆在停车线处停下,其余功能显然不正常,但可以确认车辆移动本身是正常的。现在修复前方车辆检测的 trace 逻辑。首先 重新接入 trace for car, 单独放在这里,紧接在 set actor location and rotation 之后,因为 trace for intersection 之后要加条件判断。基于条件执行。 接入后运行可以看到传送到了前方,问题源头已定位。首先修改的是 get future position and rotation along spline 使用一个稍有不同的函数,不再基于速度计算, 而是使用固定距离,该距离为 deceleration distance。 上节课设置了 max deceleration distance, 但一直没有使用。这里就是它登场的时候。在函数内部使用 get location at distance along spline 作为目标。 current distance along spline 作为距离输入,复制相关节点粘贴到这里。现在有了可以接入它给引脚的 spline, 引用距离值为 current distance along spline 加上 max deceleration distance, 即这里 controls 分 类下的 max deceleration distance 接入。这就是需要检测的目标距离点。将其同时作为 s f e r trace 的 end 和 start 替换掉之前的内容。 start 改用 get active location 作为检测起点,从自身位置向前沿 spline 路径检测该距离内的车辆。弯道上 trace 路径会稍微弯曲,暂时可以接受,因为如果前方有车,哪怕稍有偏角也可能造成影响。 理论上应该提前减速,现在还不够完美,后续会进一步优化,目前能满足需求。好,现在换用了新的 trace 方式。仍然检测是否命中车辆,判断命中目标是否有效 获取前车速度,判断是否低于本车速度。若是,则设置 deceleration 为前车速度,但不再设置 deceleration distance, 因为该部分已移除。 现在改为使用 heat result 中的 distance 值。接入这里的减两百和 max 零节点。 调整节点位置,保持整洁,整理布局。经过更多测试后发现偏移值改为三百效果更好。 具体值取决于车辆尺寸,后续会自动化计算,目前相应编码为三百。这样 current acceleration distance 就 设置好了。与之前一样,清除 acceleration timer, 停止车辆 false 分 支。 若前方没有车辆,需要执行更多判断。首先重置 max speed, set max speed, 在 未找到前方车辆后执行,需要恢复为原始 max speed, 但原始值没有存储,不知道原始 max speed 是 多少了。可以在变量中存储,在车辆出场时记录。打开 event graph, 找到 event begin play, 再复制为 max deceleration distance 的 地方,新建一个变量, 命名为 original max speed, 然后进行赋值。正如你所猜到的,赋值为传入的 max speed。 这样即使 max speed 被修改,也始终知道该车辆的原始 max speed。 将其移入 speed 分 类。 将 distance along spline 单独归入 spline 分 类。放在 spline 分 类下,有多处需要重置 max speed 多次用到,所以新建一个专用函数,命名为 reset max speed。 逻辑非常简单,将 original max speed 复制给 max speed, 就 这样 reset max speed 的 作用就是重置最大速度。原因是需要在 drive 时重置 max speed, 确保开始行驶时恢复原始 max speed。 因为可能在路口停车时被降速过,而此时前方已无车辆,没有理由继续限速。因此在启动时先重置 max b, 将其接入 drive, 先执行 reset, max b, 再执行 drive 以及 trace for new path。 注意这里确保 drive 函数的顺序在 begin play 复制之后, 否则 original max speed 为零。若 drive 先于 begin play 执行 reset 时,会把 max speed 设为零,车辆无法行驶,执行顺序直观重要。 同样的问题,未找到前方车辆时,不再手动 set max speed, 直接调用 reset max speed, 然后连接所有引脚。还有一种情况, trace 成功命中了前方车辆,但前车速度并不低于本车。 可能前车正在加速,速度在提升。在追赶过程中,前车开始加速了,此时需要更新本车 max speed 来匹配,同时确保不超过 original max speed。 只要在增速,本车也可以跟随增速。从 force 分 之。 set max speed 使用 mean float 节点,用途是取前车 current speed 与 original max speed 两者中较小的值 作为新的 max b。 这样若前车更慢,本车会匹配追上前车。使用密恩节点后,前车加速时本车不会超出自身速度上限。 之后进入这个 branch 触发 start acceleration。 与之前逻辑相同,由于这部分改动以及其他一些调整,两套系统现在已非常接近,不如直接合并。做法是如之前所说,取 current follow spline 转换为 pure get, 判断是否有效。输出波练值,用来切换 start 和 n d 的 值。 之前基于速度计算,现在不再如此,仍使用 max deceleration distance。 区别在于不再沿 spline 检测。直接取这里所有节点并获取 follow spline。 引用从 n d 拖出,连接 select 节点或直接添加 select 节点。将 block 接入 index 有 效时,使用 get location at distance along spline 处。使用该节点无效时,使用 forward vector 方式 获取 forward vector 连接到这里,乘以 max deceleration distance 与之前一致接入,加上当前位置 稍作整理, get actor location 接入,这就是新的 false 分 支。结果,向前检测 max deceleration distance 距离范围内的目标不在 spline 上时,使用此方式。在 spline 上时沿 spline 检测, 这样原来的条件判断就不再需要了,直接执行 trace for car。 稍作清理,移除整个底部分枝。原有注式已不再适用。移除注式,再次整理。 严格来说,这样做会导致问题,但我想掩饰这种情况,因为这是一个非常常见的错误,我自己也经常犯, 而且总会忘记运行 simulate, 会发现没有任何车辆移动,停止后会看到大量报错。尝试读取 current follow spline 属性失败,你可能会想,我已经判断有效期了。这不就是有效期检查的意义吗?对,但问题在于,注意 select 节点会加载所有连接的路径, 无论 true 还是 false, 不 管 index 是 什么值。这意味着即使不练为 false, current follow spline get location at distance along spline 也会被执行,即便逻辑上不应走触分之,它仍然会执行。修复方法很简单,取 current follow spline, 改回。使用 validate get。 添加一个 sequence 节点,先判断是否有效。若有效,将结果存入一个本地变量,命名为 entries location。 添加本地变量,命名为 end of trace location 类型设为 vector, 有 效时, 复制为 get location at distance along spline 的 结果,将此节点移上来连接。 无效时走这里使用 forward vector 方式,即 forward vector 那 套计算接入。不再使用 select 节点,改用 and trace location 本地变量,将其移过来,判断路径后,执行 trace 连接如下,在正式测试之前需要一起测试,还需要修复 trace four intersection 的 设置。 在 drive forward 的 里有 trace for intersection。 打开它会看到这里设置了 current deceleration distance, 但从未设置 deceleration go。 deceleration go 是 目标速度,目标是停车,即 stop at intersection。 因此需要将 deceleration go 设为零,然后触发停车,同时不再沿 spline 向前检测。 没有必要沿 spline 检测前方。我们知道 spline 的 终点在哪里,潜在的路口交叉点就在末端。只需要检测终点前方, 不需要检测沿途每一点,直接检测终点即可。已经在获取最后一个 spline point 的 位置,还需要获取旋转最后一个 spline point 处的旋转。使用 get rotation at spline point 同样的 point index, 确保 coordinate space 设为 well 的, 然后修改这里, 清除这些节点。幸好没有删掉 get forward vector, 因为还需要从这个旋转值获取朝向。现在有了最后一个 spline point 的 位置以及该 point 的 朝向方向。取最后一个 point 的 forward vector 乘以距离,右键转换为 float, 设为一千或两千。 具体数值取决于路口 spline 与主干道 spline 之间的距离,距离较远则增大该值。若仅零一千即可。 对我而言,一千就够了。保持一千,将该方向向前投影,加上 spline 最后一个点的位置, 得到 end 的 点本身作为 start 连接如下,不再沿 spline 主点检测, 只检测 spline 末端。这意味着 current deceleration distance 的 获取方式需要调整,需要修改。可以用 get location at spline point 与自身位置比较。 从这里拖出 distance vector 节点,与当前 act 位置比较。 get act location。 我 们不想在终点才开始减速。加一个减法,当距离终点一百单位时,先判断该值是否小于当前 deceleration distance, 若不小于即不满足条件,则不需要更新。 current deceleration distance。 不 做任何处理。添加一个 branch 判断条件, 处分之接入。若为处 o 继续执行条件为处时,接入 current deceleration distance。 这里的一百与之前一致,只是移了位置,连接如下。但还有一种情况,此时 current deceleration distance 已被赋值,但距离仍然大于 max deceleration distance。 即 假设车辆在一千单位内停车,但现在距离还有两千单位,此时不应该停车,不需要提前那么远就开始减速。 max stop distance 设置为一千,等到足够近再制动。使用相同的数值判断是否小于等于 max deceleration distance。 只有满足条件才执行 stop car 以及 set current spline path 全部接通接入这个 branch。 后续整理一下,可以看到这里检测距离。基于 current deceleration distance 按需调整 以及 max 的 判断,满足条件则制动,这样可以接入这里。但关键是我们不想再 drive forward。 李美珍都执行 trace for intersection, 除非车辆已经接近 spline 末端,距离终点还很远时,何必执行 trace。 因此在 trace for car 之后,每帧执行加一个判断,判断为处时才执行 trace for intersection。 此时需要知道 spline 的 总长度与当前已行驶距离在 spline 上的位置。当足够接近末端时,才开始执行路口检测。 在此之前,完全没有必要获取 current follow spline at spline point。 使用 spline point 方式, 因为获取非常方便。与之前一致,从 current follow spline 获取 spline points 总数。注意,所以从一开始不向数组,从零开始。需要减去易得到总长度。 用总长度减去当前行驶距离,获取 current distance along spline 相减,判断结果是否小于等于 max deceleration distance。 若距离未到达,直接跳过,不做检测,忽略即可。 若已进入应该制动的距离范围,在检测是否需要制动。此时靠近末端,说明已接近 spline 终点,意味着需要检测是否需要完全清除 spline 之前我使用等于等于何一个范围判断,但实际上可以换成 distance vector 节点, 两个位置之间的距离同样判断小于等于某个域值。 改回七十五,看看是否正确。从我测试来看没有明显差别。我改为使用 distance 方式,只是为了保持统一。与其他地方的写法一致, 都使用 distance, 视觉上更直观。看到 distance 和小于等于就能快速理解含义,比另一种写法更直观。视觉上不够清晰,乍看之下不直观到这里属于个人风格偏好。我认为底层实际上没有差别,如果你知道有差别,欢迎告诉我。 执行 trace for intersection 后,进行这个检测,基本就可以完成清除 follow spline。 若为 true, 清除后需要知道下一条路径。因此之后执行 trace for new path, 也就是我们设置的那个一次性 trace, 用于搜索新路径。 就在这里,本教程前面已设置好了,来看看效果。车辆能看到有停止信号。 停了哇,停下来了,但停车距离太远了。确实太远。你可能会觉得问题出在 trace for intersection 里的简易版,但实际上不是。 真正的问题在于减速计算使用了 max speed 作为减速基准,但车辆并不是在以 max speed 的 行驶,而是 current speed。 将 max speed 换成 current speed, 如下连接,同时在这里加一个保险逻辑,确保万无一失。如果车辆确实需要立即停车,直接停。 检查 current deceleration distance, 判断是否小于等于零,即是否已需要立即停车。 若为处,接入一个 boolean 判断,执行其他逻辑。若不为处,则按原有逻辑处理。若为处,立即停车。跳过大量中间逻辑,直接跳到 set current speed, 基于 deceleration go 直接赋值,因为此时已经到了必须达到目标速度的时候了,已来不及按减速曲线减速。不管原因是什么, 作为保险措施直接处理好。使用 current speed 进行减速计算来看效果,减速了。看车辆在减速效果相当不错。感觉停车位置还是离终点稍远,需要确保路口 supply 点位置更靠近一些。 将这些点稍微移近一点,因为这里是通过 trace 检测。另一种方法是把碰撞核也向前移动, 有多种方式可以调整,按需选择。最简单的方式是直接移动 spline 点,简单易行。用这个方案测试再次运行减速效果顺滑多了。 看车辆减速非常流畅,然后车辆通过运行,效果很好。车辆还没有通知后方车辆出发。可以看到那辆车转弯了,朝向目标后继续行驶。最后一步通知后方车辆出发。 实现方式是当本车收到 drive 指令时,向后方检测通知后方车辆也可以出发了。但不是在 drive 出发时立即直行,而是加一个延迟, 使用随机延迟,这样效果更自然,而不是像机器一样同步启动。现实中驾驶者的反应时间各不相同。前车开始走,后面的人才意识到,哦,我也要踩油门了,然后更后面地看到前面那辆,加速后再出发。 模拟更真实的车队启动行为。回到 event graph, 在 set a new path 之后,执行额外逻辑, 添加一个 custom event, 保持结构清晰整洁。命名为 make car behind drive。 名字起得不太好,如果有更好的命名建议,欢迎在评论区留言。总之,无论 supply 是 否有效,都需要调用 make car behind drive。 如何检测以及向哪里发送通知。最简单的实现方式,进入 viewport, 给车辆添加一个新 component。 添加一个简单的新 component, 将其移到车辆后方 x 轴位置设为负五百,后方车辆应该在这个位置。当我们需要通知它出发时,包括前保险杠区域,在这个范围内则发送通知。将 same component 重命名为 behind car location, 这样就可以获取 behind car location。 调用 get word location 获取其世界坐标。当然,也可以用 get actor location 加上 forward vector, 取反移到后方同样可行。这是另一种方式,我想展示给大家不同场景下的不同实现方法。两种方式基本可以互换,至少在这个场景下可以。我喜欢展示多种做法。 有了后方位置后,执行一个简单的 line trace for objects start 设为该位置,加上 z 轴向上两百单位 作为 start 起点, n d 减去两百。稍微向下延伸不是必须,但这样 trace 有 一定的垂直范围。 object type 设为 vehicles, make array 指定为 vehicle 通道。若命中目标,则通知其行驶。 若命中 break hit result, 获取详细信息。获取所有命中信息。判断命中的是否为车辆,是否为 b p car base 类型 case to b p car base case 成功则继续。 首先不是直接通知其行驶。虽然可以直接拖出连接 drive, 但需要先加 d 类。先执行 d 类,添加 d 类,并设置随机范围。使用 random float in range, 延迟一秒到一点五秒之间,然后发送 drive 指令。这是我测试后认为效果最好且不产生问题的时间范围。就用这个。当本车收到 drive 指令时, 向后方检测是否有处于停车状态的车辆,若有通知他出发。延迟一段时间后执行。注意检测位置在调用时已确定,坠死已执行。即使本车之后向前移动,通知后方车辆的目标引用不会随之改变。来看效果。让这些车辆前进。 可以看到这些车辆全部停在路口,走了这些接着走。可以看到两辆之间有轻微的延迟,就这样有延迟,然后出发。 我在场景里放了更多辆车,其中一些速度不同,比如这辆是一千,这辆是两千,有一定的速度差异。 来看看效果。运行 simile 车辆停止了,绿灯继续通行。这些停住了,很好,这些仍然在走。不错, 再转弯。这辆应该停,停了,继续这些再走。可以看到相邻车辆之间有一定延迟。红灯停车,然后出发。这些开始走了,整体运行效果不错,在下一辆车出发前有轻微的延迟, 这辆走得比较慢,还有一些问题存在,系统并不完美,这辆车不知为何卡在了后方。再运行一遍看看, 关注左上角的输出信息,没有看到 did not find spline 的 报错,现在有一些了,但那是因为那两辆车脱轨了,显然路径上什么都没有,确实出现了问题,明显还不够完美。但主要原因我觉得是路口 spline 点放得太近了, 导致车辆的旋转对齐,反而引发了其他问题。目前这个系统并非无懈可击,但相比上一版本已有显著改善, 我会继续优化,持续迭代。再看一下这边,这次看起来好多了,这些车都在直行,可能只是随机结果再运行一次,相信有些会右转。 来看看那辆车右转了,这辆车在直行,而这些走得很慢,不知道什么原因,它们在移动,偏偏在教程演示的时候出现了新 bug。 murphy 定律啊,开发就是这么回事, murphy 总会在你需要展示的时候, 一切之前都好好的,等你要展示了,新 bug 就 冒出来了。没关系,会修好的。整体还是在进步的,这是最重要的。如果想亲自体验这个项目,可以在我的 patreon 获取。

每天一张图,人人都是顶级地边石。大家好,我是大洋。今天咱们看 a 站大佬的一幅作品,这是他用引擎还原的 呃,一个概念原画的地边成品在 a 站呢,也是得到一堆大佬的点赞。我先问你们一个问题,同样是废墟的一个场景,为什么你做出来的感觉呢?就是空旷的很,却让人觉得密不透风, 氛围感还拉满答案呢。并不是模型的好看,是它的空间层级从头到尾被摄设计师拿捏的死死的。很多人临摹这张图, 上来就抠雕像贴图,调体积,光参照,最后做出来四不像。那我问你,你真的看懂他的视觉重心了吗? 这张作品最牛的地方在于,他把所有的景物都变成了一个工具,什么意思呢?没有任何一个东西,他是主角,他们全都在服务那个真正的主体。你但凡把这个关系搞反了,画面直接也就。 同学们,请看左右两座雕像,别光看一大一小,看一整对峙对地,硬是在这个空旷空旷的场景里,给你架出一条看不见的一个中轴线,然后你看 中间那对小人,精准落在这条轴线的焦点上。所以呢,咱们再往右边看那尊 雕像,他不只是残缺,他被彻底侵蚀了,身上长满了这种苔藓,还有植被 底座已经被碎裂了,这种被自然吞食的这种过程感,比左边那种单纯的残缺呢,要高级的多。地边在摆资产的时候呢,一定要注意这种 破坏的多样性别,千篇一律,全是碎块。叶纹要顺着建筑的承重结构走,藤蔓要顺着墙体缝隙往上爬, 你得给细节一个生长的动机,而不是随机撒胡椒面,观众的眼睛会顺着你的细节方向走,这就叫引导视觉流好。第三个问题来了,你做大场景的时候,有没有设计过这种隐形的视觉动线? 还是模型?随便往地上一丢,全靠运气凑。真正会做的,地边要先确定轴线,然后再摆东西,不是摆完东西再猜重心在哪。这张图大家都说画框构图 没错,但是很多人没有注意到的点,他用的是实体画框加光影,画框加头顶,垂头三层一块锁死你的视线。前景这个拱 十五以上的遮挡,旁边压着紫黑的暗部, 旁边压的死黑的暗部是光影上的遮挡,头顶垂下的藤蔓 形成了天然的这种帘幕,这就形成了多层次的一个遮挡,把你困在这个洞里,闭着你的眼睛只能看中间的这个。 很多新手做图,前景做的太亮太清晰,结果呢?观众的眼睛不知道该看哪。高手直接用前景死黑,让你乖乖的来看主体, 我抛个问题给你,你敢不敢为了画面层次,主动把前景所有的细节全部砍掉? 新手通病就是贪心,恨不得全图每个角落都塞满细节,结果呢?全图没有一个重点,高手作图是主动做无效暗部用留白 去托主体。再说光新人不要一天到晚想着打丁大耳光术了,那是入门级认知。这张图的光影逻辑是什么呢?就是光线切割空间,用光定义舞台,唯一的那个主光 精准砸在中间的集台上面,雾效呢,只集中在视觉的核心暗部,坚决不补光不提亮。但这个绝大多数不知道的真相,那道光之所以看起来是活的,不是因为光本身,是因为光里有灰尘。很多人以为调个光角度加个体物就完事了。 错了,真正的灵魂是粒子系统里的那些极细碎的一个尘埃,加了微弱的发光和大小变化,洒在光路里,没有这些光就是死的。你要学会在光里 洒生命,空气才有呼吸感。我问你,你打光的目的照亮场景,还是遮挡多余的信息?高反这个你的作品永远都是半吊子。在精度分层这块,很多人老爱说 进虚忠实远辉,其实本质上,他即便的核心技能之一就是做信息密度控制,你想让观众看哪哪的信息呢,就会多。还有人物比例这一块,那几个小人站在,这几个小人 站在巨大的雕像和崩塌的建筑前,显得特别渺小。这种比例呢,是刻意设计的,它放大了废墟的宏伟和 人类的孤独。最后说一个全网没人讲过的点,场景的蓄势闭环,断头的雕像,开裂的石缝,爬上去的藤蔓,崩 塌的碎石。这些细节呢,统一指向同一个事件,就是曾经一个神圣的古老遗迹,但是呢,他被自然一点一点的吃掉。那几个闯进的旅行人,刚好形成两丛对冲 过去的辉煌,当下的荒芜,宏大的文明,对渺小的人类。我问大家,你做场景是在拼搏行,还是在讲一个完整的故事?细节是有方向的,你得给他一个生长的动机,观众眼睛才会跟着你的故事走。最后给大家分享 几个大佬私藏新手直接照搬使用技巧,看完立马能改改掉画面增乱平的一个问题, 第一,做大场景永远先定轴线。第二,画面边角一定要做压摁处理。 第三,体积物和光束绝不要铺满全屏。第四,别再被近虚中时远会这种空化了去控制信息密度。第五,光里一定要有 尘埃粒子,给粒子加微弱的发光和大小变化,让光火起来。第六,人物要当尺子用,用人的渺小反衬见众的宏大,拉回透视感,强化趋势。第七,场景趋势要统一破损、藤蔓、 碎石这些元素顺着建筑结构的受力方向和重力方向去分布。真正的顶顶级地边缘,从来不是对资源的苦力,而是懂得取舍, 会控节奏的能玩转信息密度的设计师。把这些吃透了,你的出图质感直接甩开九成的同行。

地边面对的不是一栋建筑,是一个村庄、一座城市、一个世界。画面里百分之七十的工作是用模块去拼。接下来告诉你场景模块化的三个逻辑,只要理解透了,以后接到任何量产需求都不会慌。模块化的本质不是做少一点, 是规划好,让一块墙能变成十面不同的墙。一个四乘四的墙体模块,通过阵列翻转叠加,能拼出七八种建筑立面。只需要五到八个墙体模块, 加上门窗、屋顶各两三套变体,一个村庄就拼出来了。用最少资产做最多场景。所有模块化场景都必须遵循大中小的三层拆法。大模块是墙体、地面、天花板决定空间格局。 中模块是门窗、立柱、楼梯决定功能和动线。小模块是管线、灯具、道具、碎石决定细节和可信度。所有模块的尺寸必须是统一的,基本单位 行业里通常用四米或两米的整数倍。所有资产在编辑器中必须严格对齐网格。做这一步,你的模块根本拼不到一起去。材质配合也是模块化的一部分。工业化的标准做法是三件套 trim sheet, 把门窗框、踢脚线、装饰条这类重复纹理合成到一张贴图上。一张贴图支持几十个模块直接砍掉几十个 draw call tiling 贴图, 大面积墙面、地面用的可平铺纹理,顶点色和 mask 给材质加脏字,湿度、边缘磨损,让同一张贴图在不同位置看起来完全不一样。但全是模块拼的场景看起来不会千篇一律吗?所以要用上破重复感的三个工具打伞。 同类模块至少做两到三个变形,再通过旋转和缩放打乱规律材质变化,微调粗糙度,做色相偏移,用 mask 控制污渍分布。 同一个模块在不同区域可以看起来完全不同。贴花在模块衔接的地方放破损锈迹、青苔,贴花做破型处理,这是让模块化场景看起来不重复的最快方法。

大家现在看到的是五百辆车沿样条行驶,跑在一百二十帧, 前提是我不碰鼠标,编辑器操作会拖慢它 只要单纯跑这套系统,帧率就稳定在一百二十左右。但请记住,这还是在同时开两个虚幻引擎加 obs 录屏的情况下,所以已经相当不错了。我用模拟 simulate 而不是运行 play, 是 为了带大家飞到场景镜头看看。 实现方式是,车离得越远,更新频率越低。 我们基于距离优化更新,靠近角色的车更新更频繁。 事实上,我可以直接进到实际游戏里运行,现在往上飞。大家看,上面这辆跑得很稳, 你能一直看到最远处车辆仍在移动。它们只是更新的更少。更少指的就是更新次数更少。我还专门做了容错,确保系统不会因此崩溃。这点对我很重要。 我立刻想到一个隐患,你正玩着右上角显示一百二十帧, 可只要我切出虚幻引擎,帧率就调到三。其实它没真以三帧运行, 只是引擎判定窗口失去焦点,进入非激活状态。但你看,即便我切到外面,引擎也会冻结一切,停止所有更新, 等我们切回来再无缝继续。即便遇到严重卡顿,性能瞬间暴跌也没关系, 系统不应崩溃。这很关键。我们会在本系列下一部分做几处优化,让系统更高效。我们开始吧,这就是目前的搭建。它虽然不错,但偶尔会有车找不到路径, 就像你刚看到的,有几辆闯了红灯,这辆已经偏离样条,并不完美,偶尔还是有问题。 我的修复思路是检测自身到目标点的距离,距离再缩短,说明正接近,需要切换下一条样条的节点。 若距离开始变大,即再增加,就说明我们错过了切换点。如果发生这种情况,就标记它不对。我们没错过,我们没错过,已经成功找到它了。只是车辆的落位只是车辆的落点,取决于更新方式,可能不够贴近。 这也能顺带规避另一个隐患,车辆在行驶中改变帧率, 所以我们要适配这个逻辑,仍然在车辆蓝图里处理。在设置当前样条组建处,我们要加一点逻解, 当车通过切换点时,就把它指派过去。我先把这块往旁边挪,腾出操作空间。首先要做的确保这段逻辑只触发一次。我拖出一个 dunes, 等指派完实际样条后把它重置 另一件事,之前为新路径做追踪时设置的朝向这里也要保留。 我直接把那段复制过来放到这里。我把它接在 d o n s。 之后把车辆朝向设为贴合样条方向。和之前一样, 起点用 actor, 位置,目标用命中组建的世界坐标和之前一致。 我把他俩的输入顺序调换一下,因为只是做距离向量顺序,不影响结果。总之,我们补上了和追踪新路径十一致的朝向设置, 然后人判断是否在某距离内。原来成了二,现在去掉它。只按当前速度判断是否在范围内,以避免突跳。 snap 这样能避免潜在突跳,但超出范围时我们仍会强制吸附, 所以某些情况下会有轻微突跳。不过并非总是如此。接着是那个是否每次都在范围内的检测。 我们要在这里加一点额外逻辑,逻辑上我们需要一个新变量,记录到当前路径的距离。 我把它设为 float 类型,翻译后把默认值调到极高, 这样第一次检测到的值币小于它,从而被覆盖。做法是从分支的 false 端判断, 若我们与目标点之间的向量距离大于道路径的距离, 说明在远离。正常情况下,它应该不断缩小。所以我们在这里用分支节点 false 端不尽延迟,而是进这里继续判断。 若人在靠近且小于当前记录距离,就把道路径距离更新为这个新的距离向量。 我重新排了版,以便看清。设置完之后像之前那样按设定帧率,等待结束后再复查是否仍在靠近。等待结束后再查一次是否仍在靠近。 若走到触端,即正在远离,我要先校验当前样条是否有效。先确认当前跟随样条是否有效。右键转换为验证获取,看它是否有效。 此时本应早已离开当前样条,所以若无效,就去设置新样条。若仍有效,说明在真正驶离当前样条前就触发了检测,那就继续沿距离路径追踪等待,直到样条失效为止。 这算一层保险,万一当前样条越过下一条起点,即样条过充,他仍会持续追踪并强行吸附回去, 但至少不会彻底崩溃。通常不应有重叠样条,但这层防护以防万一。 好了,现在只派当前样条,我们还要把道路近距离重置回那个极大之只要设的足够大,大到绝不会误判就行。 设置完后,把 dos 重置,我直接拉一根线回到起点,接上重置,再稍微整理布局,这就是新搭建,确保足够贴近,即便过充也能正确指派。 既然已经搭好,下面这段逻辑类似,我们直接附用这套系统。唯一区别是检测方式不同。这里只需调用设置当前样条,组建命中,组建命中 actor, 接样条 actor, 然后把原来那堆全部删掉,改由触端接过来附用同一套逻辑,没必要写两遍, 没必要写两遍。现在进入模拟,看看是否还有车找不到样条,不循迹或发生交叉问题。 当然,使出场景那辆仍会提示找不到样条,但现在现在绝不会有车误入不该去的车道。 问题基本彻底解决,质量相当好。大家看这些车都没问题,有辆在上扬条时轻微吸附了一下,我再跑一遍,让你看清楚。现在一切正常了, 这些车先停下一批跟上毫无问题。这个毛病终于彻底修好了,不过车辆到红灯仍会急停,这留待以后处理。我们还会加黄灯等。逻辑 先一件件来,进度很重要,所以现在都搞定了。接下来要修的是,有时车会被落下,当一辆车起步,后车停下时,时机凑巧,可能导致后车永远不再前进。 我们要修掉它。之前用的是从后车处向下的一条单线追踪, 问题是它顾及不到临门一脚才靠近的车, 也顾及不到弯道斜向切入可能过冲或欠冲的情况。我们改成从车体向后做球体追踪,给一点半径来容纳角度偏差。 主逻辑类似,区别是用按对象球体追踪,非多重, 不用多重。起点取自身用获取 act 位置作为起点, 我们向后追踪,取 actor 前向向量,得知朝向,再决定向后追踪的距离。我向后追踪两千单位, 把向量取负就从向前变成反向。基于当前位置,加上这个反向向量,就是追踪终点。 追踪对象仍是车辆。把对象类型接过去,我把它挪下来,并勾选忽略自身,避免命中自己,然后把这些接好。 顺便说一句,按住 ctrl, 可以 把引脚从一个拖到另一个。现在删掉旧的,把新的挪上去。重连 让后车行驶的逻辑基本不变,只是改成了球体追踪,给约两百的半径,以容纳转弯、直行等各种情形。 另外,一到一点五秒的间隔偏长,我改成零点五到一秒之间,其余不变,其余没问题,只是需要加个注示。 原逻辑是说行驶时才触发,但如果车根本没停,只是减速后又被命令继续加速呢? 既然本就在行驶,我们改为加速时触发,并非仅从静止起步时才触发,这更合理。 因为前车一开始加速就该通知后车,前车再提速,你也加速, 按住 ctrl 加 x, 把它移到加速段。计时器结束后,让后车行驶,同时设置加速时要确保减速被取消。 减速段在下方有停车计时器,我把它接出来 用,通过锯柄清除并失效定时器。总之,只要下达加速,就务必停止减速,避免两者冲突,否则你刚减速,前车又起步。若只让加速而不停减速,二者就会互相打架出 bug。 同理,减速时我们会在速度归零后停掉向前行驶,计时器却没停独立的加速计时器, 所以两处都要停,可能要在多处用到。我把这两个一起选中,右键折叠为函数,命名为停止行驶计时器。函数里停掉向前行驶计时器,再把加速计时器一并停止, 速度真正归零时才能干净停下。现在看减速机制,越接近目标越慢, 到某个点其实就基本不动了,技术上还在以极小速度移动, 因此我留一点余量在五单位内,就视为足够进, 不必精确到零,然后直接归零或达目标。速度做法判断是否落在减速度,目标加五 就视为足够进,直接设零。 若目标是二十或二十五,就设成二十,数值很小,视觉上察觉不到。你可以自行调, 目的是消除那些看不见却仍在后台计算的情况。既然到了这一步,就把判断改为小于等于零来停止加速计时器。 再看。现在所有车仍能正常停下, 你几乎看不出是先减速再硬停。到红灯处仍会急停,不过后面的车都没问题, 仍顺畅提速。黄灯的事稍后处理, 接下来是不做无谓之事。目前向前行驶函数无论是否沿样条,都会做车辆追踪, 且按更新频率触发,其实没必要这么频繁,我们大可低频处理。 所以我移除上下两处的追踪, 改成在行驶时触发加速启动后挪过来新建一个定时器,用按函数名设制定时器,我直接复制一个,方便些。函数名改成车辆追踪 trace for car, 设为每零点一秒一次,每帧最多一次,当然要能停止它。我右键提升为变量,命名为车辆追踪计时器,于是它每零点一秒,每帧最多一次的运行。 停车时也要停掉这个定时器。在减速停车的停止行驶计时器里, 把向前行驶、加速以及车辆追踪计时器一并停掉,确保所有定时器都关闭。 既然不动了,就没必要查前车,直接停掉。若没完全停,它会像之前一样继续检测前车,只是现在每秒只查十次, 经我测试,十次完全够用。运行看看一切如常。 它能检测所有车,也能停止检测。我们打开车辆追踪示设为持续时长会至零点一秒,与定时器一致, 你会看到它的闪动,因为每零点一秒才更新一次,说明工作正常。所有车都在各自车道继续行驶。好,现在迎来这次的大改动, 让车辆离角色越远,更新越不频繁。 这样只有近处的车跑满帧率,远处的可以降到每秒十帧左右。它们不需要移动那么多,也不需要持续更新,这样前景车辆流畅,又不必承载过多计算量, 同时处理卡顿峰值。若当前帧号时超过零点一秒,就暂停 不动车不动路口,不更新任何东西,直到帧率回升到十帧以上。 为此要修改获取帧率,以改变更新时机,并开启每帧最多一次,这会大有帮助。在帧率门控里,原本只用更新帧率,再用一除以它得到模拟该帧率的定时器间隔, 但现在还要知道距离,用获取玩家碰取玩家位置, 在与车辆位置做距离向量,得到两者间距,即两者之间的间距。多人游戏我不在行,这部分交给专家。在评论区指点如何适配。 如果你是多人游戏专家,欢迎在评论区告诉我如何适配。眼下我按单人模式搭建,一旦拿到距离,就能给它划定一个范围,用限幅射范围 map range clamp 输入一个范围输出,一个范围,按数值落点映射输出。 比如范围设五千到五万,单位 五万其实相当远,但先这样设置 输出,若全零就不对,我们要的是五千内跑满帧率,应限幅小于等于五千都输出满帧率 最远时,输出时真没秒,这正是我要的。 于是原本接更新帧率的地方,现在改接这个映射结果。但我还要把它和当前的 delta 时间对照,因为若有卡顿,我想感知到右键或许世界 delta seconds, 它就是锯上一帧过了多久, 用最大值节点取,二者叫大者让大的那个生效。这样若发生卡顿,比如返回整整一秒,就采用这个数,而非帧率, 我们就知道有点偏高了。回到行驶函数,检查帧率,看它是否小于零点一, 即十分之一等于零点一,小于零点一说明正常无卡顿,继续之前的更新。 若卡顿走 force, 就 等待零点一秒再试。 零点一秒是整个定时器系统允许的最小间隔,也是起步时的处理,这只是在起步行驶时保证帧率稳定。 那已经在行驶中呢?看加速段, 加速时也许获取帧率,判断,只要不大于零点一就继续, 那说明这里的帧率没问题。当然减速同理,减速时若人高于零点一, force 则继续, 一旦卡顿就停止加速与减速。现在可能只是单纯行驶,所以向前行驶函数里也要检查帧率, 同样判断不超过预值,否则在卡顿时完全停止向前行驶,停止加速,停止,一切 看现在效果运行,并拉远镜头。这些车在持续更新,我切出虚幻引擎,全部静止。路口还在更新,还没让它停, 但切回虚幻引擎,车辆立即从原状态恢复。显然路口还有问题,显然让路口也在卡顿解除前停止更新。 这就来到路口蓝图,这里是它直行停车行驶的地方。一切就绪, 它也已开启。每帧最多一次。很好,但要改下一个交通灯。这段卡顿时不该执行。它 和前面一样去获取帧率并判断。区别是这里不用帧率,只用 dota 时间 用获取世界 delta seconds, 只查卡顿本身,判断它是否大于零点一,也就是是否正在卡顿。用分支,若卡顿就暂停,它 不再更新。我把节点挪开,右键提升为变量,命名为交通灯计时器,在此赋值下面取出交通灯计时器, 用通过锯柄暂停定时器把它暂停,使其停止运行,然后让它等一下再复查。 这里用零点五秒延迟,而不是之前用的零点一秒。多给点余量,让正在过路口的车先完成动作,让出空间再恢复更新。 每半秒检查一次是否还在卡顿,若已解除,就通过锯柄恢复定时器,并继续原有逻辑 完整流程。卡顿暂停定时器等半秒复查恢复并继续来看效果。运行非高看大局,再切出。所有车和路口都禁止 切回,一切恢复正常。看起来不错,现在继续顺畅运行。不过有件事要注意,我切出后再飞远人在查前车。 其实没必要,我们直接停掉这个追踪,回到车辆积累在车辆追踪处,应只在帧率良好时才做, 像前面一样加,获取帧率大于零点一分之 false 端下才执行,即无卡顿时才追踪, 再运行飞高看看,等它们跑一会儿 再切出一切暂停,不再做追踪,可示画复位路口之类全停了,切回后无缝继续。显然若某辆车当时是绿灯,它仍会继续通过。 这正是半秒余量的用意,让朕要穿越或刚开始穿越的车先完成再继续下一批。 我对卡顿期间路口轻微重叠的隐患比较宽容, 因为卡顿本就少见,帧发生也只算小问题。还有我漏做的减速和加速段 都要开启,每帧最多一次。总之,现在跑的定时器全部设为每帧最多一次,务必每个都勾上。我还更新了车辆,加了更多轨迹, 并让它们能转向,免得总挤在同两条车道。现在运行非高看实景, 帧率随玩家位置变化,这很棒,车辆沿各自路径环绕行驶,按需停车,一切顺利,随时切出全部暂停,稍后切回 卡顿前已是绿灯的最后几辆车,人走绿灯。这半秒余量让系统平稳接续。就这样,我们改进了不少, 当然如开头所见,飞得很远时它们会变慢。系统人非完美,但我每次都在进步,改进更多东西。 对了,我知道自己搭的是美式标准路口,很多人想看环岛,若我能想出好办法,接下来可能会做 环岛的关键是判断车是否诊断都在环内,是否有空位并入。 我先研究怎么在本系统实现。

用激光把江苏超大的五 a 级景区建模后,用游戏的方式打开,导入虚幻引擎舞搭建场景 江南园林景区摸金枝老板的绝密文件地点,苏州桐篱古镇退资源地面视角 空中专业航拍无人机扫描地面是激光雷达空间相机扫描后期算法生成高精度模型,导入游戏引擎进行开发,高精度一比一扫描复刻整个数字景区。地点,苏州桐里古镇景区 绝密桐里古镇街道绝密江南小镇街道 画面演示的园林小岛在苏州桐庐古镇罗兴洲开发过程用 ai 大 模型能力 web 秃顶,创造出一个可运行、可交互的三 d 数字景区产品。 后期将程序打包后部署到服务器,支持手机和电脑打开网页,小程序直接运行模型压缩到二十兆,做到网页端上实现五 g 网,一到两秒就可以瞬间加载出来。 还接入了景区的各种天气数据,实现真实数据实时同步,可以控制任意视角高精度观看景区沙盘模型。

hello, 大家好,这里是我 ryan 之前有一期视频呢,我让 codex 把虚幻引擎的所有渲染命令给汇总,在这个工程中呢,我已经将上次汇总虚幻引擎所有渲染命令的 scale 放在里面了,然后已经让 ai 应用了最高的渲染配置。 在渲染设置和控制台命令中呢,已经让 ai 把所有数值拉到最高,也应用于影视级的渲染,并开启了路径追踪,这样的话渲染效果会更好。 同时呢,我又开发了一个 m c p 插件, ai 呢,可以直接通过虚幻引擎去制作虚列并打上关键帧,并且 ai 呢,可以自动使用 movie render q 进行渲染。同时 ai 也可以生成一些高质量的预设, 比如这是我刚刚让 ai 生成的一个四 k 的 路径追踪的一个渲染预设。然后这个渲染预设可以点开看一下,它已经 将所有的关于路径追踪的参数已经配置好,比如说添加了这个路径追踪渲染器,然后抗锯齿呢,因为刚刚我只是让 ai 渲染一个静态的单张图片,所以它把空间裁量拉的很高,然后时间裁量的话只开了一。然后这边控制台命令呢, ai 直接帮我写了三十六个,比如说要把所有的配置拉到影视级,还有一些光照的参数都拉的很高, 以及 ai 自动帮我配置了渲染的分辨率和输出路径,当前这个场景中只有这一个物体,我让 ai 试图帮我添加一个摄像机,然后新建关卡虚列并创建关键帧。这个是 ai 生成的一个摄像机,虽然它找的角度不是很好哈。 然后我们播放一下 ai 直接生成的一个虚列,我,我的要求是让它绕这个物体一圈, 我们要给他提一些运镜的需求,所以他现在做的是特别的简陋,也特别的丑哈,但是无所谓,如果后面慢慢的使用 ai 去调教的话,应该是可以 k 出一些简单的动画的。 关于渲染方面呢?关于渲染方面呢,我让 ai 学习了虚幻引擎的透明通道渲染方法, 这个场景中是我摆了两把枪,我想单独只要这两个枪的模型,然后 ai 去学习了怎么去渲染透明通道,它使用了一个最高质量的方法,使用这个 composter 合成器, 就类似于虚拟制片的方法,单独把这两个物体给抠出来,这样的话它的抠图效果是最好的,而且 比如说一些渲染的粒子啊,粒子抠图或者是半透明的效果也是最好的,而且它这样子渲染出来的话,不会有一些色差的问题。同样的,我告诉哎,让他帮我渲染,他就给我输出了一个最终的成品四 k 的 起用路径,最终渲染的透明底的图片。 这套流程使用下来呢,对我的帮助是在于渲染的配置和操作方面。在之前做循环引擎渲染的时候呢,我要调整一个适用于我电脑的渲染参数,其实还是挺麻烦的,因为我既要保证效果,也要保证输出的效率。 现在 ai 可以 直接帮我配置这些命令,然后我可以直接让 ai 去帮我监管幕维 random q 渲染器,这样我可以直接跟 ai 说帮我渲染,我就可以去 做我其他事情或者是睡觉。渲染完成之后,他直接会通知我,如果中途出现了渲染崩溃, ai 也可以检测到,他可以直接帮我去检测问题或者是调整配置,然后进行重新的渲染。 以上就是这期视频的全部内容,我所使用的工程以及训练的 scale 也会同步到 github 上,同时百度网盘或者是我的官网也可以进行下载。我们下期视频,再见。拜拜。