private void CreateOutputPorts() { output = node switch { CompositeNode _ => InstantiatePort(Orientation.Horizontal, Direction.Output, Port.Capacity.Multi, typeof(bool)), DecoratorNode _ => InstantiatePort(Orientation.Horizontal, Direction.Output, Port.Capacity.Single, typeof(bool)), _ => output }; if (output == null) { return; } output.portName = ""; outputContainer.Add(output); }
// sets this node and its children to the idle state void SetNodeTreeIdle(Node n) { var nodeName = n.ToString(); // decorator node if (nodeName == "Inverter" || nodeName == "Repeater" || nodeName == "RepeatTillFail" || nodeName == "Limiter" || nodeName == "Succeeder") { DecoratorNode d = (DecoratorNode)n; SetNodeTreeIdle(d.ChildNode); } // composite node else if (nodeName == "Selector" || nodeName == "Sequence") { CompositeNode c = (CompositeNode)n; foreach (Node childNode in c.ChildNodeList) { SetNodeTreeIdle(childNode); } } n.NodeState = ENodeStates.IDLE; }
private void BuildBehaviourTree() { var chaseAction = new ActionNode(Chase); var canChaseDecorator = new DecoratorNode(chaseAction, () => remainingTimeToChase > 0.0f); var approachAction = new ActionNode(ApproachToTarget); var canApproachDecorator = new DecoratorNode(approachAction, () => isTargetInDetectionArea); var selector1 = new SelectorNode(canApproachDecorator, canChaseDecorator); var fireAction = new ActionNode(Fire); var canFireDecorator = new DecoratorNode(fireAction, () => { return(gun.CanFire()); }); var faceToTargetAction = new ActionNode(FaceToTarget); var selector2 = new SelectorNode(canFireDecorator, faceToTargetAction); var canSeeTargetDecorator = new DecoratorNode(selector2, CanSeeTarget); var selector3 = new SelectorNode(canSeeTargetDecorator, approachAction); var isTargetInRangeDecorator = new DecoratorNode(selector3, () => isTargetInRange); var selector4 = new SelectorNode(isTargetInRangeDecorator, selector1); var isTargetNullDecorator = new DecoratorNode(selector4, () => { return(target != null); }); var waitAction = new ActionNode(Wait); var selector5 = new SelectorNode(isTargetNullDecorator, waitAction); var blownChecker = new DecoratorNode(waitAction, () => { return(core.isBlown); }); var selector6 = new SelectorNode(blownChecker, selector5); behaviourTree = new BehaviourTree(selector6); }
public INode CreateRandomSelectorTest() { NodeFactory factory = FactoryManager.Instance.GetFactory <NodeFactory>(FactoryType.Node); ConditionFactory conditionFactory = FactoryManager.Instance.GetFactory <ConditionFactory>(FactoryType.Condition); DecoratorFactory decoratorFactory = FactoryManager.Instance.GetFactory <DecoratorFactory>(FactoryType.Decorator); var rootNode = factory.Create <RootNode>(NodeType.Root); RandomSelectorNode randomSelectorNode = factory.Create <RandomSelectorNode>(NodeType.RandomSelector); DecoratorNode decoratorNode = factory.Create <DecoratorNode>(NodeType.Decorator); FalseDecorator not = decoratorFactory.Create <FalseDecorator>(DecoratorType.False); decoratorNode.SetDecoratable(not); var actionNode1 = CreateSampleActionNode1(); var actionNode2 = CreateSampleActionNode1(); var actionNode3 = CreateSampleActionNode2(); randomSelectorNode.AddNode(actionNode1); randomSelectorNode.AddNode(actionNode2); decoratorNode.AddNode(actionNode3); randomSelectorNode.AddNode(decoratorNode); rootNode.AddNode(randomSelectorNode); return(rootNode); }
void DrawDecorator(DecoratorNode decorator) { //if node is a decorator, draw child and widgets. if (decorator != null) { if (ReactTypeRegister.IsCoreDecorator(decorator.GetType())) { DrawCoreDecorator(decorator); } if (decorator.Child != null) { cursor.x += decorator.rect.width + SPACING.x; cursor.y -= decorator.rect.height + SPACING.x / 2; Draw(decorator.Child, decorator); // var left = decorator.rect.xMax; // var mid = decorator.rect.center.y; // var right = decorator.Child.rect.xMin; // ReactEditorUtility.DrawLine(new Vector2(left, mid), new Vector3(right, mid), Color.white); cursor.x -= decorator.rect.width + SPACING.x; } dropZones.Add(new DropZone(decorator, decorator.rect)); } }
/// <summary> /// clone /// </summary> /// <returns></returns> public IBehaviourNode Clone() { var behaviourNode = new DecoratorNode(); base.CopyToCompositeNode(behaviourNode); return behaviourNode; }
private void InitializeTreeView() { StockNode treeNode1; foreach (string entry in this.theme.Keys) { if (entry.ToUpper().EndsWith("GRAPH")) { GraphNode treeNode = new GraphNode(entry, this.graphMenuStrip, Color.White, Color.LightGray, true, Color.LightGray, GraphChartMode.BarChart); if (entry.ToUpper().Contains("VOLUME")) { treeNode.ImageKey = "VH"; treeNode.SelectedImageKey = "VH"; } this.treeView1.Nodes.Add(treeNode); foreach (string line in this.theme[entry]) { try { string[] fields = line.Split('|'); switch (fields[0].ToUpper()) { case "GRAPH": string[] colorItem = fields[1].Split(':'); treeNode.GraphBackgroundColor = Color.FromArgb(int.Parse(colorItem[0]), int.Parse(colorItem[1]), int.Parse(colorItem[2]), int.Parse(colorItem[3])); colorItem = fields[2].Split(':'); treeNode.GraphTextBackgroundColor = Color.FromArgb(int.Parse(colorItem[0]), int.Parse(colorItem[1]), int.Parse(colorItem[2]), int.Parse(colorItem[3])); treeNode.GraphShowGrid = bool.Parse(fields[3]); colorItem = fields[4].Split(':'); treeNode.GraphGridColor = Color.FromArgb(int.Parse(colorItem[0]), int.Parse(colorItem[1]), int.Parse(colorItem[2]), int.Parse(colorItem[3])); treeNode.GraphMode = (GraphChartMode)Enum.Parse(typeof(GraphChartMode), fields[5]); if (treeNode.Text.ToUpper() == "CLOSEGRAPH") { if (fields.Length >= 7) { treeNode.SecondaryPen = GraphCurveType.PenFromString(fields[6]); } else { treeNode.SecondaryPen = new Pen(Color.DarkGoldenrod, 1); } } break; case "DATA": if (treeNode.Text.ToUpper() == "CLOSEGRAPH") { if (fields[1] == "CLOSE") { treeNode1 = new CurveNode(fields[1], null, GraphCurveType.PenFromString(fields[2]), bool.Parse(fields[3])); treeNode.Nodes.Add(treeNode1); } else { if (bool.Parse(fields[3])) // Normaly Other than close is not visible... { treeNode1 = new CurveNode(fields[1], null, GraphCurveType.PenFromString(fields[2]), bool.Parse(fields[3])); treeNode.Nodes.Add(treeNode1); } } } else { if (fields[1] != "VOLUME" && bool.Parse(fields[3])) // Normaly Other than close is not visible... { treeNode1 = new CurveNode(fields[1], null, GraphCurveType.PenFromString(fields[2]), bool.Parse(fields[3])); treeNode.Nodes.Add(treeNode1); } } break; case "INDICATOR": { IStockIndicator stockIndicator = (IStockIndicator)StockViewableItemsManager.GetViewableItem(line); treeNode1 = new IndicatorNode(stockIndicator.Name, this.indicatorMenuStrip, stockIndicator); for (int i = 0; i < stockIndicator.SeriesCount; i++) { CurveNode curveNode = new CurveNode(stockIndicator.SerieNames[i], null, stockIndicator.SeriePens[i], true, stockIndicator.SerieVisibility[i]); treeNode1.Nodes.Add(curveNode); curveNode.ImageKey = treeNode1.ImageKey; curveNode.SelectedImageKey = treeNode1.SelectedImageKey; } treeNode.Nodes.Add(treeNode1); } break; case "PAINTBAR": { IStockPaintBar stockPaintBar = (IStockPaintBar)StockViewableItemsManager.GetViewableItem(line); treeNode1 = new PaintBarsNode(stockPaintBar.Name, this.indicatorMenuStrip, stockPaintBar); for (int i = 0; i < stockPaintBar.SeriesCount; i++) { CurveNode curveNode = new CurveNode(stockPaintBar.SerieNames[i], null, stockPaintBar.SeriePens[i], true, stockPaintBar.SerieVisibility[i]); treeNode1.Nodes.Add(curveNode); curveNode.ImageKey = treeNode1.ImageKey; curveNode.SelectedImageKey = treeNode1.SelectedImageKey; } treeNode.Nodes.Add(treeNode1); } break; case "TRAILSTOP": { IStockTrailStop stockTrailStop = (IStockTrailStop)StockViewableItemsManager.GetViewableItem(line); treeNode1 = new TrailStopsNode(stockTrailStop.Name, this.indicatorMenuStrip, stockTrailStop); for (int i = 0; i < stockTrailStop.SeriesCount; i++) { CurveNode curveNode = new CurveNode(stockTrailStop.SerieNames[i], null, stockTrailStop.SeriePens[i], false, true); treeNode1.Nodes.Add(curveNode); curveNode.ImageKey = treeNode1.ImageKey; curveNode.SelectedImageKey = treeNode1.SelectedImageKey; } treeNode.Nodes.Add(treeNode1); } break; case "DECORATOR": { IStockDecorator stockDecorator = (IStockDecorator)StockViewableItemsManager.GetViewableItem(line); treeNode1 = new DecoratorNode(stockDecorator.Name, this.indicatorMenuStrip, stockDecorator); for (int i = 0; i < stockDecorator.SeriesCount; i++) { treeNode1.Nodes.Add(new CurveNode(stockDecorator.SerieNames[i], null, stockDecorator.SeriePens[i], true, stockDecorator.SerieVisibility[i])); } for (int i = 0; i < stockDecorator.EventCount; i++) { treeNode1.Nodes.Add(new EventNode(stockDecorator.EventNames[i], null, stockDecorator.EventPens[i], true, stockDecorator.EventVisibility[i])); } foreach (TreeNode childNode in treeNode.Nodes) { if (childNode.Text == stockDecorator.DecoratedItem) { childNode.Nodes.Add(treeNode1); break; } } } break; case "TRAIL": { IStockTrail stockTrail = (IStockTrail)StockViewableItemsManager.GetViewableItem(line); treeNode1 = new TrailNode(stockTrail.Name, this.indicatorMenuStrip, stockTrail); for (int i = 0; i < stockTrail.SeriesCount; i++) { treeNode1.Nodes.Add(new CurveNode(stockTrail.SerieNames[i], null, stockTrail.SeriePens[i], true, true)); } foreach (TreeNode childNode in treeNode.Nodes) { if (childNode.Text == stockTrail.TrailedItem) { childNode.Nodes.Add(treeNode1); break; } } } break; case "LINE": treeNode.Nodes.Add(new LineNode("LINE_" + fields[1], this.indicatorMenuStrip, GraphCurveType.PenFromString(fields[2]), float.Parse(fields[1]))); break; default: continue; } } catch (System.Exception e) { StockLog.Write(e); } } } } foreach (TreeNode node in this.treeView1.Nodes) { node.Expand(); } this.treeView1.SelectedNode = treeView1.Nodes[0]; }
void addDecoratorToolStripMenuItem_Click(object sender, System.EventArgs e) { AddDecoratorDlg addDlg; StockNode treeNode = (StockNode)this.treeView1.SelectedNode; switch (treeNode.Text) { case "CloseGraph": return; case "VolumeGraph": return; default: addDlg = new AddDecoratorDlg(); break; } if (addDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { StockNode stockNode = (StockNode)this.treeView1.SelectedNode; if (stockNode.Type == NodeType.Decorator) return; IStockDecorator stockDecorator = StockDecoratorManager.CreateDecorator(addDlg.DecoratorName, stockNode.Name); if (stockDecorator == null) { return; } if (stockDecorator.DisplayTarget != IndicatorDisplayTarget.PriceIndicator) { // Only one decorator per graph (except data serie) (multiple ema, BB, ....) int index = 0; bool found = false; foreach (StockNode node in stockNode.Nodes) { if (node.Type == NodeType.Decorator) { found = true; break; } index++; } if (found) { stockNode.Nodes.RemoveAt(index); } } StockNode decoratorNode = new DecoratorNode(stockDecorator.Name, this.indicatorMenuStrip, stockDecorator); stockNode.Nodes.Add(decoratorNode); int i = 0; foreach (string curveName in stockDecorator.SerieNames) { decoratorNode.Nodes.Add(new CurveNode(curveName, null, stockDecorator.SeriePens[i], true)); i++; } i = 0; foreach (string eventName in stockDecorator.EventNames) { decoratorNode.Nodes.Add(new EventNode(eventName, null, stockDecorator.EventPens[i], true)); i++; } this.treeView1.SelectedNode = decoratorNode; decoratorNode.Expand(); } }
public ApproachMachine() { DataStorage[PlayerPosition] = new Point(10, 10); DataStorage[GoalPosition] = new Point(0, 0); DataStorage[Switch] = false; var switchOffState = new State(); this[SwitchOff] = switchOffState; switchOffState.OnExecuteEvent = (machine, state) => { Debug.WriteLine($"SwitchOff"); if ((bool)machine.DataStorage[Switch]) { machine.NextStateName = SwitchOn; } }; var switchOnState = new State(); this[SwitchOn] = switchOnState; var behaviourMachine = new BehaviourMachine(); behaviourMachine.DataStorage.ReferTo(DataStorage, PlayerPosition); behaviourMachine.DataStorage.ReferTo(DataStorage, GoalPosition); switchOnState.OnExecuteEvent = (machine, state) => { Debug.WriteLine($"SwitchOn"); behaviourMachine.Execute(); }; var moveOrTeleportSelector = new SelectorNode(); behaviourMachine.RegisterRootNode(moveOrTeleportSelector); var moveDecorator = new DecoratorNode(); moveOrTeleportSelector.ChildNodes.Add(moveDecorator); moveDecorator.ConditionCallback = (machine, node) => { Debug.WriteLine($"move condition check"); var playerPosition = (Point)machine.DataStorage[PlayerPosition]; var goalPosition = (Point)machine.DataStorage[GoalPosition]; Debug.WriteLine($"P:{playerPosition} G:{goalPosition}"); return(!playerPosition.Equals(goalPosition)); }; var moveAction = new ActionNode(); moveDecorator.ChildNode = moveAction; moveAction.ActionCallback = (machine, node) => { Debug.WriteLine($"Move"); var playerPosition = (Point)machine.DataStorage[PlayerPosition]; var goalPosition = (Point)machine.DataStorage[GoalPosition]; var diffX = Math.Abs(playerPosition.X - goalPosition.X); var diffY = Math.Abs(playerPosition.Y - goalPosition.Y); if (diffX >= diffY) { playerPosition.X += playerPosition.X > goalPosition.X ? -1 : 1; } else { playerPosition.Y += playerPosition.Y > goalPosition.Y ? -1 : 1; } machine.DataStorage[PlayerPosition] = playerPosition; return(true); }; var teleportAction = new ActionNode(); teleportAction.DataStorage[TeleportCounter] = 10; moveOrTeleportSelector.ChildNodes.Add(teleportAction); teleportAction.ActionCallback = (machine, node) => { Debug.WriteLine($"teleport"); var teleportCounter = (int)node.DataStorage[TeleportCounter]; teleportCounter--; node.DataStorage[TeleportCounter] = teleportCounter; Debug.WriteLine($"teleport counter: {teleportCounter}"); if (teleportCounter > 0) { return(false); } var playerPosition = (Point)machine.DataStorage[PlayerPosition]; playerPosition.X = new Random().Next(-10, 10); playerPosition.Y = new Random().Next(-10, 10); machine.DataStorage[PlayerPosition] = playerPosition; node.DataStorage[TeleportCounter] = 10; Debug.WriteLine($"teleport to {playerPosition}"); return(true); }; }
void Start() { _behaviorTreeController = new BehaviorTreeController(); // rootとなるSequencer SequencerNode rootNode = new SequencerNode(); rootNode.name = "rootノード"; // 出発 ActionNode departure = new ActionNode(); departure.name = "出発する"; departure.SetRunningFunc(() => { Debug.LogError("出発"); return(NodeStatus.SUCCESS); }); // HP確認のDecorator DecoratorNode confirmationHp = new DecoratorNode(); confirmationHp.name = "HP確認するのDecorator"; confirmationHp.SetConditionFunc(() => { return(_myHp >= 100 ? NodeStatus.SUCCESS : NodeStatus.FAILURE); }); // 敵に寄る ActionNode enemyApproach = new ActionNode(); enemyApproach.name = "敵に寄るアクションノード"; enemyApproach.SetRunningFunc(() => { Debug.LogError("敵に寄る"); return(NodeStatus.SUCCESS); }); // HP確認のDecoratorの子供登録 confirmationHp.AddChild(enemyApproach); // 友達2人を呼ぶParallelNode ParallelNode callFriendAB = new ParallelNode(); callFriendAB.name = "友達2人を呼ぶParallelNode"; // 友達A ActionNode friendA = new ActionNode(); friendA.name = "友達Aを呼ぶ"; friendA.SetRunningFunc(() => { Debug.LogError("友達A"); return(NodeStatus.SUCCESS); }); // 友達B ActionNode friendB = new ActionNode(); friendB.name = "友達Bを呼ぶ"; friendB.SetRunningFunc(() => { Debug.LogError("友達B"); return(NodeStatus.SUCCESS); }); // 友達2人を呼ぶParallelNodeの子供登録 callFriendAB.AddChild(friendA); callFriendAB.AddChild(friendB); // スキルを繰り返し行うRepeaterNode RepeaterNode skillRepeater = new RepeaterNode(); skillRepeater.name = "スキルを繰り返し行うRepeaterNode"; // スキルを選択するSelector SelectorNode selectSkill = new SelectorNode(); selectSkill.name = "スキルを選択するSelector"; // スキルAの発動を確認するDecorator DecoratorNode triggerSkillA = new DecoratorNode(); triggerSkillA.name = "スキルAの発動を確認するDecorator"; triggerSkillA.SetConditionFunc(() => { int probability = Mathf.Clamp(probabilitySkillA, 0, 100); int random = Random.Range(0, 100); return(probability > random ? NodeStatus.SUCCESS : NodeStatus.FAILURE); }); // スキルA ActionNode skillA = new ActionNode(); skillA.name = "skillA"; skillA.SetRunningFunc(() => { Debug.LogError("skillA"); _enemyHp -= 50; return(NodeStatus.SUCCESS); }); // スキルAの発動を確認するDecoratorの子供登録 triggerSkillA.AddChild(skillA); // スキルB ActionNode skillB = new ActionNode(); skillB.name = "skillB"; skillB.SetRunningFunc(() => { Debug.LogError("skillB"); _enemyHp -= 60; return(NodeStatus.SUCCESS); }); // スキルを選択するSelectorの子供登録 selectSkill.AddChild(triggerSkillA); selectSkill.AddChild(skillB); // スキルを繰り返し行うRepeaterNodeの子供登録 skillRepeater._repeatNum = 2; skillRepeater.AddChild(selectSkill); // 敵の生存を確認するSelector SelectorNode enemySurvial = new SelectorNode(); enemySurvial.name = "敵の生存を確認するSelector"; // 敵が死んでいるか確認するDecorator DecoratorNode enemyDied = new DecoratorNode(); enemyDied.name = "敵が死んでいるか確認するDecorator"; enemyDied.SetConditionFunc(() => { return(_enemyHp <= 0 ? NodeStatus.SUCCESS : NodeStatus.FAILURE); }); // 敵が死んでいる ActionNode died = new ActionNode(); died.name = "敵が死んでいる"; died.SetRunningFunc(() => { Debug.LogError("End1"); Debug.LogError("EnemyHp : " + _enemyHp); return(NodeStatus.SUCCESS); }); // 敵が死んでいるか確認するDecoratorの子供登録 enemyDied.AddChild(died); // 敵が生きているか確認するDecorator DecoratorNode enemyAlive = new DecoratorNode(); enemyAlive.name = "敵が生きているか確認するDecorator"; enemyAlive.SetConditionFunc(() => { return(_enemyHp > 0 ? NodeStatus.SUCCESS : NodeStatus.FAILURE); }); // 敵が生きている ActionNode alive = new ActionNode(); alive.name = "敵が生きている"; alive.SetRunningFunc(() => { Debug.LogError("End2"); Debug.LogError("EnemyHp : " + _enemyHp); return(NodeStatus.SUCCESS); }); // 敵が生きているか確認するDecoratorの子供登録 enemyAlive.AddChild(alive); // 敵の生存を確認するSelectorの子供登録 enemySurvial.AddChild(enemyDied); enemySurvial.AddChild(enemyAlive); // rootノードの子供登録 rootNode.AddChild(departure); rootNode.AddChild(confirmationHp); rootNode.AddChild(callFriendAB); rootNode.AddChild(skillRepeater); rootNode.AddChild(enemySurvial); // ツリー実行 _behaviorTreeController.Initialize(rootNode); _behaviorTreeController.OnStart(); }
// Use this for initialization private void Start() { var waitPositonTime = 0f; GameObject attackPlayer = null; var isMoveTerget = false; var moveTerget = Vector3.zero; GameObject itemObject = null; var coolTime = 0f; // 行き先に向かって移動する this.UpdateAsObservable() .Where(_ => isMoveTerget) .Select(_ => { var path = new NavMeshPath(); isMoveTerget = NavMesh.CalculatePath(transform.position, moveTerget, NavMesh.AllAreas, path); return(path); }) .Where(x => x.corners.Length >= 2) .Do(_ => waitPositonTime = 0f) // 行き先を見つけた .Select(x => (x.corners[1] - x.corners[0]).normalized) .Select(x => AI_Extension.CalcDoc(x)) .Subscribe(moveDirectionSubject); // 止まっている時間のカウント this.UpdateAsObservable() .Where(_ => isMoveTerget == false) .Subscribe(_ => { waitPositonTime += Time.deltaTime; }); // 止まっている時間が一定数立ってしまったらとりあえずターゲットに向かって歩く this.ObserveEveryValueChanged(_ => waitPositonTime) .Where(_ => isMoveTerget == false) .Where(x => x > 1f) .Where(_ => (Vector3.Distance(moveTerget, transform.position) > StopDistance * (1f - LevelMaxGettingUpToTimeRate))) // 近くにすでにいるなら動かない .Select(_ => (moveTerget - transform.position).normalized) .Select(x => AI_Extension.CalcDoc(x)) .Subscribe(moveDirectionSubject); // 行きたい位置についたら移動処理を停止させる this.UpdateAsObservable() .Where(_ => isMoveTerget) .Select(_ => Mathf.Abs(Vector3.Distance(moveTerget, transform.position))) .Where(x => x < StopDistance * (1f - LevelMaxGettingUpToTimeRate)) .Subscribe(_ => isMoveTerget = false); // 敵の近くによったら攻撃する this.UpdateAsObservable() .Where(_ => attackPlayer != null) .Where(_ => (Vector3.Distance(attackPlayer.transform.position, this.transform.position) <= AttackDistance)) .Subscribe(_ => { onAttackButtonSubject.OnNext(true); onAttackButtonSubject.OnNext(false); }); // アイテム生成通知 StageSpawner.Instance.OnSpowenItemAsObservable() .Where(x => Vector3.Distance(x.transform.position, this.transform.position) < GetItemDistance) // 自分の近くに生成された .Subscribe(x => { // アイテムが存在していることを入れる itemObject = x; // 交戦中のプレイヤーを消しておく(取りに行くため) attackPlayer = null; }); // アイテム存在チェック var checkNearItemState = new ActionNode("CheckItem", _ => { if (itemObject != null) { return(NodeStatusEnum.Success); } return(NodeStatusEnum.Failure); }); // アイテムに近づくAI var goItemObject = new DecoratorNode("GoItemCheck", new ActionNode("GoItem", _ => { // 取れた取れてないにかかわらず終了 if (itemObject == null) { isMoveTerget = false; return(NodeStatusEnum.Success); } // ターゲットを設定 moveTerget = itemObject.transform.position; moveTerget.y = transform.position.y; isMoveTerget = true; return(NodeStatusEnum.Running); }) , () => (itemObject != null)); // 近くにアイテムがスポーンしたなら優先的に取り行くAI var checkItem = new SequenceNode("SearchItem", checkNearItemState // 生成してる , goItemObject // 取りに行く ); // 近くのプレイヤーを選択するAI var nearPlayer = new ActionNode("SearchPlayer", _ => { // 生きているプレイヤー取得 var players = PlayerManager.Instance.GetAlivePlayers(); if (players.Count <= 1) { isMoveTerget = false; return(NodeStatusEnum.Failure); } // ソート players.Sort((x, y) => { var xDist = Vector3.Distance(x.transform.position, this.transform.position); var yDist = Vector3.Distance(y.transform.position, this.transform.position); if (xDist == yDist) { return(0); } if (xDist > yDist) { return(1); } else { return(-1); } }); // 一番近いプレイヤーを選択 attackPlayer = players[1].gameObject; moveTerget = AI_Extension.RandomPosition(attackPlayer.transform.position, (1f - LevelMaxGettingUpToTimeRate)); // 時間経過で性格射撃になる moveTerget.y = transform.position.y; isMoveTerget = true; // 思考を停止するクールタイム coolTime = Random.Range(0.5f, 2f); coolTime *= (1f - LevelMaxGettingUpToTimeRate); // 時間経過で思考停止クールタイムがなくなる return(NodeStatusEnum.Success); } ); var aiCoolTime = new ActionNode("CoolTime", _ => { coolTime -= Time.deltaTime; if (coolTime < 0f) { return(NodeStatusEnum.Failure); } return(NodeStatusEnum.Running); }); // AI初期化 BehaviorTreeComponent.RegsterComponent(this.gameObject, new SelectorNode("name", checkItem, aiCoolTime, nearPlayer)); }
public void SimpleSearcherTest() { const string hitpoint = "hp"; const string distanceToTower = "distance"; var machine = new BehaviourMachine(); machine.DataStorage[hitpoint] = 100; machine.DataStorage[distanceToTower] = 10; machine.OnExecuteEvent += (m) => { var hp = (int)m.DataStorage[hitpoint]; var distance = (int)m.DataStorage[distanceToTower]; Debug.WriteLine($"HP: {hp}"); Debug.WriteLine($"Distance: {distance}"); }; var selector = new SelectorNode(); machine.RegisterRootNode(selector); var decoratorHp = new DecoratorNode(); selector.ChildNodes.Add(decoratorHp); decoratorHp.ConditionCallback = (m, n) => m.DataStorage.GetValue <int>(hitpoint) > 5; var attackNearEnemy = new ActionNode(); attackNearEnemy.ActionCallback = (m, n) => { Debug.WriteLine("近くの敵を攻撃"); var distance = (int)m.DataStorage[distanceToTower]; distance += 1; m.DataStorage[distanceToTower] = distance; var hp = (int)m.DataStorage[hitpoint]; hp -= 5; m.DataStorage[hitpoint] = hp; return(true); }; decoratorHp.ChildNode = attackNearEnemy; var sequencer = new SequencerNode(); selector.ChildNodes.Add(sequencer); var moveToNearTower = new ActionNode(); sequencer.ChildNodes.Add(moveToNearTower); moveToNearTower.ActionCallback = (m, n) => { var distance = (int)m.DataStorage[distanceToTower]; if (distance <= 0) { return(true); } Debug.WriteLine("近くのタワーに移動"); distance--; m.DataStorage[distanceToTower] = distance; return(true); }; var wait = new ActionNode(); sequencer.ChildNodes.Add(wait); wait.ActionCallback = (m, n) => { Debug.WriteLine("待機"); var distance = (int)m.DataStorage[distanceToTower]; if (distance < 5) { var hp = (int)m.DataStorage[hitpoint]; hp += 20; m.DataStorage[hitpoint] = hp; } return(true); }; for (var i = 0; i < 100; i++) { machine.Execute(); } }