protected override void RegisterComponent() { base.RegisterComponent(); BuffComp = AddComponent <BuffComponent>(); HumanStateMachineComp = AddComponent <HumanStateMachineComponent>(); BehaviorTreeComp = AddComponent <BehaviorTreeComponent>(); }
private void UpdateRoot() { if (this is BehaviorTreeComponent bht) { _root = bht; return; } var root = GetParent(); while (!(root is BehaviorTreeComponent)) { root = root.GetParent(); } _root = root as BehaviorTreeComponent; }
void SelectionChanged() { if (Selection.gameObjects.Length > 0) { if (Selection.gameObjects.Length > 1) { _selectedGameObject = null; _selectionErrorMessage = "Multiediting not supported"; } else { if (_selectedGameObject != Selection.gameObjects[0]) { BehaviorTreeComponent btc = Selection.gameObjects[0].GetComponent <BehaviorTreeComponent>(); if (btc == null) { _selectedGameObject = null; _selectionErrorMessage = "Selected game object doesn't have BehaviorTreeComponent attached"; } else { _allMethods.Clear(); Component[] comps = Selection.gameObjects[0].GetComponents <MonoBehaviour>(); foreach (Component c in comps) { Type t = c.GetType(); MethodInfo[] mis = new List <MethodInfo>(t.GetMethods()).Where(mi => mi.ReturnType == typeof(TaskStatus)).ToArray(); foreach (MethodInfo mi in mis) { if (mi.ReturnType != typeof(TaskStatus)) { continue; } ParameterInfo[] pis = mi.GetParameters(); if (pis.Length == 1) { if (pis[0].ParameterType == typeof(GameObject)) { string type = t.ToString(); string methodName = mi.Name; string newMethod = type + "." + methodName; _allMethods.Add(newMethod); } } } } _drawer.SetMethodsList(_allMethods); _selectedGameObject = Selection.gameObjects[0]; _selectedAsset = btc.BehaviorTreeAsset; FileSelectedChanged(); } } } } else { _selectedGameObject = null; _selectionErrorMessage = "Please, select some object on scene with BehaviorTreeComponent attached"; } Repaint(); }
// 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)); }