自由学习记录(204)

“mom / time” → /m/:嘴唇關閉,氣流走鼻腔。
“no / ten” → /n/:舌尖頂上齒齦,氣流走鼻腔。
“sing / bank” → /ŋ/:舌根靠近軟顎,氣流走鼻腔。

肺部提供氣壓,聲門/聲帶控制漏氣速度,口腔、舌頭、嘴唇、軟顎把氣流塑形成音。語音呼吸本來就是「快速吸氣、長時間控制呼氣」的模式,而不是像運動那樣大口換氣。Hal Science

如果每個 /p t k/ 都噴太大,或者在詞尾加一個多餘母音,例如把 stop 讀成 stop-uh,就會額外耗氣

/h/ 尤其像帶聲道形狀的呼氣,讀太重會很耗氣

/m n ŋ/不是最耗氣,但會讓你明顯感到「頭面部參與」

bummer
└─ 掃興的事 / 讓人失望的小壞事

hammer
└─ 錘子;用錘子敲

hammered copper
└─ 被錘打過的銅 / 錘紋銅

media
└─ medium 的複數:多種介質 / 多層材料 / 多個傳播環境

is propagating
│ 正在傳播 / 前進 / 擴散

在渲染/材質/光學語境裡,可能包括:

light propagating through media
├─ absorption
│ 被吸收,能量減少,顏色變暗
├─ scattering
│ 被散射,方向變亂,例如霧、牛奶、皮膚次表面散射
├─ refraction
│ 折射,方向改變
├─ reflection
│ 被反射回來
└─ attenuation
隨著距離衰減

You’re all looking at me
└─ 你們都在看著我

like I have horns growing out of my head
├─ like
│ 好像,好像是……一樣
├─ I have horns
│ 我長了角
└─ growing out of my head
從我頭上長出來

Substrate Thin-Film → Thickness 不是普通「毫米 / 厘米級的 coating 厚度」,而是 光學薄膜厚度,通常就是奈米級或接近可見光波長的尺度。

UE 官方 API 對這個節點的描述是:Thickness controls the thickness of the thin film layer coating the current slab,也就是控制覆在當前 slab 表面的 thin film layer 厚度;官方 Substrate overview 也說這個 helper node 是根據 thin film parameters 計算 F0 和 F90 的 specular parameters。Epic Games Developers Epic Games Developers

關鍵是:thin film 在光學裡不是「薄到肉眼覺得薄」而已,而是「薄到會和光的波長產生干涉」。可見光大約是幾百奈米量級,所以這個 thickness 會落在幾十到幾百奈米,甚至更高一點的微米級邊緣,而不是 0.1 mm、1 mm 那種宏觀厚度。Epic 社群教程裡有一個直接例子:Substrate Thin Film node 裡 Thickness = 0.02 被說成等效於 200 nm 的薄膜厚度。Epic Games Developers

所以如果這個 Thickness input 裡:

1.0 = 10 µm = 10,000 nm

那麼:

0.1
└─ 1 µm = 1,000 nm

0.01
└─ 0.1 µm = 100 nm

0.02
└─ 0.2 µm = 200 nm

0.05
└─ 0.5 µm = 500 nm

這就對上他前面講的 on the order of nanometers:他想做的是薄膜干涉,真正敏感的範圍通常是幾十到幾百奈米,而不是 10,000 nm 那麼厚。

Multiply(0.1) 就是這個意思:

Thickness source value
└─ Multiply by 0.1
└─ 把原本太大的 thickness 範圍壓小,再送進 Substrate Thin-Film 的 Thickness

官方 API 對這個 pin 的說法是:0 means disabled,1 means a coating layer of 10 micrometer,unitless,default = 0。也就是說,這個輸入本身是 unitless scalar,不是直接填「奈米」或「微米」。Epic Games Developers

藍光的波長約為450nm

紅光的波長是700nm

可見光在380到780nm

都是nm單位,晶體管也是nm單位,比光的波長要小的多//...................

4nm / 4N / 4NP:是「製程世代名」。
實際最小金屬線距、gate pitch 這類尺度,常常是 二十幾到五十幾奈米級,不是 4 奈米本身。公開整理資料中,TSMC N4/N5 類節點的 gate pitch、metal pitch 量級大致落在數十 nm。Wikipedia+1

SRAM bitcell,也就是片上快取裡存 1 bit 的小單元,常見是約 0.02–0.03 μm² 量級。換算成正方形邊長,大概是 140–170 nm 左右。但這不是一顆電晶體,而是一個存儲 bitcell,通常包含多個電晶體。

英偉達常說的是:它的 GPU 裡塞了幾百億到兩千多億個 transistor;單位常用 nm,但 “4nm” 是製程節點名稱,不等於電晶體真的只有 4nm 大。芯片裡最小的功能單元是 transistor,實際尺寸大約是奈米級到數十奈米級結構的組合。

核心不是 coating 厚度本身,而是這個:

光進入薄膜後
├─ 一部分在上表面反射
├─ 一部分進入薄膜
│ └─ 到下表面再反射回來
└─ 兩束反射光重新疊加
└─ 如果相位差剛好對上,就加強某些顏色;抵消另一些顏色

10 µm = 10,000 nm too high 的意思是:

對薄膜干涉來說,10 微米已經比可見光波長大太多倍了。
他想要的是幾十到幾百奈米那個區間,而不是 10,000 奈米。

goldsmith
= 金匠,做金器的人

silversmith
= 銀匠,做銀器的人

locksmith
= 鎖匠

blacksmith
= 鐵匠,尤其是用火、錘子、鐵砧加工鐵的人

And the cool thing about steel
is that, as you heat it up,it creates a layer of
iron oxide on the surface.And as it gets hotter
and hotter and hotter,it creates a thicker and thicker
layer of iron oxide in the zero to 1,000-nanometer range
, which
gives us thin-film interference.

也不算完全薄,其實是有厚度的,可以接觸的,但不太容易直接接觸的$$$$$$$$$$$$$$$

膜、层、镀层、沉积层

these precombustion chambers
├─ pre- = before,预先
├─ combustion = 燃烧
└─ chambers = 腔室
= 预燃室 / 预燃烧室

浅稻草色。

blue
├─ pale blue 浅蓝
├─ deep blue 深蓝
├─ violet blue 蓝紫
└─ purple 紫色

downright
├─ 1 來源層
│ Germanic / Old English 系
│ down + right 原本有“直接、彻底、毫不拐弯”的感觉。

├─ 2 使用圈層
│ 日常 / 口语 / 强调语气
│ 常用于加强负面判断,也可以加强正面判断。

downright dangerous
= 简直危险 / 真的很危险

downright stupid
= 蠢到离谱 / 完全愚蠢

downright beautiful
= 真漂亮 / 漂亮得很直接明显

means that, if you have two
slabs on top of each other,but one of those slabs
isn't visible, you're not paying to light that slab.

這個很牛啊,,,,,,,,,,,$$$$$$$$$

