Emilia-Flow是基于Emilia-NodeEditor实现的Unity流图节点编辑器
基于源生成实现 运行时无反射
函数可作为端口
运行时和编辑器分离
可视化调试
热重载
//FlowNodeMenu为菜单特性
[FlowNodeMenu("Test"), Serializable]
public class TestNodeAsset : TestBaseNodeAsset<TestNode>
{
//注册值的输入端口
[FlowInputValuePort("A")]
public int a;
[FlowInputValuePort("B")]
public int b;
}
[FlowNodeGenerator]
public partial class TestNode : TestBaseNode<TestNodeAsset>
{
//注册值的输出端口
[FlowOutputValuePort("AddResult")]
public int addResult
{
get
{
//获取a端口的值如果没有则返回默认值this.asset.a
int xPort = GetInputValue(nameof(this.asset.a), this.asset.a);
int yPort = GetInputValue(nameof(this.asset.b), this.asset.b);
return xPort + yPort;
}
}
[FlowOutputValuePort("SubResult")]
public int subResult
{
get
{
int xPort = GetInputValue(nameof(this.asset.a), this.asset.a);
int yPort = GetInputValue(nameof(this.asset.b), this.asset.b);
return xPort - yPort;
}
}
//注册函数输入
[FlowInputMethodPort("Input")]
public void Input()
{
Output();
}
//注册函数输出
[FlowOutputMethodPort("Output")]
public void Output()
{
InvokeOutputPort(nameof(Output));//调用所有连接到此端口的函数
}
//注册带参的函数输入
[FlowInputMethodPort("InputArg")]
public void InputArg(object arg)
{
OutputArg(arg);
}
//注册带参的函数输出
[FlowOutputMethodPort("OutputArg")]
public void OutputArg(object arg)
{
InvokeOutputPort(nameof(OutputArg), arg);//调用所有连接到此端口的函数并传递一个参数
}
}
Unity版本:2021.3+
Odin版本:3.1.2+
在Tag界面中选择对应版本 Tag界面
找到.unitypackage文件进行下载
导入Unity之后在PackageManager界面中安装Editor Coroutines
打开Packages/manifest.json
将以下内容添加进manifest文件中
"com.emilia.kit": "https://github.com/CCEMT/Emilia-Kit.git?path=Assets/Emilia/Kit",
"com.emilia.node.editor": "https://github.com/CCEMT/Emilia-NodeEditor.git?path=Assets/Emilia/Node.Editor",
"com.emilia.flow": "https://github.com/CCEMT/Emilia-Flow.git?path=Assets/Emilia/Flow"
是基于Emilia-Flow实现的Unity类守望先锋Statescript编辑器 Statescript
以下为例子中的实现
[CreateAssetMenu(menuName = "Emilia/Statescript/EditorStatescriptAsset", fileName = "EditorStatescriptAsset")]
public class EditorStatescriptAsset : EditorFlowAsset
{
public override string outputPath => "Assets/Emilia/Statescript/Resource/Config";
public override Type[] subNodeTypes => new[] {typeof(IStatescriptNodeAsset)};
}
outputFilePath 运行时文件最终保存的路径
subNodeTypes 节点基类,用于创建节点时菜单过滤
public interface IStatescriptNodeAsset { }
public abstract class StatescriptNodeAsset<T> : UniversalFlowNodeAsset<T>, IStatescriptNodeAsset where T : FlowNode, new() { }
public abstract class StatescriptNode<T> : UniversalFlowNode<T> where T : FlowNodeAsset { }
//创建加载器
FlowLoader flowLoader = new FlowLoader();
flowLoader.runtimeFilePath = "Assets/..";
flowLoader.editorFilePath = "Assets/..";
//这里接入自己项目里面的加载API
flowLoader.onLoadAsset = OnLoadAsset;
//这里是反序列化(如果修改了序列化方案则需要修改,这里默认使用Odin序列化)
flowLoader.onLoadStateMachineAsset = (bytes) => SerializationUtility.DeserializeValue<StateMachineAsset>(bytes, DataFormat.Binary);
string fileName = "xx";//不带后缀的文件名
runner = FlowRunnerUtility.CreateRunner();
runner.Init(fileName, flowLoader, gameObject);
runner.Start();//开始运行
runner.Update();//更新
runner.Dispose();//停止运行
email:[email protected]
QQ群:956223592