public void Execute(StateMachine machine) { OnExecute(machine); StateMachine?.Execute(machine); if (BehaviourMachine != null) { machine.NodeResult = BehaviourMachine.Execute(machine); } }
public override void OnGUI(SerializedNodeProperty property, BehaviourMachine.ActionNode node, GUIContent guiContent) { // Now draw the property as a Slider or an IntSlider based on whether it’s a float or integer. if ( property.type != typeof(MinMaxRangeSO) ) Debug.LogWarning( "Use only with MinMaxRange type" ); else { var range = attribute as MinMaxRangeSAttribute; var so=(MinMaxRangeSO)property.value; //set or reset to default full range if(so.rangeStart==so.rangeEnd){ so.rangeStart=range.minLimit; so.rangeEnd=range.maxLimit; } var newMin =so.rangeStart; var newMax = so.rangeEnd; Rect position= GUILayoutUtility.GetRect(Screen.width-32f,32f); var xDivision = position.width * 0.33f; var yDivision = position.height * 0.5f; EditorGUI.LabelField( new Rect( position.x, position.y, xDivision, yDivision ) , guiContent ); EditorGUI.LabelField( new Rect( position.x, position.y + yDivision, position.width, yDivision ) , range.minLimit.ToString( "0.##" ) ); EditorGUI.LabelField( new Rect( position.x + position.width -28f, position.y + yDivision, position.width, yDivision ) , range.maxLimit.ToString( "0.##" ) ); EditorGUI.MinMaxSlider( new Rect( position.x + 24f, position.y + yDivision, position.width -48f, yDivision ) , ref newMin, ref newMax, range.minLimit, range.maxLimit ); EditorGUI.LabelField( new Rect( position.x + xDivision, position.y, xDivision, yDivision ) , "From: " ); newMin = Mathf.Clamp( EditorGUI.FloatField( new Rect( position.x + xDivision + 30, position.y, xDivision -30, yDivision ) , newMin ) , range.minLimit, newMax ); EditorGUI.LabelField( new Rect( position.x + xDivision * 2f, position.y, xDivision, yDivision ) , "To: " ); newMax = Mathf.Clamp( EditorGUI.FloatField( new Rect( position.x + xDivision * 2f + 24, position.y, xDivision -24, yDivision ) , newMax ) , newMin, range.maxLimit ); so.rangeStart = newMin; so.rangeEnd = newMax; property.ValueChanged(); property.ApplyModifiedValue(); property.serializedNode.ApplyModifiedProperties(); } }
/// <summary> /// 构造函数 抽象类不建议是public构造函数 /// </summary> /// <param name="parent"></param> protected BehaviourAI(Actor parent) { mRunningProperty = new AIRunningProperty(); mRunningProperty.SelfActor = parent; mRunningProperty.OriginalSelfActorPos = parent.transform.position; mRunningProperty.AI = this; mRunningProperty.ViewRange = GetActorViewRange(); mPathWalker = new AIActorPathWalker(parent); mMachine = new BehaviourMachine(this); mAmbient = new AIAmbientState(this); }
public override bool Execute(BehaviourMachine machine, INode parentNode) { base.Execute(machine, parentNode); var result = ConditionCallback?.Invoke(machine, this) ?? false; if (result) { return(ChildNode.Execute(machine, this)); } return(false); }
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); }; }
public StatusEventArgs(BehaviourMachine.Status status) { this.status = status; }
public override bool Execute(BehaviourMachine machine, INode parentNode) { base.Execute(machine, parentNode); return(ActionCallback.Invoke(machine, this)); }
public override void OnGUI(SerializedNodeProperty property, BehaviourMachine.ActionNode node, GUIContent guiContent) { Rect position= GUILayoutUtility.GetRect(Screen.width-32f,32f); Rect typePos = new Rect (position.x, position.y, 80, position.height); position.xMin = typePos.xMax; Rect varPos = new Rect (position.x, position.y, position.width, position.height); Type type; GUIContent[] displayOptionsTypes; Type[] types; UniUnityVariablePropertyAttribute attributeUni = attribute as UniUnityVariablePropertyAttribute; if (property.value == null) type = EditorGUILayoutEx.unityTypes [0]; else type = ((UnityVariable)property.value).ValueType; //blackboard vars LOCAL BlackboardCustom blackboard = node.blackboard as BlackboardCustom; List<UnityVariable> blackboardVariablesLocalList = blackboard.GetVariableBy (type); List<GUIContent> displayOptionsVariablesLocal= blackboardVariablesLocalList.Select ((item) => new GUIContent ("Local/" + item.name)).ToList(); //blackboard vars GLOBAL if (attributeUni.typesCustom != null) { GUIContent[] displayOptionsCustom=attributeUni.typesCustom.Select((itm)=>new GUIContent(itm.Name)).ToArray(); if(attributeUni.only){ types=attributeUni.typesCustom; displayOptionsTypes=displayOptionsCustom; }else{ types=attributeUni.typesCustom.Concat<Type>(EditorGUILayoutEx.unityTypes).ToArray(); displayOptionsTypes = displayOptionsCustom.Concat<GUIContent>(EditorGUILayoutEx.unityTypesDisplayOptions).ToArray(); } }else{ displayOptionsTypes=EditorGUILayoutEx.unityTypesDisplayOptions; types=EditorGUILayoutEx.unityTypes; } //String name = attributeUni.name; //create types selection popup typeSelected = EditorGUILayoutEx.CustomObjectPopup<Type> (null, type,displayOptionsTypes , types,null,null,null,null,typePos); //if change of type create new variable if (typeSelected != type && !typeSelected.IsSubclassOf (type) /*&& type!=typeof(UnityEngine.Object)*/) { property.value = UnityVariable.CreateInstanceOf(typeSelected); } property.value=EditorGUILayoutEx.UnityVariablePopup(null,property.value as UnityVariable,typeSelected,displayOptionsVariablesLocal,blackboardVariablesLocalList,varPos); property.serializedNode.ApplyModifiedProperties(); }
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(); } }