So I got to put snow on top
of everything in my scene without having to pay any additional
cost because the snow wasn't visible.
 

UE 不是隨便用一個抽象顏色漸變去假裝薄膜;它確實有按 thin-film interference 的光程差 / phase 去算反射顏色。
但它也不是完整波動光學模擬,而是 real-time shader approximation:把薄膜干涉結果壓縮成新的 F0 / F90 specular color,再交給 Substrate Slab BSDF 使用。

源碼鏈路是:

Substrate Thin-Film node
├─ C++ material expression
UMaterialExpressionSubstrateThinFilm::Compile
│ 讀 Normal / F0 / F90 / Thickness / IOR
│ 然後呼叫 Compiler->SubstrateThinFilm(...)

├─ HLSL translator
FHLSLMaterialTranslator::SubstrateThinFilm
│ 生成 shader call:SubstrateGetThinFilmF0F90(...)

└─ shader 實作
ThinFilmBSDF.ush
真正做 Fresnel、OPD、phase、sensitivity、XYZ→RGB

C++ 這邊先證明它不是普通材質混合節點。Substrate Thin-Film 會把 F0、F90、Thickness、IOR 編譯成 HLSL 輸入;如果 Thickness 沒接,這份 source 裡 fallback 是 1.0f,IOR fallback 是 1.44f。最後它呼叫 Compiler->SubstrateThinFilm(...)

然後 HLSL translator 會產生這個方向的調用:

SubstrateGetThinFilmF0F90(dot(Normal, CameraVector), F0, F90, Thickness, IOR).F0/.F90

這裡已經能看出幾件事:它用到了視角方向 dot(Normal, CameraVector),不是只看 Thickness;輸出也不是一個完整 BSDF,而是 F0 或 F90。也就是說,它是先算「薄膜干涉後的 specular 參數」,再把這些參數接回 Slab BSDF。

真正的薄膜數學在 ThinFilmBSDF.ush。Substrate shader 本體有 include 這個檔案,所以這不是 editor-only 的假節點,而是 shader 路徑的一部分。

核心證據在這裡:ThinFilmEvalSensitivity(float opd, float shift) 直接把 opd 轉成 phase,裡面有 cos(... phase + shift) 和 exponential sensitivity fit。這不是單純 lerp 顏色,而是在用光程差導致的相位變化去估算不同光譜對 XYZ 顏色的貢獻。

更直接的是 F_ThinFilmRef。註釋說它是 thin-film iridescent microfacet BRDF 的 reference implementation,並且會先從 F0/F90 推回 complex IOR,再處理 air / thin film / regular material 三層界面。Thickness 在這裡被轉成 Dinc = ThinFilmTickness * 10,註釋明確寫:Thickness 是 micrometer,範圍 0–10 µm,也就是 0–10,000 nm。

它接著做兩個界面的 Fresnel:第一界面是 air→thin film,第二界面是 thin film→底層材質,然後算:

OPD = Dinc * cosTheta2

並把兩個界面的 phase shift 合起來。這就是你問的「是不是有按光程差算」的核心證據。

後面它不是只算一次,而是分成 DC term 和 m = 1..3 的干涉項,用 ThinFilmEvalSensitivity(m * OPD, phase) 累加,最後從 XYZ 轉 RGB。這就是在用光程差引起的相位變化去算可見反射顏色。

但要注意:UE 也有簡化版 F_ThinFilm。源碼註釋明確寫,這個 simplified version 依賴 Schlick Fresnel,並且「不考慮 Fresnel phase shift 和 polarization」。也就是說,UE 不是在做完整物理波動光學,而是在性能可接受的範圍內保留薄膜干涉最重要的視覺因子。

簡化版仍然不是隨機抽象。它也算 cosTheta2OPD = Dinc * cosTheta2,然後在 m = 1..3 的 loop 裡用 ThinFilmEvalSensitivity(m * OPD, m * phi2) 累加結果。只是它省掉了偏振和更完整的 Fresnel phase 處理。

Try Get Pawn Owner node in Unreal Engine is a built-in Animation Blueprint function . It retrieves the specific Pawn currently using

美國政府把 Fable 5 / Mythos 5 的自主編程與漏洞發現能力看成潛在國安與網攻風險;Anthropic 認為這個理由過度,但仍必須執行。

填 Server URL 時,連線來源是 OpenAI/ChatGPT 的服務端,不是你本機瀏覽器本身。所以:

ChatGPT 雲端
└ 請求 127.0.0.1:8000
 └ 會指向 OpenAI 那邊自己的 localhost
  └ 不會指到你 Windows 電腦上的 127.0.0.1

幻覺都能說到這地步了,至少也是有人信了

JSON Server 通常指 json-server 这个 npm 工具。它的作用是:用一个本地 db.json 文件,快速生成一个假的 REST API,用来给前端、小程序、App 做接口联调。官方 GitHub 的描述是 “zero coding” 生成 fake REST API。​编辑GitHub

它不是正式后端,也不是数据库服务器。它更像是:

前端开发阶段的假后端
└ 你还没有真实后端接口
 └ 但页面已经要请求数据
  └ 于是用 db.json 临时模拟接口返回

比如你写一个 db.json


JSON
{
  "posts": [
    { "id": 1, "title": "hello" },
    { "id": 2, "title": "world" }
  ]
}

启动后,JSON Server 会自动给你生成类似这样的接口:


GET    /posts
GET    /posts/1
POST   /posts
PUT    /posts/1
PATCH  /posts/1
DELETE /posts/1

也就是说,你不用真的写 Node.js 后端代码,它就能模拟增删改查 API。

UE 觉得你的本地缓存没有很好地帮你省时间。

你在 UE 控制台 / cmd 里直接输入的命令
= 当前进程临时生效
= 关掉 Editor 后通常不持久

“露肩披片/上臂外侧披布”

shoulder_drape_* 是因为这类设计通常可以叫 shoulder drape / upper-arm drape / off-shoulder sleeve panel。

担心自己把父子级整理提前做了

thigh_l  = 大腿
calf_l   = 小腿
foot_l   = 脚
ball_l   = 前脚掌/脚球
toe_l    = 脚趾

如果 Blender FBX 导出勾了 Only Deform Bones,而这些 IK 骨 Deform=false,它们可能不会进 UE Skeleton。

具体到 Orientation Warping:

  • SpineBones 用来分摊/反向旋转身体,让上半身不要跟着下半身完全扭走。
  • IKFootRootBone 会被节点旋转,用来承接下半身方向变化。
  • IKFootBones 会被反向补偿旋转,保持脚部 IK 目标方向/位置关系稳定。

  1. 先旋转 root
    让角色身体整体朝目标移动方向调整。

  2. 反向旋转 SpineBones
    spine_01 / spine_02 / spine_03 这类骨骼会分摊反向旋转
    效果:身体下半身转了,但胸/头不会完全一起扭走,可以保持更像“上身看前方、下身调整步伐”。

  3. 旋转 IKFootRootBone,再反向补偿 IKFootBones
    ik_foot_root 会跟着 orientation angle 旋转一部分。
    ik_foot_l / ik_foot_r 再被反向旋转。
    效果:脚 IK 目标保持更稳定,不会因为 root/body 被转向而让脚目标也歪掉。

