UE5 创建了一个C++类,现在我还有一个蓝图类,我想将编写的C++类中包含的功能加入到这个蓝图类里面,如何做到
目标:小船换军舰
- 基本概念
- 提问
- 回答
- ✅ 目标:让蓝图类继承你编写的C++类的功能
- 🔧 方法一:让蓝图继承自你的C++类
- 步骤:
- ⚙️ 方法二:组件式组合(通过组件添加功能)
- 🧠 小贴士:
- ✅ 总结:
- 继续提问
- 🎯 你的目标:
- ✅ 解决方案:迁移蓝图内容到新的蓝图类中
- 🧱 步骤 1:确认你写的 C++ 类能被蓝图继承
- 🛠️ 步骤 2:创建一个新的蓝图类,继承你的 C++ 类
- 📥 步骤 3:迁移已有蓝图内容到新蓝图
- 3.1 迁移变量
- 3.2 迁移事件图逻辑
- 3.3 迁移组件(如果有)
- ✅ 步骤 4:用新的蓝图替换旧蓝图的引用(可选)
- ✅ 最终效果
- 👋 提示
- 继续提问
- 回答
- ✅ 查看蓝图的父类(是否是你的C++类)
- ✅ 方法一:通过蓝图编辑器顶部信息栏查看(最直观)
- ✅ 方法二:通过“类设置”面板查看
- 🔁 如果不是你想要的父类,怎么办?
- 🧠 小提示:蓝图父类命名判断技巧
- 继续提问
- 回答
- ✅ 方法一:在内容浏览器中直接复制粘贴(最推荐)
- 步骤:
- ✅ 方法二:Ctrl+C / Ctrl+V(快捷键复制)
- ✅ 方法三:蓝图打开状态下“另存为”
- 步骤:
- 🔎 注意事项:
- 🛠️ 建议命名规范(方便版本管理):
- ✅ 总结:
- 继续提问
- 回答
- 🎯 你的问题总结:
- ✅ 答案:
- 是的!你说的方式**确实是“基于组件”的组合方式**,而不是传统的“类继承”。
- 🧱 方法对比:继承 vs 组件组合
- 🔧 你要实现“添加 C++ 类功能作为节点”,需满足以下条件:
- 🎮 示例图景:
- ✅ 总结:你提到的两种方法分别是:
- 🧠 开发建议:
- 继续提问
- 回答
- ✅ 为什么你的决定是明智的?
- ✅ 1. **避免破坏已有蓝图结构**
- ✅ 2. **组件式方式可控性高、低耦合**
- ✅ 3. **开发效率高,可回滚、可调试**
- 🔧 开发建议:组件化接入你的功能
- 🎯 目标:让现有蓝图(BP\_boat)通过组件接入你写的 C++ 功能
- ✅ 第一步:写一个组件类
- ✅ 第二步:在蓝图中添加这个组件
- ✅ 第三步:控制组件功能的激活/禁用
- 🛠️ 可选:通过 `TickComponent()` 实现持续逻辑
- 🧠 小提示:组件的“配置”也可以暴露到蓝图中!
- ✅ 总结:你选择的方式有什么优点?
- 🎁 Bonus:是否需要我给你一个样板组件?
- 继续提问
- 回答
- 1. 功能模块化
- 2. 可组合性
- 3. 层次结构
- 4. 独立属性和事件
- 5. 可视化编辑
- 6. 运行时动态控制
- 7. 继承和自定义
- 8. 物理模拟支持
- 9. 与其他节点协同工作
- 10. 跨蓝图复用
- 11. 支持多种类型
- 12. 事件驱动
- 13. 性能优化
- 14. 与C++结合
- 15. 支持蓝图可视化脚本
- 继续提问
- 回答
- 相似之处
- 1. 功能封装
- 2. 复用性
- 3. 抽象层级
- 不同之处
- 1. 独立的实体
- 2. 与Actor的关系
- 3. 可视化编辑
- 4. 物理和渲染功能
- 5. 事件系统
- 6. 层级结构
- 7. 运行时动态操作
- 总结
- 继续提问
- 回答
- ✅ 简要结论:
- 🧩 接入 C++ 功能的几种方式
- ✅ 方式 1:组件类(你现在采用的方式)
- ✅ 方式 2:静态函数类(Function Library)
- ✅ 方式 3:UObject 子类(动态创建实例)
- ✅ 小结:你可以不通过继承,也能让 C++ 功能出现在蓝图中:
- ✅ 最适配你的情况:
- 🧠 你可以这样思考:
- 继续提问
- 回答
- ✅ 答案:
- 🔍 所以你要做的验证,就是尝试在蓝图中“添加组件”,看它在不在列表里。
- ✅ 常规接入蓝图类的步骤(用于验证组件是否可以被添加)
- 🧪 **验证步骤:蓝图中尝试添加组件**
- 1. 打开蓝图类(比如 `BP_boat`)
- 2. 在左侧组件面板中:
- 3. 在搜索框中输入你写的组件类名(例如 `BoatFunctionComponent`)
- 4. 观察结果:
- ✅ 如果没找到该组件,该检查 C++ 类的三项内容:
- 🎯 总结:
- 💡 额外建议:
- 方法 A:查头文件中是否有以下宏
- 方法 B:在 Visual Studio 中搜索继承关系
- 👋 如果你想让我帮你判断一个类是否可添加,也可以直接贴出类名或部分定义,我可以马上分析 ✅
- 继续提问
- 回答
- **1. 定义与角色**
- **Components(组件)**
- **Actions(操作)**
- **2. 可视化表现**
- **Components**
- **Actions**
- **3. 功能与用途**
- **Components**
- **Actions**
- **4. 交互方式**
- **Components**
- **Actions**
- **5. 示例对比**
- **6. 核心区别总结**
- **常见误区**
- **如何选择?**
- 继续提问
- 回答
- 🧠 首先,什么是你说的“Actions”?
- ✅ 情况一:你希望在蓝图中调用你的 C++ 函数 —— 用 BlueprintCallable
- 那么……怎么让这些函数出现在某个蓝图类的事件图中呢?
- ✅ 方式 A:你的类是当前蓝图的**父类**(继承方式)
- ✅ 方式 B:你的类是**组件类**,已被添加到蓝图中
- ✅ 方式 C:你的类是一个静态函数类(Function Library)
- ✅ 方式 D:UObject 类,被蓝图实例化后使用其函数
- ✅ 总结:函数(Action 节点) vs 组件(Component 模块)的区别
- ✅ 最适合你的情况:
- ✅ 最后回答你的核心问题:
- 继续提问
- 回答
- 🎯 场景说明:
- ✅ 先说结论:这是**类型转换节点**,不是添加组件、也不是函数调用。
- 🧩 什么是 Casting(类型转换)?
- ✅ 分析你看到的两个节点:
- 1️⃣ `Cast To SetGetActorLocation`
- 2️⃣ `Cast To SetGetActorLocation Class`
- 🧠 那这说明什么?
- ✅ 如何让你在蓝图中**使用该类的功能**?
- 方案 1:你写的类是组件类(继承自 `UActorComponent`)?
- 方案 2:你写的类是 `UObject` 派生类(不是组件)?
- A. 在蓝图中使用 `Construct Object from Class` 创建该类的实例:
- ✅ 总结你现在看到的 Cast 节点的含义:
- 🧠 优劣对比:组件 vs Action 节点(函数) vs Cast
- ✅ 下一步建议:
- 继续提问
- 回答
- **1. 组件节点(Components):功能的载体**
- **2. 操作节点(Actions):逻辑的执行者**
- **3. 两者的关系**
- **3.1 组件为操作提供数据和功能**
- **3.2 操作节点控制组件的行为**
- **3.3 组件触发事件,操作节点响应**
- **3.4 协作实现完整功能**
- **4. 协作示例**
- **场景:角色被击中后播放特效并减血**
- **5. 核心区别总结**
- **6. 常见问题与最佳实践**
- **6.1 何时使用组件?何时使用操作节点?**
- **6.2 避免过度耦合**
- **6.3 性能考虑**
- **总结**
- 继续提问
- 回答
- **如何通过头文件判断继承关系?**
- **1. 继承自 `UObject`**
- **2. 继承自 `AActor`**
- **3. 继承自 `UActorComponent`**
- **关键判断依据**
- **为什么头文件就足够?**
- **示例分析**
- **总结**
- 继续提问
- 回答
- ✅ 分析你的类:`ASetGetActorLocation`
- 🧠 继承关系分析
- 🧭 回答你的问题:如何将它的功能接入蓝图?
- ✅ 方法一:让蓝图类继承它(不适合你当前场景)
- ✅ 方法二:将其实例“Cast”为 `ASetGetActorLocation`
- 步骤:
- ✅ 方法三(推荐):将核心功能提取为组件或函数库
- ✅ 建议:把核心功能提取出来,放进组件类中
- ✅ 新建一个 C++ 组件类(继承自 `UActorComponent`):
- 🔧 总结当前类的情况:
- ✅ 最推荐方案(适配你的目标):
- 新的改变
- 功能快捷键
- 合理的创建标题,有助于目录的生成
- 如何改变文本的样式
- 插入链接与图片
- 如何插入一段漂亮的代码片
- 生成一个适合你的列表
- 创建一个表格
- 设定内容居中、居左、居右
- SmartyPants
- 创建一个自定义列表
- 如何创建一个注脚
- 注释也是必不可少的
- KaTeX数学公式
- 新的甘特图功能,丰富你的文章
- UML 图表
- FLowchart流程图
- 导出与导入
- 导出
- 导入
基本概念
蓝图类的编辑面板中不是可以添加一个个节点(模块)吗?这些节点或者模块叫做什么?英文名是什么?—— 节点(Node)这是最基础的叫法,指的是蓝图图表里的单个元素。每个节点都代表着一个特定的功能或者操作。英文就是 “Node”。
提问
蓝图类能否加入C++类的特性?
就是我创建了一个C++类,现在我还有一个蓝图类,我想将编写的C++类中包含的功能加入到这个蓝图类里面,是否可以方便做到?
回答
是的,完全可以将C++类的功能整合到蓝图类中,这是Unreal Engine 5中非常常见且推荐的做法之一。这种方式能够结合C++的性能与蓝图的灵活性。
下面我将详细解释如何将你编写的C++类的功能集成到蓝图中,并确保蓝图可以继承和使用你定义的逻辑。
✅ 目标:让蓝图类继承你编写的C++类的功能
🔧 方法一:让蓝图继承自你的C++类
这是最直接、最推荐的方式。
步骤:
-
创建C++类
比如你创建了一个C++类:UCLASS(Blueprintable) class YOURGAME_API AMyCustomActor : public AActor {GENERATED_BODY()public:UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Custom")float Health = 100.0f;UFUNCTION(BlueprintCallable, Category = "Custom")void TakeDamage(float DamageAmount); };
-
编译代码
在编译完成后,
AMyCustomActor
将会出现在蓝图类的父类选择列表中。 -
创建蓝图类继承这个C++类
- 在内容浏览器中 → 右键 → “蓝图类”
- 在父类中选择你写的
AMyCustomActor
- 命名为
BP_MyCustomActor
(例如)
此时这个蓝图类就拥有你C++类中的所有属性和函数,可以在蓝图中直接调用,比如:
- 在事件图中使用
TakeDamage
函数 - 修改
Health
变量
⚙️ 方法二:组件式组合(通过组件添加功能)
如果你希望某些功能可以被多个不同的类共享,而不是单一继承,可以用组件(UActorComponent
):
-
创建C++组件类
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class YOURGAME_API UMyHealthComponent : public UActorComponent {GENERATED_BODY()public:UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health")float Health = 100.0f;UFUNCTION(BlueprintCallable, Category = "Health")void TakeDamage(float DamageAmount); };
-
编译后,在蓝图中添加这个组件
- 打开你的蓝图类 → 组件面板 → 添加组件 → 选择
MyHealthComponent
- 然后你可以直接在蓝图中访问该组件的属性和函数
- 打开你的蓝图类 → 组件面板 → 添加组件 → 选择
🧠 小贴士:
-
如果你想让C++中的函数在蓝图中调用,记得加上:
UFUNCTION(BlueprintCallable)
-
如果你想让C++中的变量在蓝图中可见/可编辑,使用:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
✅ 总结:
方式 | 优点 | 场景适用 |
---|---|---|
继承C++类 | 简单直接,蓝图获得完整C++逻辑 | 一个蓝图只需一个核心功能类 |
添加C++组件 | 模块化复用,可在多个蓝图中共享功能 | 多个蓝图共用逻辑,如健康系统 |
如果你愿意,可以告诉我你C++类的具体功能,我可以给出更贴合的蓝图集成建议(例如具体蓝图节点展示、变量同步、事件响应等)。你想要继承的C++类是什么类型(比如AActor、UObject、ActorComponent等)?这样我可以给你一个更具体的对接步骤。
继续提问
我打算采用方式一,
现在我已经有一个蓝图类了,我该怎么为这个蓝图类继承我的C++类?
太好了,你选择的方式一(蓝图继承 C++ 类)是最稳妥也最主流的做法,尤其适合做基础功能拓展,比如角色、敌人、武器等核心逻辑的底层实现。
🎯 你的目标:
已有一个蓝图类,现在想让它“继承”你写的 C++ 类。
Unreal 蓝图创建时会选定一个“父类”(Parent Class),这个父类一旦确定,是不能在编辑器中直接更改的。所以我们不能“改”蓝图的父类,但可以创建一个新的蓝图,继承你写的 C++ 类,然后把原来蓝图的内容迁移过去。
✅ 解决方案:迁移蓝图内容到新的蓝图类中
🧱 步骤 1:确认你写的 C++ 类能被蓝图继承
确保你的 C++ 类写成了类似这样:
UCLASS(Blueprintable) // 或者 BlueprintType
class YOURGAME_API AMyCustomActor : public AActor
{GENERATED_BODY()public:UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyCustom")float Health;UFUNCTION(BlueprintCallable, Category = "MyCustom")void TakeDamage(float Amount);
};
编译完成后,在内容浏览器里应该能作为蓝图父类选择。
🛠️ 步骤 2:创建一个新的蓝图类,继承你的 C++ 类
-
在内容浏览器中 右键 → 蓝图类(Blueprint Class)
-
在弹出的“选择父类”窗口中:
- 搜索并选择你写的 C++ 类,比如
AMyCustomActor
- 搜索并选择你写的 C++ 类,比如
-
命名新蓝图为
BP_MyCustomActor
📥 步骤 3:迁移已有蓝图内容到新蓝图
打开你原来的蓝图类(比如 OldActor_BP
)和新蓝图类(BP_MyCustomActor
),进行以下操作:
3.1 迁移变量
- 打开原蓝图 → “我的蓝图”窗口 → 找到所有变量
- 右键 → “复制”
- 切换到新蓝图 → “我的蓝图”窗口 → 粘贴
- 注意:类型、默认值、暴露设置(Expose on Spawn)等可能需要重新设置
3.2 迁移事件图逻辑
- 打开旧蓝图的“事件图” → Ctrl+A 选中所有节点 → Ctrl+C
- 切换到新蓝图 → 粘贴(Ctrl+V)
3.3 迁移组件(如果有)
- 在旧蓝图的“组件面板”中,选中组件 → 复制 → 粘贴到新蓝图中
注意:部分组件的绑定或引用逻辑(例如绑定到某个自定义事件)可能需要重新设置。
✅ 步骤 4:用新的蓝图替换旧蓝图的引用(可选)
如果旧蓝图已经放入关卡或被其他蓝图引用:
- 在内容浏览器中选中旧蓝图 → 右键 →
Asset Actions
→Replace References
- 选择用
BP_MyCustomActor
替换
✅ 最终效果
你现在有了一个完整继承自你的 C++ 类的蓝图,并且保留了原蓝图的所有逻辑和变量,现在蓝图里可以直接访问你 C++ 中声明的属性与函数!
👋 提示
你可以在新蓝图中:
- 右键输入你在 C++ 中声明的函数名 → 蓝图中会自动补全调用
- 添加
BeginPlay
、Tick
等事件,自动调用父类函数(注意是否需要调用Super::BeginPlay()
) - 通过蓝图扩展 C++ 的逻辑而不触碰 C++ 代码
如果你能贴出你的 C++ 类名称(比如是 AEnemyBase
?),我可以一步步为你写好迁移示范,包括变量迁移、函数蓝图节点使用方法等。是否需要我进一步帮你搭建这个流程?
继续提问
如何查看我的蓝图(叫做BP_boat)是否已经继承某个C++类了?
回答
很好,这个问题问得非常关键。在Unreal Engine中,每个蓝图类都继承自某个父类(Parent Class),你可以很容易地查看你当前的蓝图(比如 BP_boat
)是否已经继承自你的某个C++类。
✅ 查看蓝图的父类(是否是你的C++类)
✅ 方法一:通过蓝图编辑器顶部信息栏查看(最直观)
-
双击打开蓝图
BP_boat
-
看蓝图编辑器顶部标题栏(蓝图名称右侧):
-
你会看到类似:
BP_boat (inherits from ABoatBase)
-
这个括号里的内容就是 父类名称,比如:
- 如果你写的 C++ 类叫
ABoatBase
,而看到inherits from ABoatBase
,那就说明已经继承成功 ✅ - 如果显示的是
AActor
或其他系统类名,那说明目前还没有继承你的自定义类 ❌
- 如果你写的 C++ 类叫
-
✅ 方法二:通过“类设置”面板查看
-
打开蓝图
BP_boat
-
点击工具栏上的
类设置(Class Settings)
-
在细节面板中找到:
- 父类(Parent Class) 属性
它会显示当前蓝图继承的是哪个类,例如:
ABoatBase
✅(是你写的 C++ 类)AActor
❌(未继承你的 C++ 类)APawn
,ACharacter
, 等(也可能是默认引擎类)
🔁 如果不是你想要的父类,怎么办?
如前面提到的,蓝图一旦创建后,父类无法直接更改,你需要:
- 新建一个蓝图,选择你写的 C++ 类作为父类(比如
ABoatBase
) - 然后把
BP_boat
里的内容复制/迁移过去(参考前面步骤)
🧠 小提示:蓝图父类命名判断技巧
- 如果你看到蓝图父类是你写的 C++ 类名,比如
ABoatBase
、UMyActorComponent
等,那说明就是继承你写的类 - 如果前缀是
A
,说明是 Actor 或派生类 - 如果是
U
,说明是 UObject 或组件类
如果你告诉我你的 C++ 类叫什么,比如 ABoatBase
或 AMyBoatActor
,我可以帮你确认是否继承成功,甚至给你一个继承结构图。
你现在看到的蓝图父类是哪个?我们可以一起确认。
继续提问
能否对某一个蓝图类创建副本?因为我可能要对现在的蓝图类做修改。我不希望对原蓝图进行变动。 如果可以方便地创建副本,告诉我方案
回答
是的,完全可以对蓝图类创建副本,而且操作非常简单。这在开发过程中是非常常见的需求,比如:
- 你要尝试新逻辑,但不想破坏现有蓝图
- 你要创建多个变体(比如不同类型的船)
- 你想做版本备份
下面我提供几种方式,帮你快速对现有蓝图(比如 BP_boat
)创建副本。
✅ 方法一:在内容浏览器中直接复制粘贴(最推荐)
步骤:
- 打开内容浏览器(Content Browser)
- 找到你的蓝图
BP_boat
- 右键 → Duplicate(复制)
- 系统会自动创建副本,比如叫
BP_boat_Copy
- 你可以重命名为
BP_boat_VariantA
、BP_boat_Test
或其他自定义名称
✅ 优点:
- 非常快捷
- 复制的是完整蓝图,包括组件、变量、图表逻辑等
- 所有引用仍然指向独立副本
✅ 方法二:Ctrl+C / Ctrl+V(快捷键复制)
- 在内容浏览器中点击
BP_boat
- 按
Ctrl + C
然后Ctrl + V
- 系统同样会创建一个副本,命名为
BP_boat_Copy
(你可重命名)
✅ 方法三:蓝图打开状态下“另存为”
适合你在蓝图编辑器中,边修改边保存副本。
步骤:
- 打开蓝图
BP_boat
- 点击工具栏中的
文件(File)
菜单 - 选择
另存为(Save As)
- 输入新名称,例如
BP_boat_Modified
- 保存到相同目录或不同文件夹均可
✅ 适合在修改前备份当前蓝图版本
🔎 注意事项:
项目 | 是否复制 |
---|---|
图表逻辑(事件图) | ✅ |
变量、默认值 | ✅ |
组件(Mesh、Camera等) | ✅ |
绑定事件 | ✅ |
蓝图事件(如BeginPlay) | ✅ |
外部引用(被其他蓝图引用) | ❌(需手动替换) |
如果你复制的是一个被关卡或其他蓝图引用的蓝图,记得更新引用,否则他们还是指向旧版本。
🛠️ 建议命名规范(方便版本管理):
用途 | 示例 |
---|---|
实验性修改版本 | BP_boat_TestA |
特定功能版本 | BP_boat_WithWeapons |
备份版本 | BP_boat_Backup_2025_06_04 |
✅ 总结:
复制蓝图最推荐方式:右键 → Duplicate
它完全复制蓝图的所有内容,你可以在不影响原蓝图的前提下自由修改副本。
如果你后续需要批量替换关卡中的旧蓝图为新副本,我也可以给你详细操作方案。是否需要?例如把关卡中所有 BP_boat
替换成 BP_boat_Test
。
继续提问
前面提到,可以新建一个蓝图类,然后继承我写的C++类。 用这种办法,可以让我新建的蓝图类拥有我写的C++类的所有功能。
那么,是否可以在蓝图类中以加入C++类对应节点的方式引入我编写的这个C++类的所有功能?如果可以,这个方法是否就是你前面说的基于组件的方式组合并添加功能的方式?
回答
非常棒的问题,而且你理解得已经非常接近本质了!我们来拆解一下你的提问,并明确核心概念:
🎯 你的问题总结:
你问的是:
❓是否可以不通过蓝图继承 C++ 类,而是通过在蓝图里添加“C++类对应的节点”,就让蓝图获得这些功能?这是不是前面说的“基于组件”的方式?
✅ 答案:
是的!你说的方式确实是“基于组件”的组合方式,而不是传统的“类继承”。
在Unreal中,这两种方式都可以让蓝图获得 C++ 写好的功能,但原理完全不同,我们下面详细对比。
🧱 方法对比:继承 vs 组件组合
方式 | 说明 |
---|---|
✅ 继承(Inheritance) | 蓝图类直接继承你写的 C++ 类(例如 AMyBoatActor),从而拥有所有属性和函数。 ➡ 蓝图类就是你的 C++ 类的子类 |
✅ 组件组合(Composition) | 你写的是一个 C++ 组件类(继承自 UActorComponent), 然后蓝图中将其添加为一个组件,通过它来使用 C++ 写的功能。 |
🔧 你要实现“添加 C++ 类功能作为节点”,需满足以下条件:
- 你写的 C++ 类应该是一个 组件类,比如:
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class YOURGAME_API UBoatMovementComponent : public UActorComponent
{GENERATED_BODY()public:UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Boat")float Speed = 200.0f;UFUNCTION(BlueprintCallable, Category = "Boat")void MoveForward(float Value);
};
注意这里继承自的是
UActorComponent
,不是AActor
!
-
然后你可以在任何蓝图类中:
-
添加组件 → 选择
BoatMovementComponent
-
然后在蓝图事件图中使用:
Get BoatMovementComponent
→ 调用MoveForward
- 设置
Speed
等变量
-
🎮 示例图景:
你写了这个 C++ 组件:
UCLASS(Blueprintable, meta=(BlueprintSpawnableComponent))
class UBoatWeaponComponent : public UActorComponent
{GENERATED_BODY()public:UFUNCTION(BlueprintCallable)void FireWeapon();
};
然后你在蓝图 BP_boat
中:
- 添加
BoatWeaponComponent
组件 - 在事件图中调用
FireWeapon
这就实现了“我不继承类,但我能用功能”的组合式设计。
✅ 总结:你提到的两种方法分别是:
方式 | 关键词 | 典型用法 |
---|---|---|
✅ 类继承 | 父类、继承 | BP_boat 继承自 AMyBoatActor |
✅ 组件组合(你问的) | 添加组件、节点 | 在蓝图中添加 UBoatComponent 使用其函数 |
🧠 开发建议:
情况 | 推荐方式 |
---|---|
你的蓝图对象有“明确的核心身份” | 用类继承 |
你的功能是“可复用的模块”(如健康、移动、射击) | 用组件组合 |
你希望多个蓝图复用同一功能逻辑 | 用组件组合 |
你要快速做原型、可视化逻辑复杂 | 用蓝图继承 + C++ 核心类 |
如果你愿意,我可以帮你把你当前的 C++ 类改造成组件,并告诉你怎么在蓝图中添加它,创建节点调用它的函数。你要不要尝试这种方式?可以贴下你写的 C++ 类代码或说下它的功能,我来帮你模块化 👇
继续提问
我之所以不倾向于使用继承类的方式,是因为我现在手头拥有的蓝图类并不是我自己做的,而是别人的,是我导入进来的, 所以我对它的内在机理并不是很熟悉而由于它的内在机理不是很重要,所以我不用太过熟悉,然而如果我采用新建蓝图来继承C++类的方式,过程中需要将现在的蓝图的所有变量复制到新的蓝图中来,这个过程你说有类型、默认值、暴露设置(Expose on Spawn)等可能需要重新设置,那么一旦确有其事,那么我可能是无法很方便的发现这些需要重新设置的参数,导致要么之后会报莫名其妙的错误,要么没有报错,但是有些参数变化了以后我想去修改却不知道在哪里怎么修改。 所以我希望尽可能不要去变动现在的蓝图的任何设置,所以最好的方法就是新建一个副本,然后在这个副本的基础上,直接添加一个C++类的组件接入进去。所以我决定采用第二种方法。
这是我决定采用第二种方法接入我写的C++类的功能的方式的理由。你对此怎么看?
回答
你的思考非常周全,而且这个决策非常合理,我完全支持你选择组件组合的方式来接入你写的 C++ 功能。你权衡了风险、可维护性、可逆性,这正是一个成熟开发者应有的判断。
✅ 为什么你的决定是明智的?
✅ 1. 避免破坏已有蓝图结构
你导入的蓝图不是你自己写的,结构复杂且不透明。如果你用继承的方式,就必须新建蓝图并手动迁移逻辑,这一过程非常容易遗漏细节(比如默认值、变量是否暴露、组件设置、事件绑定等)。
这些问题你提得非常准确:
“一旦确有其事,那么我可能是无法很方便地发现这些需要重新设置的参数”
这正是很多项目迁移出 bug 的根源。
✅ 2. 组件式方式可控性高、低耦合
组件是独立模块,只影响你加进去的功能,不会动原有蓝图结构。你可以:
- 自己决定什么时候激活组件逻辑
- 随时移除组件,不影响蓝图本体
- 在多个蓝图中复用同一个组件(减少重复代码)
这是一种非侵入式扩展,非常适合你当前这种“使用第三方蓝图”的情况。
✅ 3. 开发效率高,可回滚、可调试
用组件:
- 添加简单
- 调试方便(你可以只调试组件)
- 回滚容易(删掉组件或禁用它就行)
比起迁移蓝图继承结构,你在使用中掌控力更强。
🔧 开发建议:组件化接入你的功能
既然你打算用组件方式,我可以帮你梳理一个清晰的工作流(你也可以直接参考这个模板):
🎯 目标:让现有蓝图(BP_boat)通过组件接入你写的 C++ 功能
✅ 第一步:写一个组件类
// BoatFunctionComponent.hUCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class YOURGAME_API UBoatFunctionComponent : public UActorComponent
{GENERATED_BODY()public:UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Boat")float MaxSpeed = 300.0f;UFUNCTION(BlueprintCallable, Category = "Boat")void ActivateTurbo();
};
注意:
BlueprintSpawnableComponent
允许你在蓝图中添加这个组件- 使用
BlueprintCallable
让你能在蓝图里调用函数
✅ 第二步:在蓝图中添加这个组件
-
打开
BP_boat
-
左侧组件面板 → 添加组件
-
搜索你的
BoatFunctionComponent
→ 添加 -
现在你可以:
- 在图表中拖出该组件 → 调用
ActivateTurbo
- 编辑它的变量,比如
MaxSpeed
- 在图表中拖出该组件 → 调用
✅ 第三步:控制组件功能的激活/禁用
你可以通过蓝图的 BeginPlay 或输入事件:
→ Event BeginPlay→ Get BoatFunctionComponent→ Call ActivateTurbo
🛠️ 可选:通过 TickComponent()
实现持续逻辑
如果你需要持续运作(如速度更新、状态检测),你可以在组件类中覆写:
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
并在构造函数里开启 Tick:
PrimaryComponentTick.bCanEverTick = true;
🧠 小提示:组件的“配置”也可以暴露到蓝图中!
例如你可以写:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Boat|Settings")
bool bTurboEnabled;
然后你就可以在蓝图面板上直接修改这个参数,不用动逻辑。
✅ 总结:你选择的方式有什么优点?
优点 | 说明 |
---|---|
✅ 非侵入式 | 不改变原蓝图结构、不改变量 |
✅ 易于维护 | 调试、回滚简单 |
✅ 易于复用 | 组件可以放在多个蓝图中 |
✅ 模块化清晰 | 所有功能集中在你的组件类中 |
✅ 兼容第三方蓝图结构 | 不需要理解原蓝图的内部机制 |
🎁 Bonus:是否需要我给你一个样板组件?
如果你告诉我你写的功能大概是什么(比如:控制船加速、武器发射、自动导航),我可以直接帮你写一个组件样板代码,并告诉你如何在蓝图中使用它。
你只需要告诉我:
- 你想让蓝图“多出”的功能是什么?
- 是否涉及 Tick / 输入 / 状态更新?
我可以直接给你定制出 C++ 组件 + 蓝图使用流程 👇
继续提问
组件节点的特点是什么?
回答
在虚幻引擎的蓝图系统里,组件节点有着诸多重要特点,下面为你详细介绍:
1. 功能模块化
组件节点把特定功能封装起来,实现了功能的模块化。像静态网格体组件(Static Mesh Component)负责处理3D模型的显示,碰撞组件(Collision Component)用于处理碰撞检测,音频组件(Audio Component)则负责播放声音。这种模块化设计让蓝图的结构更清晰,也提升了代码的复用性。
2. 可组合性
一个Actor(游戏中的实体)能够包含多个不同类型的组件节点,通过组合这些组件,可以构建出功能丰富的游戏对象。例如,一个角色Actor可能会包含骨骼网格体组件(Skeletal Mesh Component)、胶囊体碰撞组件(Capsule Collision Component)、移动组件(Movement Component)以及光照组件(Light Component)等。
3. 层次结构
组件节点之间可以形成父子关系,以此定义相对位置和变换。比如,武器组件可以作为子组件附着在角色的手部骨骼上,当角色移动或做出动作时,武器也会跟着一起运动。
4. 独立属性和事件
每个组件节点都有自己独立的属性和事件。以粒子系统组件(Particle System Component)为例,它有发射速率、生命周期、粒子大小等属性,还有粒子开始发射、结束发射等事件。这些属性和事件能独立于Actor进行配置。
5. 可视化编辑
在编辑器中可以直观地对组件节点进行可视化编辑。你能够直接调整组件的位置、旋转和缩放,还能预览组件的效果,比如调整光照组件的颜色和强度,或者预览粒子系统的效果。
6. 运行时动态控制
在游戏运行期间,可以通过蓝图代码动态地控制组件节点。你可以启用或禁用组件,修改组件的属性,或者添加、移除组件。例如,在角色死亡时禁用碰撞组件,或者在触发事件时动态添加特效组件。
7. 继承和自定义
可以基于现有的组件节点派生出自定义组件,从而扩展其功能。比如,创建一个自定义的武器组件,在其中添加特殊的攻击逻辑或者特效。
8. 物理模拟支持
部分组件节点专门用于物理模拟,像刚体组件(Static Mesh Component with Physics)、弹簧臂组件(Spring Arm Component)等。这些组件能够与物理引擎进行交互,实现真实的物理效果。
9. 与其他节点协同工作
组件节点可以和蓝图中的其他节点,如事件节点、函数节点、变量节点等协同工作,实现复杂的游戏逻辑。例如,通过事件节点监听碰撞事件,然后调用组件的函数来处理碰撞结果。
10. 跨蓝图复用
组件节点可以在多个蓝图之间复用。创建一个通用的组件后,能将其添加到不同的Actor蓝图中,避免了重复开发。
11. 支持多种类型
虚幻引擎提供了多种类型的组件节点,涵盖了渲染、物理、AI、音频、输入等多个领域。常见的组件类型包括:
- 静态网格体组件(Static Mesh Component)
- 骨骼网格体组件(Skeletal Mesh Component)
- 碰撞组件(Box Collision、Sphere Collision等)
- 粒子系统组件(Particle System Component)
- 音频组件(Audio Component)
- 光照组件(Point Light、Spot Light等)
- 摄像机组件(Camera Component)
- 移动组件(Character Movement Component、Projectile Movement Component等)
- AI感知组件(AIPerception Component)
- 弹簧臂组件(Spring Arm Component)
- 文本渲染组件(Text Render Component)
12. 事件驱动
组件节点可以通过事件与其他游戏元素进行交互。例如,碰撞组件可以触发OnComponentHit事件,粒子系统组件可以触发OnSystemFinished事件。
13. 性能优化
组件节点的设计有助于性能优化。可以根据需要启用或禁用组件,或者设置组件的更新频率,从而减少不必要的计算。
14. 与C++结合
组件节点可以用C++实现,然后在蓝图中使用。这种方式适合实现复杂的核心功能,同时保持蓝图的易用性。
15. 支持蓝图可视化脚本
即使不编写代码,也能通过蓝图可视化脚本来配置和控制组件节点,降低了开发门槛。
组件节点是虚幻引擎蓝图系统的重要组成部分,它通过模块化、可组合性和可视化编辑等特点,让开发者能够高效地构建复杂的游戏对象和功能。
继续提问
那么将组件节点大致理解为是多个一般的节点的封装,是否可行?
回答
可以将组件节点大致理解为多个一般节点的封装,不过这种理解不够全面,下面为你详细分析:
相似之处
1. 功能封装
组件节点和一般节点都具备封装功能的特点。一般节点(如函数节点)是把一系列操作封装在一起,而组件节点则是将多个相关的功能(包括属性、事件和函数)整合起来,形成一个更高层次的功能单元。
2. 复用性
两者都能提高代码的复用性。一般节点可以在同一个蓝图中多次调用,组件节点则可以在多个蓝图之间复用,例如,一个自定义的武器组件能被添加到不同角色的蓝图中。
3. 抽象层级
组件节点处于比一般节点更高的抽象层级。它隐藏了内部实现的细节,为用户提供了一个简洁的接口。比如,粒子系统组件将复杂的粒子模拟逻辑封装起来,用户只需设置发射速率、粒子生命周期等参数即可。
不同之处
1. 独立的实体
组件节点是游戏世界中的独立实体,拥有自己的变换(位置、旋转、缩放)和生命周期。而一般节点只是蓝图图表中的一个操作单元,依附于蓝图存在,没有物理实体。
2. 与Actor的关系
组件节点通常作为Actor的一部分存在,多个组件可以组合成一个完整的Actor。例如,一个角色Actor可能包含骨骼网格体组件、碰撞组件、移动组件等。而一般节点是直接用于实现蓝图逻辑的,不与Actor建立直接的组合关系。
3. 可视化编辑
组件节点支持在编辑器中进行可视化编辑,用户可以直接调整组件的位置、形状等属性,并实时预览效果。一般节点则主要通过蓝图图表进行编辑。
4. 物理和渲染功能
许多组件节点专门用于物理模拟和渲染,像静态网格体组件、碰撞组件、光照组件等。这些组件与引擎的底层系统紧密集成,一般节点很难实现同等的功能。
5. 事件系统
组件节点有自己独立的事件系统,例如碰撞组件会触发OnComponentHit事件,粒子系统组件会触发OnSystemFinished事件。这些事件与组件的特定功能相关,而一般节点的事件通常是通用的流程控制事件。
6. 层级结构
组件节点可以形成父子层级关系,从而定义复杂的变换关系。比如,武器组件可以作为子组件附着在角色的手部骨骼上。一般节点之间不存在这样的层级关系。
7. 运行时动态操作
在游戏运行时,可以动态地添加、移除或替换组件节点,还能修改组件的属性。这种动态性使得游戏对象可以根据不同的情况改变其功能。一般节点在运行时则相对固定。
总结
组件节点可以看作是一种特殊的“超级节点”,它不仅封装了多个一般节点的功能,还具备独立的实体、可视化编辑、物理渲染能力等特性。虽然从功能封装的角度可以将其大致理解为多个一般节点的封装,但组件节点在虚幻引擎中的角色和能力要比简单的节点集合丰富得多。
如果用一个比喻来形容,一般节点就像是积木,而组件节点则是用积木搭好的具有特定功能的模块(如房子、汽车),这些模块可以直接使用,也可以组合成更复杂的结构。
继续提问
难道C++类的功能如果要能够接入蓝图类,则必须以组件类的身份被导入,不能够以其他类型的节点的形式被导入吗?
回答
这是一个很关键的问题,我们来系统梳理一下:
是否只有把C++类写成组件(如
UActorComponent
)才能被蓝图类“接入”?是否不能以其他形式(比如某种“节点”)将 C++ 类功能引入蓝图?
✅ 简要结论:
不是必须写成组件类(
UActorComponent
)才可以接入蓝图,
但如果你希望**“蓝图类不继承C++类”**的前提下,还能用到你写的 C++ 功能,那组件是最灵活、最可控的方式。
蓝图能通过以下方式接入 C++ 编写的功能:
🧩 接入 C++ 功能的几种方式
方式 | 是否需要继承 | 是否适合“非自己写的蓝图” | 简述 |
---|---|---|---|
✅ 继承 C++ 类 (AActor , APawn , 等) | 是 | ❌ | 蓝图继承你的 C++ 类,获得所有成员变量和函数 |
✅ 添加 C++ 组件类 (UActorComponent ) | 否 | ✅ | 蓝图中添加组件,通过其提供的函数/变量使用功能 |
✅ 使用静态函数库类 (BlueprintFunctionLibrary ) | 否 | ✅ | 蓝图通过“节点”调用你写的工具函数(无状态) |
✅ 使用 UObject 子类 | 否 | 有限制 | 蓝图中可动态创建你的 C++ 类的实例,然后使用其方法(但稍复杂) |
✅ 方式 1:组件类(你现在采用的方式)
- 优点:有状态、可 Tick、可复用、易插拔
- 使用方式:蓝图中添加组件 → 使用组件函数/变量
✅ 方式 2:静态函数类(Function Library)
你可以写一个 Blueprint Function Library:
UCLASS()
class YOURGAME_API UBoatFunctionLibrary : public UBlueprintFunctionLibrary
{GENERATED_BODY()public:UFUNCTION(BlueprintCallable, Category = "BoatUtils")static float CalculateBoatSpeed(float Throttle, float MaxSpeed);
};
然后在任何蓝图里都可以直接搜索这个函数节点:
🔹CalculateBoatSpeed
✅ 适合工具类逻辑,例如:
- 数据换算
- 状态判断
- 数学函数
❌ 不适合需要状态(变量)或 Tick 的逻辑
✅ 方式 3:UObject 子类(动态创建实例)
你也可以写一个普通的 C++ 类:
UCLASS(Blueprintable)
class YOURGAME_API UBoatHelper : public UObject
{GENERATED_BODY()public:UFUNCTION(BlueprintCallable)void DoSomething();
};
然后在蓝图中通过 Construct Object from Class
创建一个 UBoatHelper
的实例,再调用 DoSomething
。
适合:
- 工具类、单次操作逻辑
- 有生命周期管理需求
但缺点是需要显式创建,管理稍复杂。
✅ 小结:你可以不通过继承,也能让 C++ 功能出现在蓝图中:
技术方式 | 是否适合你当前情况(已有第三方蓝图) |
---|---|
✅ ActorComponent | ✅✅✅(推荐) |
✅ FunctionLibrary | ✅✅(适合纯函数,无状态) |
⛔ 子类继承 C++ 类 | ❌(不适合已有第三方蓝图) |
✅ UObject 实例化 | ✅(较高级用法,适合高级控制) |
✅ 最适配你的情况:
你现在的需求是:
已有第三方蓝图类,不想改动其结构,只想“挂载”自己的功能模块进去使用。
✅ 推荐优先级:
- 组件类方式 → 如果你的功能需要保存变量、处理 Tick、响应事件等
- 函数库方式 → 如果你的功能是纯计算、工具性逻辑(无状态)
- UObject 工厂创建 → 如果你想做“模块对象”,可动态创建和回收(复杂一点)
🧠 你可以这样思考:
- 功能是持续存在/有状态? ➜ 用组件
- 功能是静态逻辑/一次性? ➜ 用 FunctionLibrary
- 功能像一个小黑盒逻辑模块,可随时创建销毁? ➜ 用 UObject
如果你告诉我你写的 C++ 功能具体是什么,我可以直接告诉你用哪种方式最合适,并写好接口让你在蓝图中一拖就用 👇
你需要我帮你做个例子吗?
继续提问
我的C++类是很早以前写的,我忘记了其中是否加入了一些必要的代码,(我是指那些使得这个C++类能够作为组件节点被接入蓝图类的代码),那么是否可以直接在蓝图类中尝试着按照一般的接入步骤来进行验证?如果能够成功,就说明我已经有了前述的“必要的代码”,那么我就不需要回顾C++类的源码了,否则我再花些时间去看我的C++源码并对其做一些必要的修改。 你觉得这个验证是否可以将C++类接入蓝图类的方法是否是足够机智的?如果你认可这个方法,就提供给我常规的接入蓝图类的步骤
回答
你的这个思路可以说是非常机智且现实可行的验证方法,完全值得推荐。
✔️ 你问的是:
我忘记当初写的 C++ 类是否加了必要的宏/标签,让它能作为组件被添加到蓝图中。那我能不能直接尝试在蓝图中添加它,来验证它是否支持?
✅ 答案:
是的,完全可以!而且这是最有效率的验证方式之一。
如果你的 C++ 类已经具备以下特性,它就会出现在蓝图组件添加列表中:
- 是
UActorComponent
或子类 - 标记为
BlueprintSpawnableComponent
- 使用了
UCLASS
宏
只要满足这些条件,UE 会自动识别它并将其列入可添加的组件类中。
🔍 所以你要做的验证,就是尝试在蓝图中“添加组件”,看它在不在列表里。
✅ 常规接入蓝图类的步骤(用于验证组件是否可以被添加)
你可以跟着以下步骤来验证:
🧪 验证步骤:蓝图中尝试添加组件
1. 打开蓝图类(比如 BP_boat
)
2. 在左侧组件面板中:
- 点击
添加组件(Add Component)
3. 在搜索框中输入你写的组件类名(例如 BoatFunctionComponent
)
- 如果类名是
UBoatFunctionComponent
,就搜BoatFunctionComponent
4. 观察结果:
结果 | 意义 |
---|---|
✅ 你能看到并添加该组件 | ✔️ 类定义正确,包含所有必要的宏,可以直接使用 |
❌ 组件不出现在搜索结果中 | ❌ 类缺少必要的宏、继承方式不对,需回顾 C++ 代码 |
✅ 如果没找到该组件,该检查 C++ 类的三项内容:
如果组件没能添加进去,说明可能缺少以下其中一项:
// 1. UCLASS 宏
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class YOURGAME_API UBoatFunctionComponent : public UActorComponent
{GENERATED_BODY()...
};
要素 | 是否必要 | 说明 |
---|---|---|
UCLASS(...) | ✅ | 宏必须存在,Unreal 的反射机制需要 |
BlueprintSpawnableComponent | ✅ | 允许蓝图中作为组件添加 |
继承自 UActorComponent | ✅ | 组件类必须继承该基类或其子类 |
🎯 总结:
✔️ 你的方法——尝试在蓝图中添加组件,判断是否已配置好——是一种非常合理、快速、低成本的验证方式,
非常适合你这种“C++写得早,不想翻源码”的场景。
✅ 结论:你这套逻辑思路完全正确,并建议使用!
💡 额外建议:
如果你将来要复查某个类是否支持蓝图组件添加,但不想靠蓝图试验,也可以用这些方式:
方法 A:查头文件中是否有以下宏
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
方法 B:在 Visual Studio 中搜索继承关系
确认是否继承自 UActorComponent
👋 如果你想让我帮你判断一个类是否可添加,也可以直接贴出类名或部分定义,我可以马上分析 ✅
你要不要现在就试一下你的类名能否添加?或者给我类名我帮你一起试?
继续提问
在UE5的蓝图编辑面板中,actions和components的区别是什么?
回答
在UE5的蓝图编辑面板中,Actions(操作) 和 Components(组件 是两个不同的概念,分别用于不同的场景和功能。以下是它们的主要区别:
1. 定义与角色
Components(组件)
- 定义:组件是蓝图中的功能模块,用于封装特定的行为或属性。它们是游戏对象(如Actor)的组成部分,可以在编辑器中可视化配置,并在运行时独立工作。
- 角色:组件负责实现具体的功能,例如渲染模型(Static Mesh Component)、处理碰撞(Collision Component)、播放声音(Audio Component)等。
Actions(操作)
- 定义:操作通常指蓝图中的节点或函数调用,用于执行特定的任务或逻辑。它们是蓝图图表中的执行单元,通过连接线组织成逻辑流程。
- 角色:操作负责实现动态逻辑,例如条件判断(Branch)、变量赋值、调用函数等。
2. 可视化表现
Components
- 在蓝图编辑器的Components面板中可见,以树形结构展示。
- 每个组件有独立的属性面板,可直接编辑其参数(如位置、旋转、材质等)。
- 组件通常有可视化的预览效果(如网格体、碰撞体、光照等)。
Actions
- 在蓝图编辑器的Event Graph(事件图表)h中可见,以节点形式存在。
- 通过引脚(Pins)连接其他节点,形成执行流程。
- 操作节点本身没有可视化外观,仅代表逻辑操作。
3. 功能与用途
Components
- 封装独立功能:例如,弹簧臂组件(Spring Arm Component)用于相机跟随,粒子系统组件(Particle System Component)用于特效。
- 可组合性:多个组件可组合成复杂的游戏对象(如角色、武器等)。
- 生命周期管理:组件有自己的生命周期(如BeginPlay、Tick),可独立响应事件。
Actions
- 执行逻辑流程:例如,使用Set Variable节点修改变量值,用If-Else节点进行条件判断。
- 事件驱动:操作通常由事件(如按键输入、碰撞检测)触发,或作为函数的一部分被调用。
- 临时操作:操作节点本身不存储状态,仅在执行时产生效果。
4. 交互方式
Components
- 通过蓝图类的默认设置进行配置(如在编辑器中拖放、调整属性)。
- 在运行时可通过蓝图代码动态操作(如启用/禁用组件、修改属性值)。
Actions
- 在事件图表中通过拖拽节点并连接引脚来创建逻辑。
- 可调用组件的函数或访问其属性(例如,通过Get Component节点获取组件引用)。
5. 示例对比
场景 | Component | Action |
---|---|---|
添加3D模型到角色 | 添加Static Mesh Component | 无(组件负责渲染,无需额外操作节点) |
处理碰撞事件 | 添加Sphere Collision Component | 在事件图表中使用OnComponentHit节点 |
控制角色移动 | 添加Character Movement Component | 使用Move Forward/Move Right节点 |
播放音效 | 添加Audio Component | 使用Play Sound节点 |
实现条件逻辑 | 无 | 使用Branch节点(属于操作) |
6. 核心区别总结
维度 | Components | Actions |
---|---|---|
本质 | 功能模块/实体 | 逻辑操作/执行单元 |
可视化位置 | Components面板 | Event Graph(事件图表) |
生命周期 | 随Actor创建/销毁 | 按需执行(事件触发或函数调用) |
状态存储 | 可存储属性值(如位置、材质) | 无状态(仅执行逻辑) |
用途 | 实现游戏对象的静态/动态功能 | 实现动态逻辑流程 |
常见误区
- 混淆术语:在蓝图中,“Action”有时被非正式地用于指代任何可执行的操作(包括组件函数调用),但严格来说,组件是实体,而操作是逻辑。
- 过度依赖组件:复杂的逻辑(如AI决策、数学计算)更适合用操作节点实现,而非创建大量组件。
如何选择?
- 使用组件:当需要封装独立功能、复用代码或可视化配置时(如添加碰撞体、粒子效果)。
- 使用操作:当需要实现动态逻辑流程、条件判断或临时任务时(如响应输入、计算数值)。
理解这两者的区别,能帮助你更高效地组织蓝图结构,避免功能冗余或逻辑混乱。
继续提问
C++类是否可以以Actions的形式在事件图表中被接入蓝图类呢?如果可以,这种方式和前面提到的以组件的形式被接入蓝图类的区别在哪里?优劣对比是如何?
回答
这是一个非常深入、也非常有价值的问题。
你问的是:
C++类的功能是否可以以“Actions”的形式(即作为蓝图节点)出现在蓝图事件图中?这种方式和“作为组件被添加进蓝图类”的方式有什么区别?优劣如何?
我们来逐步拆解,分别讲清楚:
🧠 首先,什么是你说的“Actions”?
你这里说的“Actions”,指的是:
- 在蓝图的事件图表中,右键 → 搜索你 C++ 写的函数
- 然后把它以蓝图节点的形式添加进事件图中
✅ 是的,这是完全可以实现的,而且是 Unreal C++ 和蓝图互通最基础的桥梁。
但实现它的方法取决于你的 C++ 类的类型和你希望函数怎么出现。
✅ 情况一:你希望在蓝图中调用你的 C++ 函数 —— 用 BlueprintCallable
你可以在 C++ 类中声明函数为蓝图可调用的:
UFUNCTION(BlueprintCallable, Category = "Boat")
void StartEngine();
然后在蓝图中:
- 右键事件图空白处
- 输入
Start Engine
- 你就会看到它出现在节点搜索中(只要蓝图上下文里能访问这个类)
那么……怎么让这些函数出现在某个蓝图类的事件图中呢?
取决于你C++类的归属关系:
✅ 方式 A:你的类是当前蓝图的父类(继承方式)
- 如果蓝图是你 C++ 类的子类(即
BP_Boat
继承自ABoatBase
) - 你写的函数就自动出现在蓝图中,可直接右键搜索调用
✅ 非常直观
❌ 不适合你当前使用第三方蓝图的情况
✅ 方式 B:你的类是组件类,已被添加到蓝图中
- 你在蓝图中添加了
UBoatComponent
- 然后你可以在事件图中拖出这个组件 → 搜索其函数作为节点使用
✅ 模块化 + 状态可控
✅ 适合你当前这种“添加功能但不修改原始结构”的场景
✅ 方式 C:你的类是一个静态函数类(Function Library)
你可以写一个“纯功能库类”:
UCLASS()
class UBoatFunctionLibrary : public UBlueprintFunctionLibrary
{GENERATED_BODY()public:UFUNCTION(BlueprintCallable, Category = "Boat|Math")static float CalculateAcceleration(float Mass, float Force);
};
这种函数会出现在蓝图节点中(右键搜索)不依赖任何对象,可以像数学函数一样使用。
✅ 易用
❌ 没有状态、不处理内部数据
✅ 方式 D:UObject 类,被蓝图实例化后使用其函数
- 你可以写一个
UObject
子类 - 然后在蓝图中使用
Construct Object From Class
节点来创建它 - 得到一个变量 → 调用其 BlueprintCallable 的方法
✅ 灵活
❌ 使用门槛略高,生命周期需要你自己管理
✅ 总结:函数(Action 节点) vs 组件(Component 模块)的区别
维度 | 函数节点(Action) | 组件(Component) |
---|---|---|
来源 | 来自 C++ 函数,声明为 BlueprintCallable | 来自继承自 UActorComponent 的 C++ 类 |
需要对象上下文? | 是(当前蓝图、某个组件、或实例) | 是(组件必须添加到蓝图上) |
能否保存状态变量? | ❌ 通常是无状态函数 | ✅ 有完整生命周期与状态管理 |
是否能持续执行逻辑 | ❌(除非你手动挂 Tick) | ✅ TickComponent() 可持续运行 |
适合做什么? | 工具函数、数学逻辑、事件响应 | 复杂逻辑模块、AI、移动控制、战斗行为等 |
与第三方蓝图兼容? | ✅(只要能获取对象) | ✅(你只添加组件即可) |
是否易复用? | ✅(只要函数是静态或可访问) | ✅(模块化复用强) |
✅ 最适合你的情况:
你当前的目标是:
对第三方蓝图添加自己的逻辑模块,同时尽量不动它的结构
那么优先级排序建议如下:
用途 | 推荐方式 |
---|---|
✅ 有状态、需持续运行的功能 | UActorComponent (组件方式) |
✅ 一次性或静态计算/辅助工具 | UBlueprintFunctionLibrary (函数方式) |
✅ 需实例化并保持少量状态 | UObject (高级方式) |
✅ 最后回答你的核心问题:
“C++类是否可以以 Action 节点形式被接入蓝图?”
✔️ 可以,前提是函数被标记为 BlueprintCallable
,并且对象上下文正确。
“这种方式和作为组件被接入的方式有什么区别?”
➡️ 函数是调用式、无状态逻辑,组件是模块式、有状态逻辑
如果你愿意,我可以帮你写一个函数类、组件类,让你分别试试它们在蓝图中表现的区别。你只需要告诉我你的功能目标,比如“加速逻辑”、“航线规划”之类的即可 👇
继续提问
我现在手头的C++类名字叫做SetGetActorLocation,我在事件图表中右键后输入SetGetActorLocation,跳出来如图的信息。请解释其中的Casting的含义,以及解释下属的Cast to SetGetActorLocation和 Cast to SetGetActorLocation Class 的含义
回答
你现在看到的是蓝图中的一个非常关键的机制:类型转换(Casting)。这在将 C++ 类“接入”蓝图功能中,也扮演着重要角色。
🎯 场景说明:
你有一个 C++ 类,名叫 SetGetActorLocation
,你在蓝图事件图中右键搜索它,出现了如图所示的:
Utilities└── Casting├── Cast To SetGetActorLocation└── Cast To SetGetActorLocation Class
你想知道这些“Cast”是什么意思,怎么用。
✅ 先说结论:这是类型转换节点,不是添加组件、也不是函数调用。
它们的作用是:
🔁 把某个已有的对象转换为你定义的 C++ 类类型,以便调用其中的函数或访问变量。
🧩 什么是 Casting(类型转换)?
在蓝图中,很多时候你拿到的是一个“基类指针”,比如 Actor
,你需要“转型”为你自己定义的类,才能调用你在 C++ 中定义的函数。
就像 C++ 中这样:
AActor* MyActor = ...;
AMyCustomActor* Custom = Cast<AMyCustomActor>(MyActor);
if (Custom)
{Custom->MyFunction();
}
在蓝图中也是一样的流程,只是通过“Cast To XXX”节点来完成。
✅ 分析你看到的两个节点:
1️⃣ Cast To SetGetActorLocation
-
功能:尝试将某个对象 转换为你的类
SetGetActorLocation
-
用法场景:
- 你在蓝图中拿到一个对象(如
Actor
、Component
) - 你知道它其实是
SetGetActorLocation
类型(或其子类) - 你想访问它里面的 C++ 函数或变量
- 你在蓝图中拿到一个对象(如
-
蓝图操作方式:
- 拖一个对象引用 → 连接到
Cast To SetGetActorLocation
→ 成功后输出端就可以访问你的类的函数和变量
- 拖一个对象引用 → 连接到
✔️ 如果转换成功(不为null),你就可以使用你写的 SetLocation
、GetLocation
等函数
2️⃣ Cast To SetGetActorLocation Class
- 功能:这个是对类的转换,而非对象实例
- 用法较少,适用于你需要操作类本身的特殊情况
- 例如你从某个地方获取了一个
UClass
类型(比如Spawn Actor from Class
),你想确认这个类是不是SetGetActorLocation
的类
❗通常你在操作“类”的时候才会用到它,比如配合类引用变量使用
🧠 那这说明什么?
你的类 SetGetActorLocation
:
- 已被 Unreal 正确识别 ✅
- 至少是
UObject
的子类(因为能 Cast) - 但目前你没有在蓝图上下文中获得一个该类的实例,所以无法使用你写的函数
✅ 如何让你在蓝图中使用该类的功能?
方案 1:你写的类是组件类(继承自 UActorComponent
)?
→ 如果是,建议你:
- 检查是否在
UCLASS
中加了BlueprintSpawnableComponent
- 然后在蓝图中添加它作为组件
- 然后可以直接拖出组件变量 → 访问你写的函数(不用 Cast)
✅ 推荐使用组件方式的本质原因:蓝图中可以直接访问组件成员,而不用手动 Cast
方案 2:你写的类是 UObject
派生类(不是组件)?
→ 那么你需要通过以下方式创建并使用它:
A. 在蓝图中使用 Construct Object from Class
创建该类的实例:
→ Construct Object from Class(类选择 SetGetActorLocation)→ Promote to variable→ 你就可以从这个变量拖出你的函数使用了
这时候你可以使用你类中的 BlueprintCallable
函数作为节点(只要你定义了)
✅ 总结你现在看到的 Cast 节点的含义:
节点名称 | 含义 |
---|---|
Cast To SetGetActorLocation | 试图将一个对象强制转换为你写的类的实例,成功后可以访问其函数/变量 |
Cast To SetGetActorLocation Class | 试图将一个类对象(非实例)转换为你的类,用于高级场景,如类判断、反射操作 |
🧠 优劣对比:组件 vs Action 节点(函数) vs Cast
方式 | 优点 | 缺点 |
---|---|---|
组件方式 | 有生命周期、有状态、Tick、可在蓝图中直接访问 | 需要继承 UActorComponent ,要加组件宏 |
函数节点(BlueprintCallable) | 可作为蓝图节点调用,适合工具函数 | 需要创建对象或获取上下文 |
Cast | 动态判断对象类型、访问类函数 | 依赖你能拿到对象引用,代码结构更复杂 |
✅ 下一步建议:
如果你希望在蓝图中直接使用 SetGetActorLocation
的函数,请你检查以下内容:
SetGetActorLocation
是否是继承自UActorComponent
?- 是否加了
BlueprintSpawnableComponent
? - 是否在类中写了
UFUNCTION(BlueprintCallable)
的方法?
我可以帮你一步步调整这个类,让它在蓝图中能作为组件添加或作为实例被创建使用。
你方便贴出这个类的定义头文件吗?或者告诉我它是继承自哪一类(比如 UObject
, AActor
, UActorComponent
)?这样我可以马上帮你判断该怎么接入。
继续提问
组件节点和事件图表中的actions(用节点表征)之间的关系?
回答
在虚幻引擎的蓝图系统中,**组件节点(Components)和事件图表中的操作节点(Actions)**是紧密协作的两个核心概念,它们共同构成了蓝图的功能实现方式。以下是它们的关系及协作模式:
1. 组件节点(Components):功能的载体
- 定义:组件是蓝图中的功能模块,封装了特定的行为或属性(如渲染、碰撞、移动等)。
- 特点:
- 作为Actor的组成部分存在(例如,角色Actor可能包含骨骼网格体组件、碰撞组件、移动组件)。
- 有独立的生命周期(如BeginPlay、Tick)和属性(如位置、材质)。
- 在蓝图编辑器的Components面板中可视化配置。
- 示例:
- Static Mesh Component:渲染3D模型。
- Box Collision Component:处理碰撞检测。
- Audio Component:播放声音。
2. 操作节点(Actions):逻辑的执行者
- 定义:操作节点是蓝图事件图表(Event Graph)d中的执行单元,用于实现动态逻辑(如条件判断、函数调用、变量修改)。
- 特点:
- 通过引脚(Pins)连接形成逻辑流程。
- 通常由事件(如按键输入、碰撞触发)驱动执行。
- 不存储状态,仅在执行时产生效果。
- 示例:
- Branch节点:条件判断。
- Set Variable节点:修改变量值。
- Call Function节点:调用函数(包括组件的函数)。
3. 两者的关系
3.1 组件为操作提供数据和功能
- 组件节点暴露属性和函数,供事件图表中的操作节点访问。
- 例如:通过Get Component节点获取组件引用,然后调用其函数或访问其属性。
- 示例代码(蓝图伪代码):
Event BeginPlay -> Get Mesh Component -> Set Material (修改网格体材质)Get Audio Component -> Play Sound (播放声音)
3.2 操作节点控制组件的行为
- 事件图表中的操作节点可以动态控制组件(如启用/禁用、修改属性、调用函数)。
- 例如:
Event OnActorHit -> If (Damage > 10) -> Get Particle System Component -> Activate (触发特效)Get Audio Component -> Play Sound (播放音效)
- 例如:
3.3 组件触发事件,操作节点响应
- 组件可以触发事件,这些事件可被事件图表捕获并处理。
- 例如:
Component: Box Collision Component -> OnComponentHit事件 Event Graph: 捕获OnComponentHit -> 执行逻辑(如造成伤害、播放特效)
- 例如:
3.4 协作实现完整功能
- 复杂功能通常需要组件和操作节点协同工作。
- 例如,实现角色跳跃:
1. 组件:Character Movement Component(提供跳跃功能) 2. 操作:- Event OnKeyPressed(空格) -> - Call Character Movement Component -> Jump()
- 例如,实现角色跳跃:
4. 协作示例
场景:角色被击中后播放特效并减血
组件配置:
- 骨骼网格体组件(Skeletal Mesh Component)
- 粒子系统组件(Particle System Component,用于受伤特效)
- 音频组件(Audio Component,用于受伤音效)事件图表逻辑:
Event OnComponentHit (由碰撞组件触发) ->If (Damage > 0) ->Get Particle System Component -> ActivateAtLocation (播放特效)Get Audio Component -> Play (播放音效)Get Character Health Variable -> Subtract (减少生命值)If (Health <= 0) -> Call Die() Function (角色死亡)
5. 核心区别总结
维度 | 组件节点(Components) | 操作节点(Actions) |
---|---|---|
本质 | 功能模块/实体 | 逻辑执行单元 |
存储位置 | Components面板 | Event Graph(事件图表) |
状态 | 有状态(存储属性值,如位置、材质) | 无状态(仅执行逻辑) |
角色 | 提供功能和数据 | 控制流程和调用组件功能 |
生命周期 | 随Actor创建/销毁 | 按需执行(事件触发或函数调用) |
6. 常见问题与最佳实践
6.1 何时使用组件?何时使用操作节点?
- 组件:当需要封装独立功能、复用代码或可视化配置时(如添加碰撞体、粒子效果)。
- 操作节点:当需要实现动态逻辑流程、条件判断或临时任务时(如响应输入、计算数值)。
6.2 避免过度耦合
- 组件应保持功能单一,避免在组件内部实现复杂逻辑。
- 复杂逻辑应放在事件图表或函数中,通过操作节点调用组件功能。
6.3 性能考虑
- 频繁调用组件函数可能影响性能,尽量批量处理或缓存组件引用。
- 使用Event Tick时需谨慎,避免不必要的组件更新。
总结
组件节点和操作节点是蓝图系统的“数据与逻辑分离”设计理念的体现:
- 组件负责封装功能和状态,提供可复用的模块;
- 操作节点负责实现动态逻辑,控制组件的行为和交互。
理解两者的协作关系,能帮助你构建更清晰、高效的蓝图架构。
继续提问
难道只需要提供头文件,就足以判断它是继承自哪一类(比如 UObject, AActor, UActorComponent)吗?
回答
是的,只需要查看类的头文件(.h)h就可以明确判断它的继承关系,因为在C++/Unreal Engine中,类的继承结构是在头文件中显式声明的。
如何通过头文件判断继承关系?
在Unreal Engine的C++类中,继承关系通常在类定义的第一行明确指定。例如:
1. 继承自 UObject
UCLASS()
class MYPROJECT_API UMyObject : public UObject
{GENERATED_BODY()
};
2. 继承自 AActor
UCLASS()
class MYPROJECT_API AMyActor : public AActor
{GENERATED_BODY()
};
3. 继承自 UActorComponent
UCLASS(BlueprintSpawnableComponent)
class MYPROJECT_API UMyComponent : public UActorComponent
{GENERATED_BODY()
};
关键判断依据
-
类声明的第一行:
public UObject
→ 继承自UObjectpublic AActor
→ 继承自Actorpublic UActorComponent
→ 继承自组件
-
UCLASS标签:
BlueprintSpawnableComponent
仅用于组件类(继承自UActorComponent)。- 如果类声明中包含该标签,但实际未继承自UActorComponent,编译会报错。
-
函数宏:
UFUNCTION(BlueprintCallable)
可用于任何UObject派生类,但只有组件类的函数才能在蓝图中通过组件引用调用。
为什么头文件就足够?
- 继承关系是静态的:在C++中,类的继承结构在编译时就确定了,头文件是唯一记录这种关系的地方。
- 无需查看实现:类的方法实现(.cpp文件)不影响其继承关系,因此只需查看头文件即可。
示例分析
假设你有一个名为 USetGetActorLocation
的类,其头文件如下:
UCLASS(BlueprintSpawnableComponent)
class MYPROJECT_API USetGetActorLocation : public UActorComponent
{GENERATED_BODY()public:UFUNCTION(BlueprintCallable)FVector GetActorLocation();UFUNCTION(BlueprintCallable)void SetActorLocation(const FVector& NewLocation);
};
从这个头文件可以直接得出:
- 继承关系:
USetGetActorLocation
是UActorComponent
的子类。 - 蓝图可用性:
BlueprintSpawnableComponent
标签允许在蓝图中生成该组件。BlueprintCallable
方法可在蓝图中调用。
总结
查看头文件足以判断类的继承关系,因为:
- 继承结构在头文件中显式声明。
- 蓝图相关的标签(如
BlueprintSpawnableComponent
)只能用于特定类型的类。
如果你需要进一步分析类的蓝图兼容性,提供头文件是最直接有效的方式。
继续提问
// Copyright 2019-2022 The MathWorks, Inc.
#pragma once
#include “CoreMinimal.h”
#include “Sim3dActor.h”
#include “SetGetActorLocation.generated.h”
UCLASS()
class TESTSIM3DGETSET_API ASetGetActorLocation : public ASim3dActor
{
GENERATED_BODY()
void* SignalReader;
void* SignalWriter;
public:
// Sets default values for this actor’s properties
ASetGetActorLocation();
virtual void Sim3dSetup() override;
virtual void Sim3dRelease() override;
virtual void Sim3dStep(float DeltaSeconds) override;
};
这是头文件,现在你来判断一下它继承自哪一类,以及该如何接入。
回答
非常好,有了这个头文件,我们现在可以准确判断你这个 C++ 类的性质,并明确如何才能让它被蓝图使用。
✅ 分析你的类:ASetGetActorLocation
你定义的类如下:
UCLASS()
class TESTSIM3DGETSET_API ASetGetActorLocation : public ASim3dActor
🧠 继承关系分析
ASetGetActorLocation
是一个 Actor 类(因为它的祖先是AActor
)- 它继承自
ASim3dActor
ASim3dActor
极有可能本身继承自AActor
或其子类(标准 UE4/5 风格)
因此,ASetGetActorLocation
的完整继承链很可能是:
ASetGetActorLocation → ASim3dActor → AActor
✅ 它是一个可放置在场景中的“Actor类”
🧭 回答你的问题:如何将它的功能接入蓝图?
✅ 方法一:让蓝图类继承它(不适合你当前场景)
你可以通过蓝图继承 ASetGetActorLocation
,然后在蓝图中访问其函数。
但如你前面所说,你用的是第三方蓝图(如 BP_boat
),不希望改变其继承结构。
❌ 所以这个方式不适合你当前需求
✅ 方法二:将其实例“Cast”为 ASetGetActorLocation
你目前能看到蓝图中有:
Cast To SetGetActorLocation
Cast To SetGetActorLocation Class
说明它已被引擎正确识别为一个蓝图可用类型。
那你可以这样使用:
步骤:
- 假设你在场景中放置了一个该类的实例(比如通过 C++、蓝图或关卡手动拖进去)
- 在蓝图中获得它的引用(比如通过
Get All Actors of Class
→SetGetActorLocation
) - 拿到引用后,拖出节点 →
Cast To SetGetActorLocation
- Cast 成功后,就能使用其 public 函数(你需要加上
UFUNCTION(BlueprintCallable)
)
✅ 方法三(推荐):将核心功能提取为组件或函数库
因为你当前是想把该类的功能集成到别人的蓝图中(比如 BP_boat),你就会遇到一个问题:
你无法将该类作为“组件”添加到蓝图中,因为它是
AActor
的子类,不是UActorComponent
所以你无法直接在 BP_boat 中:
- 添加一个
SetGetActorLocation
组件 - 然后直接访问它的逻辑
✅ 建议:把核心功能提取出来,放进组件类中
如果你希望这个逻辑能被蓝图模块化使用,你应该这么做:
✅ 新建一个 C++ 组件类(继承自 UActorComponent
):
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class TESTSIM3DGETSET_API UActorLocationComponent : public UActorComponent
{GENERATED_BODY()public:UFUNCTION(BlueprintCallable, Category = "Sim3D")void SetLocation(const FVector& NewLocation);UFUNCTION(BlueprintCallable, Category = "Sim3D")FVector GetLocation() const;
};
然后在 BP_boat
或任何蓝图中添加 ActorLocationComponent
,你就可以在蓝图事件图中:
- 调用
SetLocation
- 调用
GetLocation
这样完全解耦了你原来的 ASetGetActorLocation
类。
🔧 总结当前类的情况:
项目 | 值 |
---|---|
类名 | ASetGetActorLocation |
继承自 | ASim3dActor → 应为 AActor |
是否是组件类 | ❌ 否,不能作为组件添加进蓝图 |
是否能被蓝图使用 | ✅ 可以 Cast,但需要你获得实例引用 |
最推荐的蓝图接入方式 | ❌ 不建议使用当前类直接接入 |
替代方案 | ✅ 把核心功能提取成组件类或函数库 |
✅ 最推荐方案(适配你的目标):
将
ASetGetActorLocation
的功能提炼为一个组件类UActorLocationComponent
,并挂在蓝图BP_boat
上使用。
我可以帮你写出这个组件模板,以及把你的逻辑迁移过去。你只要告诉我:
- 你希望组件中暴露哪些功能?
- 是设置坐标、获取坐标,还是执行 Sim3dStep/Setup/Release?
是否要我帮你把这个类转成一个组件,适合蓝图使用?只需你说“是”,我来写 👇
新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
- 全新的界面设计 ,将会带来全新的写作体验;
- 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
- 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
- 全新的 KaTeX数学公式 语法;
- 增加了支持甘特图的mermaid语法1 功能;
- 增加了 多屏幕编辑 Markdown文章功能;
- 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
- 增加了 检查列表 功能。
功能快捷键
撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G
合理的创建标题,有助于目录的生成
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC
语法后生成一个完美的目录。
如何改变文本的样式
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
链接: link.
图片:
带尺寸的图片:
居中的图片:
居中并且带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block
var foo = 'bar';
生成一个适合你的列表
- 项目
- 项目
- 项目
- 项目
- 项目1
- 项目2
- 项目3
- 计划任务
- 完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' | ‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" | “Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash | – is en-dash, — is em-dash |
创建一个自定义列表
- Markdown
- Text-to- HTML conversion tool Authors
- John
- Luke
如何创建一个注脚
一个具有注脚的文本。2
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
- 关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
mermaid语法说明 ↩︎
注脚的解释 ↩︎