Skip to content

Commit 99a797f

Browse files
authored
Merge pull request #2 from CCEMT/dev
Dev
2 parents 9056a19 + bffeab0 commit 99a797f

File tree

3 files changed

+175
-1
lines changed

3 files changed

+175
-1
lines changed

README.md

+175-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,176 @@
11
# Emilia-Flow
2-
Unity 的流图节点编辑器
2+
3+
Emilia-Flow是基于[Emilia-NodeEditor](https://github.com/CCEMT/Emilia-NodeEditor)实现的Unity流图节点编辑器
4+
5+
![](./doc/flow-image.png)
6+
7+
# 特点
8+
9+
基于源生成实现 运行时无反射
10+
函数可作为端口
11+
运行时和编辑器分离
12+
可视化调试
13+
热重载
14+
15+
# 示例
16+
~~~
17+
//FlowNodeMenu为菜单特性
18+
[FlowNodeMenu("Test"), Serializable]
19+
public class TestNodeAsset : TestBaseNodeAsset<TestNode>
20+
{
21+
//注册值的输入端口
22+
[FlowInputValuePort("A")]
23+
public int a;
24+
25+
[FlowInputValuePort("B")]
26+
public int b;
27+
}
28+
29+
[FlowNodeGenerator]
30+
public partial class TestNode : TestBaseNode<TestNodeAsset>
31+
{
32+
//注册值的输出端口
33+
[FlowOutputValuePort("AddResult")]
34+
public int addResult
35+
{
36+
get
37+
{
38+
//获取a端口的值如果没有则返回默认值this.asset.a
39+
int xPort = GetInputValue(nameof(this.asset.a), this.asset.a);
40+
int yPort = GetInputValue(nameof(this.asset.b), this.asset.b);
41+
42+
return xPort + yPort;
43+
}
44+
}
45+
46+
[FlowOutputValuePort("SubResult")]
47+
public int subResult
48+
{
49+
get
50+
{
51+
int xPort = GetInputValue(nameof(this.asset.a), this.asset.a);
52+
int yPort = GetInputValue(nameof(this.asset.b), this.asset.b);
53+
54+
return xPort - yPort;
55+
}
56+
}
57+
58+
//注册函数输入
59+
[FlowInputMethodPort("Input")]
60+
public void Input()
61+
{
62+
Output();
63+
}
64+
65+
//注册函数输出
66+
[FlowOutputMethodPort("Output")]
67+
public void Output()
68+
{
69+
InvokeOutputPort(nameof(Output));//调用所有连接到此端口的函数
70+
}
71+
72+
//注册带参的函数输入
73+
[FlowInputMethodPort("InputArg")]
74+
public void InputArg(object arg)
75+
{
76+
OutputArg(arg);
77+
}
78+
79+
//注册带参的函数输出
80+
[FlowOutputMethodPort("OutputArg")]
81+
public void OutputArg(object arg)
82+
{
83+
InvokeOutputPort(nameof(OutputArg), arg);//调用所有连接到此端口的函数并传递一个参数
84+
}
85+
}
86+
~~~
87+
88+
# 安装
89+
Unity版本:2021.3+
90+
Odin版本:3.1.2+
91+
92+
### Odin为付费插件请自行导入
93+
94+
### 使用unitypackage安装
95+
96+
在Tag界面中选择对应版本 [Tag界面](https://github.com/CCEMT/Emilia-Flow/tags)
97+
找到.unitypackage文件进行下载
98+
导入Unity之后在PackageManager界面中安装Editor Coroutines
99+
100+
### 使用Unity Package Manager安装
101+
102+
打开Packages/manifest.json
103+
104+
将以下内容添加进manifest文件中
105+
106+
~~~
107+
"com.emilia.kit": "https://github.com/CCEMT/Emilia-Kit.git?path=Assets/Emilia/Kit",
108+
"com.emilia.node.editor": "https://github.com/CCEMT/Emilia-NodeEditor.git?path=Assets/Emilia/Node.Editor",
109+
"com.emilia.flow": "https://github.com/CCEMT/Emilia-Flow.git?path=Assets/Emilia/Flow"
110+
~~~
111+
112+
# 例子
113+
114+
是基于Emilia-Flow实现的Unity类守望先锋Statescript编辑器 [Statescript](https://github.com/CCEMT/Emilia-Statescript)
115+
![](./doc/statescript.gif)
116+
117+
# 开始
118+
119+
以下为例子中的实现
120+
121+
### 创建编辑器文件
122+
123+
~~~
124+
[CreateAssetMenu(menuName = "Emilia/Statescript/EditorStatescriptAsset", fileName = "EditorStatescriptAsset")]
125+
public class EditorStatescriptAsset : EditorFlowAsset
126+
{
127+
public override string outputPath => "Assets/Emilia/Statescript/Resource/Config";
128+
129+
public override Type[] subNodeTypes => new[] {typeof(IStatescriptNodeAsset)};
130+
}
131+
~~~
132+
133+
outputFilePath 运行时文件最终保存的路径
134+
subNodeTypes 节点基类,用于创建节点时菜单过滤
135+
136+
### 创建节点基类
137+
138+
~~~
139+
public interface IStatescriptNodeAsset { }
140+
141+
public abstract class StatescriptNodeAsset<T> : UniversalFlowNodeAsset<T>, IStatescriptNodeAsset where T : FlowNode, new() { }
142+
143+
public abstract class StatescriptNode<T> : UniversalFlowNode<T> where T : FlowNodeAsset { }
144+
~~~
145+
146+
### 运行
147+
148+
~~~
149+
//创建加载器
150+
FlowLoader flowLoader = new FlowLoader();
151+
flowLoader.runtimeFilePath = "Assets/..";
152+
flowLoader.editorFilePath = "Assets/..";
153+
154+
//这里接入自己项目里面的加载API
155+
flowLoader.onLoadAsset = OnLoadAsset;
156+
157+
//这里是反序列化(如果修改了序列化方案则需要修改,这里默认使用Odin序列化)
158+
flowLoader.onLoadStateMachineAsset = (bytes) => SerializationUtility.DeserializeValue<StateMachineAsset>(bytes, DataFormat.Binary);
159+
160+
string fileName = "xx";//不带后缀的文件名
161+
162+
runner = FlowRunnerUtility.CreateRunner();
163+
runner.Init(fileName, flowLoader, gameObject);
164+
~~~
165+
166+
### 生命周期
167+
~~~
168+
runner.Start();//开始运行
169+
runner.Update();//更新
170+
runner.Dispose();//停止运行
171+
~~~
172+
173+
# 联系
174+
175+
176+
QQ群:956223592

doc/flow-image.png

1.5 MB
Loading

doc/statescript.gif

323 KB
Loading

0 commit comments

Comments
 (0)