可以用一个简单例子理解:

原动画:角色向前跑 实际移动:角色向右前方跑

没有 Orientation Warping 时:

身体仍按原动画方向跑,或者整个人硬转 脚步方向和移动方向不匹配 脚容易滑、扭、交叉感明显

有 Orientation Warping 时:

root/下半身转向右前方 spine 反向补偿一点,上身不至于被拧得太死 ik_foot_l/r 保持脚目标稳定 脚步更像顺着移动方向走

Orientation Warping:
  需要 ik_foot_root / ik_foot_l / ik_foot_r 存在
  用它们做脚目标旋转补偿
  和是否有权重无关
  和鞋底接触精度关系较弱

Foot Placement:
  用 FKFootBone / IKFootBone / BallBone / IKFootRootBone
  更关心脚底、前脚掌、地面距离、trace
  高跟鞋影响更大

节点确实带了 Tag,例如 PoseHistoryOffsetRoot,而且 PoseSearchHistoryCollectorOffsetRootBoneMotionMatchingOrientationWarping 都在这套图里。

别的函数会通过 Tag 找它们。

Motion Matching 节点内部还有一个子图 / Blend Stack Graph。

宿主链

ABP 不能凭空得到 Level 里的任意 Actor。

Print String 节点
└─ 节点本身不是函数
└─ 它是一个“调用 UKismetSystemLibrary::PrintString 的图形节点”
└─ 节点上有 Pin、默认值、显示状态、是否展开高级 Pin、注释、断点等编辑器信息

Switch on Int 节点
└─ 背后不是一个固定形状的函数调用
└─ 它的输出 Pin 数量可以在 Details 里改
└─ Epic 文档里也明确说 Switch 节点的 Default Pin 可以在 Details tab 里通过 Has Default Pin 控制。​编辑Epic Games Developers

Animation Notify
└─ 贴在 Animation Sequence 时间轴上的事件/区间
└─ 作用是“这段动画播放到这个时间点时,触发某事”
└─ 例如脚步声、落地特效、攻击判定窗口、重置布料/AnimDynamics、ABP 里的 Notify Event
└─ 它不是调试工具。

“和 Animation Sequence 同步发送/接收事件”,并且 Skeleton Notify 可以在 Animation Blueprint 的 Event Graph 或 Transition Graph 里变成事件节点。​编辑Epic Games Developers+1

CHT_CMCCharacterAnimations 正在按这些输入判断:
 └─ State Machine State
 └─ Stance
 └─ Gait

Event Possessed 為例,它不是藍圖隨便生成的。它來自 APawn 裡的 C++ 函數:


C++

APawn::ReceivePossessed 是「Pawn 被 Controller possess 時呼叫的事件」,而且只在 server 或 standalone 觸發。​编辑Epic Games Developers

AController::Possess(Pawn)
Pawn->PossessedBy(NewController)
 └ 觸發 ReceivePossessed(NewController)
  └ 走 UObject::ProcessEvent
   └ 找到這個 Blueprint 是否覆寫了該事件
    └ 執行你 EventGraph 裡的 Event Possessed

Result Type = Object Of Type
Result Class = AnimationAsset

SpawnActor / PlayerStart / GameMode 生成 Pawn
└ 只是把 Pawn Actor 生出來

Controller Possess Pawn
└ 才是「誰控制這個 Pawn」

ReceivePossessed / Event Possessed
└ 給 Blueprint 一個入口:Pawn 已經被 Controller 接管了

Client RPC / Replicated To Owning Client
└ 依賴這個 Pawn/Controller 的 owner 關係,才能知道發給哪個 client

RPC = Remote Procedure Call,中文就是「遠程過程調用」。

我在這台機器上調用一個 Event / Function
└ 但真正執行位置在另一台機器
 └ 例如 server 叫 client 執行
 └ 或 client 叫 server 執行
 └ 或 server 叫所有相關 client 執行

Chooser Table
└─ 输入一组上下文参数
 └─ Object 参数
 └─ Struct 参数
 └─ Enum 参数
 └─ Bool / Float / Name / Tag 等条件
└─ 按行匹配条件
└─ 返回一个 Result
 └─ 可以是 AnimationAsset
 └─ 也可以是别的 Object / Class / Struct / 数据

Parent class: Character
└ 只是說這個藍圖繼承自 Character

Event Possessed
└ 是從 Pawn/Character 體系來的繼承事件入口

這個紅色 NextPawn 存在的理由只有一個:把 client 的輸入請求送到 server

因為:

PlayerController
└ client 擁有它,可以從 client 發 Run on Server

因為 Event Possessed 在多人模式下主要跑在 server。Camera 和 Input 是本地玩家客戶端的事。server 上做 camera/input 通常沒有意義,甚至拿不到正確的本地 Enhanced Input context。

你直觉对了一半:Blender 的 smoke simulation 确实通常不是“GPU 实时粒子碰撞”那套,而是 Mantaflow 的体积流体模拟;但它也不是“一个烟粒子一个烟粒子去撞模型”。Blender 手册把 Fluid 分为 Domain、Flow、Effector;Flow 发出烟/火,Effector 用来 deflect fluids / influence fluid flow,也就是碰撞或引导流体。​编辑Blender Documentation+2​编辑Blender Documentation+2

核心模型是:

Smoke Simulation
└ 不是粒子主导
 └ 是 voxel / grid 主导
  └ Domain 里划成一格一格的 3D 网格
   └ 每个格子存:烟密度、速度、温度、燃料、火焰信息等
    └ 每一帧更新这些场,而不是逐个烟点碰撞

“烟”更接近:

一团三维像素数据
└ density field
 └ 哪里密度高,哪里就显得白/黑/浓
└ velocity field
 └ 每个空间格子里,烟往哪个方向流
└ temperature / buoyancy
 └ 热烟往上飘
└ collision field
 └ 哪些格子被障碍物占住,烟不能穿过去

不是:

烟 = 100万个小球
└ 每个小球和鲸鱼 mesh 三角面逐个碰撞

Frame N
└ Flow object 注入烟密度/温度/速度
└ 根据 velocity field 把烟密度往前搬运,叫 advection
└ 加重力、浮力、涡旋、湍流等力
└ 把碰撞物体转成 domain 里的障碍格子
└ 修改障碍附近的速度边界,让烟不能流进固体
└ 解 pressure projection,让流体速度尽量不可压缩
└ 输出下一帧的 volume cache

