diff --git a/core/BehaviorTree.go b/core/BehaviorTree.go index c0ca7d3..3b193f6 100644 --- a/core/BehaviorTree.go +++ b/core/BehaviorTree.go @@ -147,7 +147,7 @@ func (this *BehaviorTree) SetDebug(debug interface{}) { this.debug = debug } -func (this *BehaviorTree) GetRoot() IBaseNode { +func (this *BehaviorTree) GetRoot() IBaseNode { return this.root } @@ -295,10 +295,21 @@ func (this *BehaviorTree) Tick(target interface{}, blackboard *Blackboard) b3.St var currOpenNodes []IBaseNode currOpenNodes = append(currOpenNodes, tick._openNodes...) + var same bool + l := len(lastOpenNodes) + if l == len(currOpenNodes) { + if l == 0 || lastOpenNodes[l-1] == currOpenNodes[l-1] { + same = true + } + } + if same { + return state + } + // does not close if it is still open in this tick var start = 0 for i := 0; i < b3.MinInt(len(lastOpenNodes), len(currOpenNodes)); i++ { - start = i + 1 + start = i if lastOpenNodes[i] != currOpenNodes[i] { break } diff --git a/examples/testwork/README.md b/examples/testwork/README.md new file mode 100644 index 0000000..445a2bd --- /dev/null +++ b/examples/testwork/README.md @@ -0,0 +1,119 @@ +# 修正第一个记忆节点无法关闭示例 +关联问题https://github.com/magicsea/behavior3go/issues/17 。 +追踪原版的老bug,记忆节点链关闭的第一个会执行不了onclose,导致memseq节点会错误的记录runningChild不清理。 +错误表现为,因为runningChild没重置,直接从Wait0-2跳入Wait1-2。 +### 修复方法 +start=i+1改start,增加same判断是否调用链修改了(不判断会导致一直在running节点)。 + +### 修复前后日志 +重现需开打Wait节点的print日志。 +- 修复前日志 +``` +logtest: job 0-0 +wait: Wait0-1 ms => 0 +wait: Wait0-1 ms => 108 +wait: Wait0-1 ms => 216 +wait: Wait0-1 ms => 325 +wait: Wait0-1 ms => 434 +wait: Wait0-1 ms => 542 +wait: Wait0-1 ms => 652 +wait: Wait0-1 ms => 759 +wait: Wait0-1 ms => 869 +wait: Wait0-1 ms => 978 +wait: Wait0-1 ms => 1087 +logtest: job 0-1 +logtest: job 0-2 +wait: Wait0-2 ms => 0 +wait: Wait0-2 ms => 109 +logtest: job 1-0 +wait: Wait1-1 ms => 0 +wait: Wait1-1 ms => 111 +wait: Wait1-1 ms => 221 +wait: Wait1-1 ms => 331 +wait: Wait1-1 ms => 442 +wait: Wait1-1 ms => 551 +wait: Wait1-1 ms => 662 +wait: Wait1-1 ms => 771 +wait: Wait1-1 ms => 880 +wait: Wait1-1 ms => 991 +wait: Wait1-1 ms => 1098 +logtest: job 1-1 +logtest: job 1-2 +wait: Wait1-2 ms => 0 +logtest: job 0-0 +wait: Wait0-1 ms => 0 +wait: Wait0-1 ms => 109 +wait: Wait0-1 ms => 219 +wait: Wait0-1 ms => 329 +wait: Wait0-1 ms => 438 +wait: Wait0-1 ms => 545 +wait: Wait0-1 ms => 652 +wait: Wait0-1 ms => 760 +wait: Wait0-1 ms => 869 +wait: Wait0-1 ms => 976 +wait: Wait0-1 ms => 1084 +logtest: job 0-1 +logtest: job 0-2 +wait: Wait0-2 ms => 0 +wait: Wait0-2 ms => 108 +wait: Wait1-2 ms => 0<--------------------错误行,应该进入:job 1-0 +wait: Wait1-2 ms => 107 +logtest: job 1-0 +wait: Wait1-1 ms => 0 +wait: Wait1-1 ms => 108 +wait: Wait1-1 ms => 216 + + +``` + +- 修复后日志 +``` +logtest: job 0-0 +wait: Wait0-1 ms => 0 +wait: Wait0-1 ms => 110 +wait: Wait0-1 ms => 217 +wait: Wait0-1 ms => 327 +wait: Wait0-1 ms => 437 +wait: Wait0-1 ms => 545 +wait: Wait0-1 ms => 653 +wait: Wait0-1 ms => 763 +wait: Wait0-1 ms => 872 +wait: Wait0-1 ms => 980 +wait: Wait0-1 ms => 1088 +logtest: job 0-1 +logtest: job 0-2 +wait: Wait0-2 ms => 0 +wait: Wait0-2 ms => 109 +logtest: job 1-0 +wait: Wait1-1 ms => 0 +wait: Wait1-1 ms => 109 +wait: Wait1-1 ms => 219 +wait: Wait1-1 ms => 328 +wait: Wait1-1 ms => 436 +wait: Wait1-1 ms => 545 +wait: Wait1-1 ms => 652 +wait: Wait1-1 ms => 759 +wait: Wait1-1 ms => 868 +wait: Wait1-1 ms => 976 +wait: Wait1-1 ms => 1085 +logtest: job 1-1 +logtest: job 1-2 +wait: Wait1-2 ms => 0 +logtest: job 0-0 +wait: Wait0-1 ms => 753 +wait: Wait0-1 ms => 861 +wait: Wait0-1 ms => 967 +wait: Wait0-1 ms => 1075 +logtest: job 0-1 +logtest: job 0-2 +wait: Wait0-2 ms => 0 +wait: Wait0-2 ms => 109 +<---------------------------------------------------------------------正确切换到1-0 +logtest: job 1-0 +wait: Wait1-1 ms => 0 +wait: Wait1-1 ms => 108 +wait: Wait1-1 ms => 217 +wait: Wait1-1 ms => 325 +wait: Wait1-1 ms => 433 + +``` \ No newline at end of file diff --git a/examples/testwork/main.go b/examples/testwork/main.go new file mode 100644 index 0000000..c4a0c5d --- /dev/null +++ b/examples/testwork/main.go @@ -0,0 +1,63 @@ +/* +从原生工程文件加载 +*/ +package main + +import ( + "fmt" + b3 "github.com/magicsea/behavior3go" + . "github.com/magicsea/behavior3go/config" + . "github.com/magicsea/behavior3go/core" + . "github.com/magicsea/behavior3go/examples/share" + . "github.com/magicsea/behavior3go/loader" + "sync" + "time" +) + +// 所有的树管理 +var mapTreesByID = sync.Map{} +var maps = b3.NewRegisterStructMaps() + +func init() { + //自定义节点注册 + maps.Register("Log", new(LogTest)) + maps.Register("SetValue", new(SetValue)) + maps.Register("IsValue", new(IsValue)) + + //获取子树的方法 + SetSubTreeLoadFunc(func(id string) *BehaviorTree { + //println("==>load subtree:",id) + t, ok := mapTreesByID.Load(id) + if ok { + return t.(*BehaviorTree) + } + return nil + }) +} + +func main() { + projectConfig, ok := LoadRawProjectCfg("testwork.b3") + if !ok { + fmt.Println("LoadRawProjectCfg err") + return + } + + var firstTree *BehaviorTree + //载入 + for _, v := range projectConfig.Data.Trees { + tree := CreateBevTreeFromConfig(&v, maps) + tree.Print() + mapTreesByID.Store(v.ID, tree) + if firstTree == nil { + firstTree = tree + } + } + time.Sleep(time.Second) + //输入板 + board := NewBlackboard() + //循环每一帧 + for i := 0; i < 40; i++ { + firstTree.Tick(i, board) + time.Sleep(time.Millisecond * 100) + } +} diff --git a/examples/testwork/testwork.b3 b/examples/testwork/testwork.b3 new file mode 100644 index 0000000..fc46d10 --- /dev/null +++ b/examples/testwork/testwork.b3 @@ -0,0 +1,329 @@ +{ + "name": "testwork", + "description": "", + "data": { + "version": "0.3.0", + "scope": "project", + "selectedTree": "9e6f6cb9-d3d2-41af-9d03-3ab247d42be7", + "trees": [ + { + "version": "0.3.0", + "scope": "tree", + "id": "9e6f6cb9-d3d2-41af-9d03-3ab247d42be7", + "title": "A behavior tree", + "description": "", + "root": "7656895d-d268-4252-81bc-e0cd013add4b", + "properties": {}, + "nodes": { + "197a07a2-1444-4088-8dd9-509d5208c6e8": { + "id": "197a07a2-1444-4088-8dd9-509d5208c6e8", + "name": "MemSequence", + "category": "composite", + "title": "MemSequence1", + "description": "", + "properties": {}, + "display": { + "x": 240, + "y": 60 + }, + "children": [ + "9fbbec3b-3f57-4fa9-8800-021859a5baf1", + "866d2e78-120e-446e-8e87-3dfc93eed895", + "f54a5051-b8ba-4296-958b-99f0da7f5c0f", + "5dad8fe4-3d34-4a75-a82e-ac4aa3a33c3f", + "93c25ee3-7dda-41e6-92a0-a9c2302c6d91", + "819cd7d8-eed8-4294-bacd-e6cdfe04fcbc", + "17c2e7c4-d571-4772-8e8b-79045a9125d3" + ] + }, + "42f24b36-88a5-4c20-b8c7-0579145cb71c": { + "id": "42f24b36-88a5-4c20-b8c7-0579145cb71c", + "name": "MemSequence", + "category": "composite", + "title": "MemSequence2", + "description": "", + "properties": {}, + "display": { + "x": 228, + "y": 396 + }, + "children": [ + "4cfaf27e-dfab-4a4d-85eb-e6fe6d66fc50", + "25305166-3936-4270-8d0f-3dd99e2986ed", + "a64f52c1-385d-4381-9c51-3b3c9509648f", + "970dce20-6cff-4515-8a3c-a969c13ca984", + "fd916444-28dc-4448-9039-1b6f009ee8aa", + "db67a446-51ef-4d61-8e3a-b214a34b691f", + "0acaa9c4-384b-478e-be04-556351cca31c" + ] + }, + "7656895d-d268-4252-81bc-e0cd013add4b": { + "id": "7656895d-d268-4252-81bc-e0cd013add4b", + "name": "Priority", + "category": "composite", + "title": "Priority", + "description": "", + "properties": {}, + "display": { + "x": 96, + "y": 216 + }, + "children": [ + "197a07a2-1444-4088-8dd9-509d5208c6e8", + "42f24b36-88a5-4c20-b8c7-0579145cb71c" + ] + }, + "f54a5051-b8ba-4296-958b-99f0da7f5c0f": { + "id": "f54a5051-b8ba-4296-958b-99f0da7f5c0f", + "name": "Wait", + "category": "action", + "title": "Wait0-1 ms", + "description": "", + "properties": { + "milliseconds": 1000 + }, + "display": { + "x": 468, + "y": 60 + } + }, + "a64f52c1-385d-4381-9c51-3b3c9509648f": { + "id": "a64f52c1-385d-4381-9c51-3b3c9509648f", + "name": "Wait", + "category": "action", + "title": "Wait1-1 ms", + "description": "", + "properties": { + "milliseconds": 1000 + }, + "display": { + "x": 456, + "y": 396 + } + }, + "93c25ee3-7dda-41e6-92a0-a9c2302c6d91": { + "id": "93c25ee3-7dda-41e6-92a0-a9c2302c6d91", + "name": "SetValue", + "category": "action", + "title": "SetValue(,)1", + "description": "", + "properties": { + "key": "job", + "value": 1 + }, + "display": { + "x": 468, + "y": 144 + } + }, + "fd916444-28dc-4448-9039-1b6f009ee8aa": { + "id": "fd916444-28dc-4448-9039-1b6f009ee8aa", + "name": "SetValue", + "category": "action", + "title": "SetValue(,)2", + "description": "", + "properties": { + "key": "job", + "value": 0 + }, + "display": { + "x": 456, + "y": 492 + } + }, + "9fbbec3b-3f57-4fa9-8800-021859a5baf1": { + "id": "9fbbec3b-3f57-4fa9-8800-021859a5baf1", + "name": "IsValue", + "category": "condition", + "title": "IsValue(,)1", + "description": "", + "properties": { + "key": "job", + "value": 0 + }, + "display": { + "x": 468, + "y": -36 + } + }, + "4cfaf27e-dfab-4a4d-85eb-e6fe6d66fc50": { + "id": "4cfaf27e-dfab-4a4d-85eb-e6fe6d66fc50", + "name": "IsValue", + "category": "condition", + "title": "IsValue(,)2", + "description": "", + "properties": { + "key": "job", + "value": 1 + }, + "display": { + "x": 456, + "y": 300 + } + }, + "866d2e78-120e-446e-8e87-3dfc93eed895": { + "id": "866d2e78-120e-446e-8e87-3dfc93eed895", + "name": "Log", + "category": "action", + "title": "Log()", + "description": "", + "properties": { + "info": "job 0-0" + }, + "display": { + "x": 468, + "y": 12 + } + }, + "5dad8fe4-3d34-4a75-a82e-ac4aa3a33c3f": { + "id": "5dad8fe4-3d34-4a75-a82e-ac4aa3a33c3f", + "name": "Log", + "category": "action", + "title": "Log()", + "description": "", + "properties": { + "info": "job 0-1" + }, + "display": { + "x": 468, + "y": 96 + } + }, + "819cd7d8-eed8-4294-bacd-e6cdfe04fcbc": { + "id": "819cd7d8-eed8-4294-bacd-e6cdfe04fcbc", + "name": "Log", + "category": "action", + "title": "Log()", + "description": "", + "properties": { + "info": "job 0-2" + }, + "display": { + "x": 468, + "y": 192 + } + }, + "25305166-3936-4270-8d0f-3dd99e2986ed": { + "id": "25305166-3936-4270-8d0f-3dd99e2986ed", + "name": "Log", + "category": "action", + "title": "Log()", + "description": "", + "properties": { + "info": "job 1-0" + }, + "display": { + "x": 456, + "y": 348 + } + }, + "970dce20-6cff-4515-8a3c-a969c13ca984": { + "id": "970dce20-6cff-4515-8a3c-a969c13ca984", + "name": "Log", + "category": "action", + "title": "Log()", + "description": "", + "properties": { + "info": "job 1-1" + }, + "display": { + "x": 456, + "y": 444 + } + }, + "db67a446-51ef-4d61-8e3a-b214a34b691f": { + "id": "db67a446-51ef-4d61-8e3a-b214a34b691f", + "name": "Log", + "category": "action", + "title": "Log()", + "description": "", + "properties": { + "info": "job 1-2" + }, + "display": { + "x": 456, + "y": 540 + } + }, + "17c2e7c4-d571-4772-8e8b-79045a9125d3": { + "id": "17c2e7c4-d571-4772-8e8b-79045a9125d3", + "name": "Wait", + "category": "action", + "title": "Wait0-2 ms", + "description": "", + "properties": { + "milliseconds": 100 + }, + "display": { + "x": 468, + "y": 240 + } + }, + "0acaa9c4-384b-478e-be04-556351cca31c": { + "id": "0acaa9c4-384b-478e-be04-556351cca31c", + "name": "Wait", + "category": "action", + "title": "Wait1-2 ms", + "description": "", + "properties": { + "milliseconds": 100 + }, + "display": { + "x": 456, + "y": 588 + } + } + }, + "display": { + "camera_x": 540, + "camera_y": 306.5, + "camera_z": 1, + "x": -12, + "y": 216 + } + } + ], + "custom_nodes": [ + { + "version": "0.3.0", + "scope": "node", + "name": "SetValue", + "category": "action", + "title": "SetValue(,)", + "description": null, + "properties": { + "key": "string", + "value": 1 + }, + "parent": null + }, + { + "version": "0.3.0", + "scope": "node", + "name": "IsValue", + "category": "condition", + "title": "IsValue(,)", + "description": null, + "properties": { + "key": "string", + "value": 1 + }, + "parent": null + }, + { + "version": "0.3.0", + "scope": "node", + "name": "Log", + "category": "action", + "title": "Log()", + "description": null, + "properties": { + "info": "string" + }, + "parent": null + } + ], + "custom_folders": [] + }, + "path": "E:\\mgame\\server\\mgameserver.git\\src\\lib\\behavior3go\\examples\\testwork\\testwork.b3" +} \ No newline at end of file