在编辑器的节点属性窗口中,为了给某个节点选择和配置属性,首先需要选择一个实例(instance),然后再选择该实例的属性或方法,如下图所示:

这些实例主要来自于如下三个方面:

  • Self:表示当前行为树根节点所配置的Agent类型的实例,类似于程序语言中的this。
  • 成员实例:当前行为树根节点所配置的Agent类型的成员属性、自定义属性或局部变量,也是Agent或其子类类型。
  • 全局实例:运行时端(游戏端)注册和导出的各种Agent或其子类的全局实例。

其中,成员实例无需编写额外代码来进行注册和导出,behaviac组件会自动根据当前行为树根节点所配置的Agent类型,列举出所有的成员实例以供选择。但在使用该成员实例之前,需要确保该实例已经赋过值,不是空指针/引用。

对于全局实例,在运行时端(游戏端)的各种Agent或其子类实例的名字注册和绑定的设计意图,主要是为了支持单件(Singleton)或者类似确定的全局性的实例(同一个类可能会有若干个实例而不是仅仅有一个实例),例如:player,camera,director等。

注意:只有通过RegisterInstanceName注册过的“名字”才在导出元信息时被导出;而BindInstance和Create等与实例相关的函数在执行行为树的时候才需要,如果只是导出元信息则不需要。

C++中全局实例的注册

Agent::RegisterInstanceName可以注册一个名字,该名字表示游戏中某个Agent类的实例,如下代码所示:


behaviac::Agent::RegisterInstanceName<AgentNodeTest>();
behaviac::Agent::RegisterInstanceName<behaviac::Agent>("Name_Agent_0");

需要说明的是,游戏中需要调用Agent::Create或Agent::BindInstance创建实例并且绑定到该名字。如果指定的名字没有注册或注册的类型不同或该名字已经绑定,则调用Agent::Create的时候会有runtime的错误。

当调用Agent::RegisterInstanceName和Agent::Create而没有指定名字的时候,该Agent类型的名字将作为实例的名字被注册和绑定,如下代码所示:


behaviac::Agent* testAgentA = behaviac::Agent::Create<behaviac::Agent>("Name_Agent_0");
AgentNodeTest* testAgentB = behaviac::Agent::Create<AgentNodeTest>(NULL);

behaviac::Agent* testAgent_0 = behaviac::Agent::GetInstance<behaviac::Agent>("Name_Agent_0");
AgentNodeTest* testAgent_1 = behaviac::Agent::GetInstance<AgentNodeTest>();

behaviac::Agent::BindInstance(testAgent_0, "Name_Agent_0");
behaviac::Agent::BindInstance(testAgent_1, AgentNodeTest);

CHECK_EQUAL(testAgent_0, testAgentA);
CHECK_EQUAL(testAgent_1, testAgentB);

behaviac::Agent::UnbindInstance("Name_Agent_0");
behaviac::Agent::UnbindInstance("AgentNodeTest");

更多细节可以参考behaviac组件C++源码中附带的test工程的btloadtest.cpp文件。

C# 中全局实例的注册

类似的,在C#中实例的注册和绑定相关代码如下:

behaviac.Agent.RegisterInstanceName<AgentNodeTest>(); behaviac.Agent.RegisterInstanceName<behaviac.Agent>("Name_Agent_0"); 

behaviac.Agent.BindInstance(parTestAgent, "Name_Agent_0"); behaviac.Agent.BindInstance(nodeTestAgent, "AgentNodeTest");

behaviac.Agent testAgent_0 = behaviac.Agent.GetInstance<behaviac.Agent>("Name_Agent_0");
AgentNodeTest testAgent_1 = behaviac.Agent.GetInstance<AgentNodeTest>(); 
AgentNodeTest testAgent_3 = behaviac.Agent.GetAgent("AgentNodeTest") as AgentNodeTest;

Assert.AreEqual(testAgent_0, parTestAgent);
Assert.AreEqual(testAgent_1, nodeTestAgent);
Assert.AreEqual(testAgent_1, testAgent_3);

Assert.NotNull(testAgent_0);
Assert.NotNull(testAgent_1);

behaviac.Agent.UnbindInstance("Name_Agent_0");
behaviac.Agent.UnbindInstance("AgentNodeTest");

更多细节可以参考behaviac组件C#源码中附带的integration/unity工程的OtherUnitTest.cs文件。

发表评论

电子邮件地址不会被公开。 必填项已用*标注