“还能碰撞说明大概在 CPU”,这个判断方向可以理解,但因果不严谨。能碰撞不代表一定 CPU;GPU 也能做碰撞、粒子、grid fluid。更准确地说是:Blender 的 Mantaflow bake 传统上偏离线 CPU 求解,GPU 更多参与最后渲染 volume,而不是把整个烟雾流体解算实时放到 GPU 上。Mantaflow 本身是面向 CG 和研究的开源流体模拟框架。​编辑MantaFlow

Eulerian vs. Lagrangian (Physics) 
In fluid mechanics and continuum physics, these two methods are used to describe the motion of continuous materials: 

碰撞感也是这样来的:

鲸鱼 mesh / collider
└ 体素化到 smoke domain
 └ 这部分格子被标记为 solid / obstacle
 └ 烟的速度不能进入这些 solid 格子
 └ 障碍物移动时,还可以把速度传给周围流体
└ 结果视觉上就像烟撞到鲸鱼、绕过鲸鱼、被拖拽

这里的关键不是“烟真的撞到了鲸鱼表面的每个三角形”,而是:

三角形表面
└ 被转译成 voxel 障碍边界
 └ 流体求解器只看这个边界场
  └ GPU/CPU 都很擅长处理这种规则网格

Foley 是影视/游戏音频里的词,不是 UE 专有词。意思是“为了动作画面补出来的现实声音效果”,典型就是脚步、衣服、道具、碰撞、开门、落地这些声音;这个词来自声音效果艺术家 Jack Foley。

Traversal
└─ 角色穿越环境
 └─ vault 翻越矮障碍
 └─ mantle 攀上平台边缘
 └─ climb 爬墙/爬梯/爬边缘
 └─ ledge grab 抓边
 └─ slide 滑铲穿过
 └─ jump over 跨越
 └─ drop down 从边缘下落

Locomotion
└─ 日常移动
 └─ idle / walk / run / sprint / stop / turn / jump / fall

Traversal
└─ 通过环境障碍
 └─ climb / vault / mantle / ledge / slide

Axis2D 类型会输出 Vector2D

更常见的是 ABP 自己每帧从 Pawn/CharacterMovement 拉数据。

Character 是在 Pawn 基础上扩展出来的类,额外带了 CharacterMovementComponentCapsuleComponentSkeletalMeshComponent;并且 CharacterMovementComponent 是 Character 专用,不能直接装到其他类上。Epic Games Developers

所以你说“Pawn 里根本没有 CharacterMovement”是对的,但这不是矛盾。这个节点的意思不是“我要直接从 Pawn 上拿 CharacterMovement”,而是:

Try Get Pawn Owner
└─ 先拿到控制这个 AnimInstance 的 Pawn 级 owner
 └─ 如果实际类型是 AglinaCharacter_CMC
  └─ 再 Cast 成 AglinaCharacter_CMC
   └─ 才能拿 CharacterMovement

它故意返回 Pawn,因为 Anim Blueprint 不一定只服务 Character。它也可能服务:

Pawn
└─ 载具 Pawn
└─ 飞机 Pawn
└─ 动物 Pawn
└─ 机器人 Pawn
└─ 自定义 Pawn
└─ Character 派生类

如果 Try Get Pawn Owner 直接返回 Character,那 ABP API 就被锁死在 Character 体系里了。Epic 这里做的是“先给你最通用的 possessed object”,后面你自己决定要不要 Cast 到具体类型。

worker thread 就是“非 Game Thread 的后台工作线程”。在 UE 的动画系统里,它主要用来并行更新/评估动画,避免所有 ABP 逻辑都挤在 Game Thread 上。

V&A 的 fashion collection 跨越五个世纪,包含服装和配饰;巴黎 Musée des Arts Décoratifs 有 Decorative Arts、Fashion and Textiles、Advertising and Graphic Design 等收藏方向;KCI Digital Archives 也按年代整理服装与图像资料。Google Arts & Culture madparis.fr+2

SVG 是网页上常见的矢量图格式。GitHub+1

CVarConsole Variable,也就是运行时控制台变量。这个函数每帧读一组 console variable,然后缓存成 ABP 自己的普通变量,因为你这个蓝图注释里明确写了:Blueprint 里获取 CVar 不是 thread safe,所以要先缓存,后面给 BlueprintThreadSafe 函数使用。

顺序是有意图的。先读 CVar,是为了让后面的 Update_PropertiesFromCharacterUpdate_Logic 都拿到“这一帧最新的全局开关”。

Thread Safe
└─ 一个函数 / 读写操作 / 数据访问方式的安全属性
└─ 意思是:即使不在 Game Thread,也不会和别的线程抢 UObject 生命周期、组件状态、全局表、Console Variable 等内部数据

GetConsoleVariableBoolValue
└─ 访问全局 Console Variable 系统
└─ 在这个蓝图作者看来:不适合直接放到 thread-safe 动画函数里
└─ 所以说它 “not thread safe”

OffsetRootBoneEnabled
└─ 普通 bool 缓存
└─ worker thread 读取它的风险低得多

Game Thread
└─ 可以直接碰 Actor、Pawn、Component、Console Variable、UObject validity

Worker Thread
└─ 只能碰被设计为 thread safe 的数据路径
└─ 最好读已经缓存好的 primitive 值
└─ 不要直接查 UObject、Component、Console Variable 这种可能被 Game Thread 改的东西

不能像普通蓝图函数那样改名,

CharacterProperties 是从 Character 拿到的一整个结构,里面包括:

movementMode、stance、rotationMode、gait、movementDirection、actorTransform、velocity、inputAcceleration、currentMaxAcceleration、currentMaxDeceleration、orientationIntent、aimingRotation、justLanded、landVelocity、groundNormal 等。

之后主要生成三组中间数据:

  1. Update_EssentialValues

从 CharacterProperties 拆出并计算:

CharacterTransform
RootTransform
Acceleration
AccelerationAmount
HasAcceleration
Velocity
Speed2D
HasVelocity
VelocityAcceleration
RelativeAcceleration
LastNonZeroVelocity

这些被 IsMoving、IsStarting、Get_LeanAmount、Get_TrajectoryTurnAngle、ShouldSpinTransition、AO、StrafeYawRotationOffset 等函数消费。

  1. Update_Trajectory

用当前速度/角色数据生成 Pose Search 轨迹:

Trajectory
TrajectoryCollision
Trj_PastVelocity
Trj_CurrentVelocity
Trj_FutureVelocity

这些被 Motion Matching、启动判断、移动方向判断、轨迹转向角等消费。

  1. Update_States

从 CharacterProperties 写入状态变量:

MovementMode
RotationMode
MovementState
Gait
Stance

并保留上一帧版本。它们被状态机 transition、Motion Matching blend/interrupt、Offset Root、FootPlacement、AO、Turn in Place、Pivot、Land 判断等消费。

最终消费在 AnimGraph 里:

MotionMatching 节点挂了 Update_MotionMatching 和 Update_MotionMatching_PostSelection,会设置搜索数据库并记录当前选中的动画/数据库。

主 AnimGraph 里还确认有:

StateController
MotionMatching
PoseHistory
OffsetRootBone
FootPlacement
BlendStack
Slot
ApplyMeshSpaceAdditive

所以简化成一句话:

Character 数据先被塞进 CharacterProperties,然后每帧拆成 EssentialValues / Trajectory / States 三组动画中间变量;这些变量主要驱动 Motion Matching 搜索、状态机切换、OffsetRoot、FootPlacement、AO/Lean/Turn/Pivot/Land 这些动画修正和判断。

  1. 按 W 不等于角色真的在前进
    可能被墙挡住、在空中、上坡、打滑、根运动锁住、正在落地、正在转身。动画要看 Velocity / Acceleration / MovementMode,不是只看按键。

  2. 鼠标方向不等于身体方向
    有 aimingRotation、orientationIntent、actorTransform、rotationMode。比如瞄准时身体可以侧移,非瞄准时身体朝移动方向转。

Motion Matching 需要轨迹,不只是输入
它要问:“过去怎么动、现在怎么动、未来可能往哪走?”
所以才有:

Trajectory
Trj_PastVelocity
Trj_CurrentVelocity
Trj_FutureVelocity

同样是按 W,当前状态可以完全不同:

按 W
└─ 刚从静止起步
└─ 已经跑了 2 秒
└─ 刚从左转切回直行
└─ 刚从空中落地
└─ 被墙挡住,输入有但速度很小
└─ 角色朝北,镜头朝东,输入实际是侧移
└─ 当前左脚在前
└─ 当前右脚在前

如果只看当前输入,这些全都一样。但动画上不能一样。

  • Gait 是一个偏中性、偏医学或生物力学 的词,纯粹指“走路的步态/步伐 ”(例如:慢、瘸、稳)。
  • 如果只说 "She has a gait",语法上不完整,听起来像在分析她的生物步行特征,完全没有“贵妇”的尊贵、优雅感。  
  • Poise (最推荐)
    • 含义: 优雅的仪态、泰然自若的气质。
    • 例句: She carries herself with the poise of a noblewoman.(她举手投足间尽显贵妇的仪态。)  
  • Bearing / Carriage
    • 含义: 举止、体态、风度(尤指站姿和坐姿)。
    • 例句: Her regal bearing commanded the room.(她那贵妇般的风度震慑全场。)  
  • Elegance
    • 含义: 高雅、优雅。
    • 例句: She moves with aristocratic elegance .(她一举一动都带着贵族的优雅。)  

仍然不是 Motion Matching 需要的完整信息。关键差别是:

CharacterProperties
└─ 描述 capsule / actor / movement 的状态
 └─ movementMode
 └─ gait
 └─ velocity
 └─ inputAcceleration
 └─ actorTransform
 └─ orientationIntent
 └─ aimingRotation
 └─ groundNormal
 └─ justLanded / landVelocity

PoseHistory
└─ 描述 skeletal mesh 的身体连续性
 └─ 上一帧骨盆在哪里
 └─ 左脚/右脚在哪里
 └─ thigh / spine / pelvis 的 pose 怎么连续过来
 └─ 当前步态 phase 是什么
 └─ 当前动画 pose 能不能接到数据库某一帧

ABP 里也能直接看到这个分层。Update_Logic 先跑 Update_Trajectory,再跑 Update_EssentialValues,再跑 Update_States。这说明 CharacterProperties 进来以后,还要继续被整理成动画系统要用的轨迹、基础状态、状态机变量。

PoseSearchHistoryCollector 绑定了 Trajectory,收集的骨骼包括 foot_rfoot_lthigh_rthigh_lspine_03pelvis,还收集 curve Phase。这已经超出 CharacterProperties 的范围了。它不是在重复 velocity,而是在采样骨架 pose。

同一个 CharacterProperties 可以对应多个完全不同的动画 pose:

velocity = 500
└─ 左脚撑地
└─ 右脚撑地
└─ 左脚刚离地
└─ 右脚刚离地
└─ 上一帧正在 turn-in-place
└─ 上一帧刚从 landing blend 出来
└─ pelvis 已经被 OffsetRootBone 拉偏
└─ montage / additive / aim offset 已经改变上半身

而且 Pose 内部还可能携带额外属性,所以会画成多条并行线。那些并行线表示随 Pose 一起传递的内部信息,比如 CurvesAnimation AttributesSync GroupRoot MotionInertial Blending。也就是说它不是 float + vector + bool 这种普通数据线,而是一个“姿势包”。Epic Games Developers

M_Neutral_AO_Stand_X+45_Y+90 不是完整动画,它是 additive / AimOffset 用的“偏移姿势”。

我刚查了这个资产,它的关键属性是:

AdditiveAnimType = AAT_RotationOffsetMeshSpace

意思是:它不是“一个完整站立动作”,而是“在已有基础姿势上,额外旋转身体/上半身到某个瞄准方向”。

所以它不能这样用:

M_Neutral_AO_Stand_X+45_Y+90 -> Output Pose

正确用法应该是:

M_Neutral_Stand_Idle_Loop // 完整基础姿势 -> Base M_Neutral_AO_Stand_X+45_Y+90 // additive 偏移姿势 -> Additive Base + Additive -> Output Pose

对应节点一般是:

Apply Mesh Space Additive

或者用现成的:

BS_Neutral_AO_Stand

你看到人物消失,是因为你把“偏移量”当成了“完整姿势”输出。它缺少正常站姿的完整骨骼姿态基础,预览就会变成异常状态。

白线 = Pose Link 主线
其他颜色 = Pose 里附带的不同数据通道
tooltip 里已经写了:

Animation Pose
Attributes:
Curves
Attributes
RootMotionDelta
这些不是你要一个个接的独立线,而是一个 Pose Link 里打包携带的内容。
当你换成 additive AO 这种资产时,它可能没有正常曲线、属性、root motion,或者只输出偏移姿势,所以那些彩色附带通道看起来会少/消失。

  1. 它们不一定每个动画都有
    有些 Sequence 有曲线,有些没有。有些节点会生成属性,有些不会。

  2. 它们会被节点混合、筛选、覆盖
    你看到它们有时出现有时消失,不一定代表“这里执行了一个新效果”,可能只是某个节点没保留那类数据。

  3. 它们的来源分散
    有的来自 AnimSequence,有的来自 PoseSearchHistoryCollector,有的来自 RootMotion,有的来自插件节点。不是一个地方能看完。

  4. 它们通常是服务白线效果的
    比如 FootPlacement 可能用曲线判断脚接触,但你先要知道 FootPlacement 在白线链路里的位置。否则你会先看脚接触曲线,却不知道它服务哪个效果。

对,角色跟随摄像头/控制器方向转动身体,不是 ABP 造成的。

我刚确认了 AglinaCharacter_CMC 里的旋转逻辑,真实位置在:

[可搜] UpdateRotation_PreCMC

它里面会改 CharacterMovement:

Set bUseControllerDesiredRotation Set bOrientRotationToMovement Set RotationRate

也就是说:

摄像头 / Controller 朝向 -> Character / CharacterMovement 决定 capsule/actor 怎么转 -> ABP 只是读取转完后的结果

“之后又会有关”也对。ABP 后面会用这些旋转结果做动画表现,比如:

GetActorRotation GetControlRotation / GetBaseAimRotation RotationMode aimingRotation RootTransform AO / AimOffset TurnInPlace OffsetRootBone

区别是:

CharacterMovement 负责真的转角色/capsule。 ABP 负责让 mesh 动画看起来合理: 上半身瞄准、身体扭转、转身动画、root 偏移、脚不滑。


CharacterMovement->RotationRate = FRotator(0, 0, -1);

在蓝图里结构是:


Character Movement
└ 作为 Target
   └ Set Rotation Rate
      └ X = 0
      └ Y = 0
      └ Z = -1

Rotation RateUCharacterMovementComponent 的属性,官方 API 里说明它控制角色旋转变化速度;负值表示无限旋转速率,也就是可以立即转向。

-> 地面 RotationRate.Yaw = -1,所以几乎瞬间转过去

WASD 输入
-> CharacterMovement 算 Acceleration
-> 角色朝向 Acceleration 方向
-> 地面 RotationRate.Yaw = -1,所以几乎瞬间转过去


X = Roll
Y = Pitch
Z = Yaw

但蓝图显示有时会按结构体 pin 展开显示成 X/Y/Z。

移动类输入
WASD / 跳跃 / 下蹲 / 加速 / 停止移动
-> 主要进入 CharacterMovement
-> 算 Velocity、Acceleration、MovementMode、是否落地、摩擦、刹车、重力等


视角类输入
鼠标移动 / 镜头旋转
-> 主要进入 Controller / Camera
-> 算 ControlRotation / CameraTransform
-> 现在我临时让它不再驱动角色朝向

动作类输入
交互 / 攻击 / 翻滚 / 瞄准 / 切状态
-> 通常先进入角色蓝图或能力系统/状态机
-> 可能再影响 Movement,也可能直接影响 ABP 或 Montage

DSL 是 Domain-Specific Language,领域专用语言。它不是泛用语言,不是 C++、Python 那种什么都能写的语言,而是专门为某个领域设计的表达系统。

比如:

IA_Move(输入意图 DSL)
MovementMode(运动状态 DSL)
Motion Matching graph(动画选择 DSL)

外部 DSL(External DSL)
独立语法和解析器,例如:

  • SQL(数据库查询)
  • Regex(正则表达式)
  • CSS(样式描述)
  • HLSL/GLSL(shader 语言)

特点:语法自成体系,通常需要专门 parser。

内部 DSL(Internal DSL)
基于宿主语言实现,例如:

  • Unreal Engine 蓝图(Blueprint)
  • Unity Shader Graph(某种程度)
  • Python decorators / fluent API
  • Rust macro DSL

特点:本质还是宿主语言,但语义被“限制成某个领域的表达方式”。

大体是:非 WASD 的一部分在当前 AglinaCharacter_CMC 蓝图里处理,但不是全部都交给 MovementComponent。

我刚查到当前角色蓝图的结构是这样:

SetupInput -> 给本地 PlayerController 加 /Game/Input/IMC_Sandbox

IMC_Sandbox 里有:

IA_Move IA_Move_WorldSpace IA_Look IA_Look_Gamepad IA_Walk IA_Sprint IA_Jump IA_Crouch IA_Strafe IA_Aim IA_Interact IA_Traverse ...

其中 Jump / Crouch / Sprint / Walk / Strafe / Aim 都被 /Game/Characters/AglinaCharacter_CMC 直接引用;Interact / Traverse 我查引用关系时只看到 Mapping Context 引用,没看到当前角色蓝图直接消费它们。

它们最后分三种流向:

1. 直接给 CharacterMovementComponent
Jump / Crouch 这类
-> 通常调用 Character 的 Jump / Crouch / UnCrouch
-> Character 再交给 CharacterMovementComponent 改 MovementMode、胶囊、速度等

blender--很多 auto weight 错误不是算法太笨,而是输入数据让它误判:

衣服有内外两层厚度
└─ 内层面、外层面、缝边互相干扰
└─ 自动权重容易出现内外层不一致

没 Apply Transform
└─ scale / rotation 异常会让权重计算和变形表现不稳定

骨骼 rest pose 没摆好
└─ 关节中心不对,权重再准也会弯得难看

一个Local Player会需要同时挂多个 Input Mapping Context,只是通常会有一个“基础 Gameplay Context”长期存在。

Local Player
└─ 当前激活的 Mapping Context 列表
 └─ 每个 context 有 priority
  └─ 当前输入按优先级解析

IMC_UI
└─ 打开菜单时添加
└─ Confirm / Cancel / Navigate / CloseMenu

IMC_Vehicle
└─ 上车时添加
└─ Throttle / Brake / Steer

IMC_Combat
└─ 拿武器或进入战斗状态时添加
└─ Fire / Reload / Aim / SwitchWeapon

IMC_Building
└─ 建造模式时添加
└─ RotateObject / Place / CancelPlacement

Enhanced Input 本来就支持 runtime 动态添加、移除 Mapping Context,用来根据玩家状态改变输入行为。

高 priority 的 context 先处理;

如果它消费了输入,就会挡住低 priority 的 mapping。Epic 的 API 文档也是这个规则:higher priority mappings are applied first,consume input 时会 block lower priority mappings。

Context 之间不是有一个单独的“Block Other Contexts”总开关,而是:

Add Mapping Context Priority
└─ 决定谁先被看见

IA.bConsumeInput
└─ 决定命中后是否挡住低优先级

Remove Mapping Context
└─ 直接让不该存在的输入上下文失效

Epic 官方文档也推荐复杂项目用多个 IMC,因为可以动态添加、移除、排序,避免不合适的 Input Action 运行和输入冲突。

你对 IA 复用的理解基本对,但要再分细一点。

IA 可以复用,而且有时应该复用。

适合复用:

IA_Move
└─ Gameplay 里 WASD
└─ Swimming 里 WASD
└─ Vehicle 里 Left Stick
└─ 都表达“二维移动意图”

IA_Look
└─ Mouse XY
└─ Gamepad Right Stick
└─ 都表达“视角/瞄准方向”

IA_Confirm
└─ UI、对话、背包
└─ 都表达“确认”

不建议复用:

IA_Interact
└─ 世界交互

IA_UIConfirm
└─ UI 确认

这两个虽然可能都是 E,但语义不是一个东西。复用成同一个 IA_E 会导致蓝图里看不出它到底是“开门”“拾取”“确认菜单”还是“跳过对话”。

更准确的原则是:

IA 按语义命名
└─ 不是按按键命名

不要:

IA_E
IA_LeftMouse
IA_Space

应该:

IA_Interact
IA_Fire
IA_Jump
IA_Confirm
IA_Dodge

是否复用,看它是不是同一个“玩家意图”,不是看它是不是同一个按键。

成本确实很低。多几个 IA 资产的成本远低于后期排查:

为什么打开菜单时角色还在跳
为什么按 E 确认 UI 同时触发开门
为什么 Vehicle Context 里还触发 Character Dodge

英文

largest volume-production 6-in indium phosphide manufacturing platform

不要把 volume 理解成「體積」。在半導體/製造業裡:

volume production
= 大批量生產 / 量產

6-in
= six-inch
= 6 英寸,通常指晶圓直徑。也就是 6-inch wafer。

indium phosphide
= 磷化銦,縮寫 InP。這是一種化合物半導體材料,常用在光通信、雷射、光子器件、AI datacenter 光互連等領域。這段話對應的是 Coherent 在 Sherman, Texas 的 6-inch InP 製造設施;新聞稿說這個 site 是 “world's first and largest volume-production 6-in. InP manufacturing platform”。Construction Equipment Guide

manufacturing platform
不是單純一台機器,而是整套量產能力:

晶圓廠
└─ cleanroom
 └─ wafer fabrication equipment
  └─ process flow
   └─ 6-inch InP wafer / photonic device production

Sherman 應該是地名,通常指 Texas 的 Sherman。

在造 AI 時代的高速連接基礎設施

AI 集群需要大量高速光互連,Coherent 在 Sherman 做 InP 光子器件量產,這些器件會進入 NVIDIA 的 AI infrastructure 供應鏈。

美國商務部 CHIPS Program 也說這筆最高 5000 萬美元意向資金是給 Coherent 擴大 Sherman 的 indium phosphide production。Coherent Inc+1

AI GPU 核心計算芯片
└─ NVIDIA 設計
 └─ TSMC 代工
  └─ HBM 由 SK hynix / Samsung / Micron 等供應

Silicon Valley
→ 原版科技中心

Silicon Alley
→ 紐約科技圈,alley = 小巷

Silicon Hills
→ Austin 科技圈,hills = 山丘

Silicon Prairie
→ 中西部/德州平原科技圈,prairie = 草原

sector 的作用是把整個經濟切成幾塊:

economy
└─ energy sector
└─ technology sector
└─ semiconductor sector
└─ financial sector
└─ healthcare sector
└─ industrial sector

industry--sector--infrastructure

industry
= 某個產業本身

sector
= 在經濟/市場/政策分析裡切出來的一大塊  \扇块

infrastructure

產業所需的底層條件。

shell
 └─ 建築殼體 / 廠房外殼 / data center building shell
 └─ 不是 Shell 石油公司,也不是電腦 shell

working on inventing
= 正在努力把它發明出來
= 正在研發、探索、創造這項技術

invent
└─ 從無到有地發明
 └─ 比 make 更強,強調以前沒有現成答案

epicenter---earthquake

earthquake
└─ hypocenter / focus
 └─ 地震在地下真正發生的點
└─ epicenter
 └─ 地表上正對著震源的位置

後來變成比喻:

epicenter of X
= X 的中心地帶
= X 最強烈、最集中的地方
= X 爆發/形成/推動的核心位置

quadruple = 變成四倍 / 使……增加到四倍。

grid---电网

└─ shovel
 └─ 鏟子,groundbreaking ceremony 破土動工時用
└─ beam
 └─ 鋼梁,topping-out / construction milestone 時讓嘉賓簽名
  └─ 之後這根梁可能會被吊裝到建築裡,作為紀念

spoil the mood / the movie / the ending


├─ 1 寵壞
│ └─ spoil a child
│ = 把小孩寵壞
├─ 2 毀掉 / 搞壞
│ └─ spoil the mood
│ = 破壞氣氛
├─ 3 劇透 / 說破驚喜
│ └─ spoil the movie / spoil the ending
│ = 劇透電影 / 把結局說破
└─ 4 食物變質
└─ The milk spoiled.
= 牛奶壞了

NeRF 是縮寫:

Neural Radiance Fields

中文通常叫:

神經輻射場

它是 3D/AI 視覺領域的一種技術:用多張照片或影片,訓練出一個可以從不同角度重新渲染場景的神經網路表示。


Triple-I / IIIindie 小團隊

III / Triple-I
└─ 高製作品質的獨立遊戲
 └─ 想做出接近商業大作級別的系統完整度、畫面、流程、內容量

AC_PreCMCTick 这种时序组件的时候-variables- Editable when Inherited


└ 它负责在 CharacterMovementComponent tick 前更新旋转状态

这时我反而会把 Editable when Inherited 关掉。

如果没有这么做:

BP_Aglina_Test
└ 某天我为了测试,把 AC_PreCMCTick 的某些属性改了

BP_Aglina_Player
└ 继承链里也出现不同默认值

UpdateRotation_PreCMC
└ 父类图看起来没问题
└ 但实际运行时某个子类行为不一样

结果就是:我调试时一直看父蓝图,以为逻辑没错,但 bug 藏在子蓝图对继承组件的默认值覆盖里。这种 bug 很阴,因为 Graph 没变,变的是继承组件的属性。

UpdateMovement_PreCMC 把其中一部分翻译成 MovementComponent 参数
-> ABP 再读取 MovementComponent 数据 + 角色蓝图状态

基本就是这个意思:这些状态有一部分可以从 Movement 推出来,但很多已经超出 CharacterMovementComponent 的职责范围。

CharacterMovementComponent 主要回答的是:

角色现在怎么移动? 速度是多少? 加速度是多少? 在地上还是空中? 最大速度是多少? 摩擦/刹车是多少? 能不能跳、正在下落吗?

但它通常不负责回答:

玩家现在想走还是想跑? 玩家是不是按着 Aim? 现在是 Strafe 玩法还是朝移动方向跑? 这个速度应该表现成“谨慎走路”还是“普通慢跑”? 角色是不是刚落地后要播特殊恢复姿势上半身是不是该瞄准? 摄像机方向和身体方向的差异要不要变成 AimOffset

这些属于 角色玩法状态 / 动画表现意图,不属于 Movement 的底层物理结果。

IA 输入
-> AglinaCharacter_CMC 角色蓝图接收
-> 改角色蓝图自己的变量,比如 CharacterInputState / Gait
-> UpdateMovement_PreCMC 把其中一部分翻译成 MovementComponent 参数
-> ABP 再读取 MovementComponent 数据 + 角色蓝图状态

Character Movement (CharMoveComp)

它在窄面板里也能完整显示。
如果没有这个短名,我每次都要点进去看 Details,或者拉宽左侧面板,才能确认这个组件对象名。

提效就是少一次“点选确认”。

CharaMoveComp,不是不能用,但它不如 CharMoveComp 符合 UE/C++ 工程常见压缩习惯。CharMoveComp 都是短 token,扫一眼能分块;Chara 更像二次元语境里的 “character” 简写,不是引擎代码里常见工程缩写。

C++ 里确实有 char 这个基础类型,表示一个字符。你说的误读是合理的。
但实际代码/蓝图里它通常不会冲突,因为:

char
└ 小写
└ 一般出现在 char*TCHAR、字符串/字节处理语境

CharMoveComp
└ PascalCase
└ 后面接 MoveComp
└ 出现在 Actor Component / Character Movement 语境

你可以把这个节点理解成 C++ 的:


C++
self->UpdateMovement_PreCMC();

虽然你在函数内部没看到 self,但里面如果有这些东西:

Get Character Movement
Get Actor Location
Set Old Loc
Set Old Vel
Get Mesh
Get Controller
Set 某个成员变量

它们其实都等价于:

self.CharacterMovement
self.GetActorLocation()
self.OldLoc = ...
self.Mesh
self.Controller

在 PlayerController 里拿到一个角色引用,然后想让那个角色执行这个函数的时候

节点链路会是:

Get Controlled Pawn
Cast to AglinaCharacter_CMC
 └ Update Movement Pre CMC
  └ Target = As AglinaCharacter_CMC

这时 Target 就不是 self 了,而是那个被控制的角色。

Cast 不是“把一段无类型地址规定成某种 layout 然后强行读”。

在 UE 的 UObject 体系里,Cast 更准确是:

已有一个 UObject / Actor / Pawn 基类引用
└─ 这个引用本身已经有静态类型,比如 Pawn Object Reference
 └─ 但它只允许你按 Pawn 的接口看
  └─ Cast To AglinaCharacter_CMC
   └─ 运行时检查:这个对象真实类型是不是 AglinaCharacter_CMC 或其子类
    └─ 成功:输出同一个对象地址,但 pin 类型变成 AglinaCharacter_CMC Object Reference
    └─ 失败:不让你按错误 layout 读

Speed2D
└─ Velocity 的 XY 平面长度
 └─ 忽略 Z 轴上下速度
 └─ 用来判断 idle / walk / run / stop / pivot

官方文档里的对应做法就是:先从 Movement Component 拿 Velocity,然后用 Vector Length XY 抽出 X/Y 平面速度,promote 成 Speed 变量给 AnimGraph 用。Epic Games Developers

CMC 不是通过“绑定具体 InputAction”在自己内部获得改变。

更准确是:

IA_Move
└─ Character BP 收到输入事件
 └─ 调 AddMovementInput(WorldDirection, ScaleValue)
  └─ Pawn/Character 记录这一帧的 movement input
   └─ CharacterMovementComponent 在自己的 tick / movement update 里消费这个 input
    └─ 根据 MaxWalkSpeed、Acceleration、Braking、Friction、碰撞、MovementMode 等算出真实 Velocity
     └─ ABP 读取这个 Velocity
      └─ 算 Speed2D

Character Movement
└ 这个组件对象自己的运行参数
 └ Gravity Scale
 └ Max Acceleration
 └ Braking Friction Factor
 └ Crouched Half Height
 └ 等等

线 A:身体实际移动
WASD / Jump / Crouch / Sprint
-> CharacterMovementComponent
-> Velocity / Acceleration / MovementMode / IsFalling
-> ABP 用来选 locomotion、落地、速度、脚步等
线 B:玩家意图 / 状态标签
Walk / Sprint / Aim / Strafe / CameraStyle / CharacterInputState
-> AglinaCharacter_CMC 自己保存
-> ABP 通过 Get_PropertiesForAnimation 拿到
-> ABP 用来判断应该怎么表现

普通走路
瞄准横移
慢走
跑步启动
刹车
落地后恢复
转身但还没移动
如果 ABP 只拿 Velocity,这些情况会长得很像;所以它才额外拿 Gait / Aim / Strafe / Acceleration / LastFrame / Rotation 这些东西。

Target is Kismet Math Library


└ 这个节点不是在读 Actor、Character、MovementComponent
└ 它只是调用一个全局数学工具函数
└ 输入 A 给什么,它就算什么

True Blend Time
└ Active Value 从 false 变成 true 时,多久混到 True Pose

False Blend Time
└ Active Value 从 true 变成 false 时,多久混回 False Pose

如果没有 True Blend Time / False Blend Time,Active Value 一变,角色会直接从一个姿势跳到另一个姿势。肩膀、裙摆、手臂、脊椎会出现“啪”的一下切换。

Blueprint Debugger 面板的实际价值是:它不是让你“模拟输入”,而是让你在真实 PIE/SIE 运行时,把蓝图执行停在某个节点,然后看“刚才到底走了哪条路、哪个函数调用了它、哪些 pin/变量当时是什么值”。

最贴近你现在 ABP 的用法是这样:

我在看 Speed2D 为什么不对的时候
└ 在 Set Speed 2D 节点右键
 └ Add Breakpoint

然后:

Play
└ 按 WASD
└ 执行到 Set Speed 2D 前,游戏暂停
└ Debugger 会跳到这个节点
└ 你看当时的 Get VelocityVector Length XYSpeed2D

如果不这么做,你只能看到最终姿势错了,但不知道是哪一帧、哪个节点把 Speed2D 写成了错值。

前端

localStorage 是以**域名(Origin)**为单位共享的,而不是每个 HTML 文件一份。

关键规则

  • 同源共享:只要是同一个域名、协议和端口(例如 https://example.com),该站点下的所有页面(index.htmlcart.html 等)都访问同一个 localStorage 仓库。
  • 持久存储:数据不会因为关闭页面或浏览器而消失,除非你手动删除或通过代码清除。

.nav-row
├─ logo        左边
├─ nav         中间,设置 flex: 1,占满剩余空间
└─ user-zone   被挤到右边

.nav-row {
  display: flex;
  align-items: center;
  gap: 26px;
}

.topbar nav {
  flex: 1;
}

.topbar nav,
.user-zone {
  display: flex;
  align-items: center;
  gap: 18px;
}

不会“每个用户一个独立数据集”。如果用户量很大,每个用户都单独一个库或一个文件,管理成本会爆炸:

user_001_db user_002_db user_003_db ...

这样迁移、备份、索引、统计、跨用户查询都会很麻烦。

更常见的是按业务拆表:

users 用户表 products 商品表 orders 订单表 cart_items 购物车表 addresses 地址表 favorites 收藏表

用户登录成功后,不是进入“个人数据库”,而是拿到一个 user_id,之后所有请求都带着这个身份:

GET /cart?userId=10001 GET /orders?userId=10001 GET /addresses?userId=10001

1. 索引
   给商品名、分类、品牌、价格等字段建立索引。

2. 分页
   每次只返回 20 或 50 条,不返回全部数据。

3. 搜索引擎
   例如 Elasticsearch、Solr、OpenSearch,用于关键词搜索和复杂筛选。

4. 缓存
   热门搜索、首页推荐、热门商品可以放 Redis 缓存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值