/// <summary> /// This function is called when the object is loaded. /// </summary> public new void OnEnable() { base.OnEnable(); if (FuncNames == null) { FuncNames = AgentFunctions.GetConditionStrings(_conditionGroup); } }
/// <summary> /// Create LoopNode from json string. /// </summary> /// <param name="node"></param> /// <param name="jObj"></param> /// <returns></returns> private static Node Serialize(this LoopNode node, JsonObject jObj) { node.NodeName = jObj["type"].String; node.Id = jObj["ID"].String; //node.FuncIndex = jObj["functionID"].Int; node.ConditionGroup = jObj["conditionGroup"].ConditionGroup; node.FuncNames = AgentFunctions.GetConditionStrings(node.ConditionGroup); try { node.FunctionName = jObj["functionName"].String; } catch (Exception) { /*Debug.Log("Your behaviour has a deprecated format");*/ } try { node.MinTime = jObj["minTime"].Float; node.MaxTime = jObj["maxTime"].Float; } catch (Exception) { /*Debug.Log("Your behaviour has a deprecated format");*/ } var sortedFunctions = node.FuncNames; System.Array.Sort(sortedFunctions, StringComparer.InvariantCulture); if (node.FunctionName != null) { for (var i = 0; i < node.FuncNames.Length; i++) { if (node.FuncNames[i] == node.FunctionName) { node.FuncIndex = i; } } } if (node.FuncIndex == -1) { node.FuncIndex = jObj["functionID"].Int; } node.Reverse = jObj["reverse"] != null && jObj["reverse"].Bool; var x = jObj["rect"]["posX"].Float; var y = jObj["rect"]["posY"].Float; var w = jObj["rect"]["width"].Float; var h = jObj["rect"]["height"].Float; node.Rect = new Rect(x, y, w, h); return(node); }
//All the checks the agent goes though. private void AgentChecks() { if (AgentFunctions.CheckTarget(Target)) { Transition(FindTarget(), "No Target"); } if (AgentFunctions.CheckTargetLocation(TargetLocation)) { Transition(FindLocation(), "No Target Location"); } if (AgentFunctions.CheckForDeath(transform, -1)) { Transition(Death(), "Off Map"); } if (AgentFunctions.CheckDistanceToLocation(transform, TargetLocation, 2.0f)) { Transition(FindLocation(), "Arrived At Last Location"); } }
/// <summary> /// Get the array of method names for appropriate action group. /// </summary> private void GetFunctions() { switch (_actionGroup.enumValueIndex) { case 1: _skill = false; _options = AgentFunctions.GetFunctions <InventoryActionInterface>(); break; case 2: _skill = true; _options = new[] { _skillName }; _funcIndex.intValue = 0; break; default: _skill = false; _options = AgentFunctions.GetFunctions <MotionActionInterface>(); break; } ((InvokerNode)target).FuncNames = _options; }
IEnumerator Move() { while (NextState == null) { AgentChecks(); if (Target == null) { continue; //If AI has no target then skip. } float Dir = AgentFunctions.AngleDir(transform.up, (transform.position - TargetLocation), transform.forward); //Because I am using torque and not calculating a direction force, everything is simplified. Body.AddForce((transform.forward * TankSpeed) * Time.deltaTime); Body.AddTorque((transform.up * TurnSpeed * Dir) * Time.deltaTime); //Finds the turret rotation ignores the y rotation. Quaternion TargetRotation = AgentFunctions.GetTargetRotation(Target, transform); Turret.transform.rotation = Quaternion.Lerp(Turret.transform.rotation, TargetRotation, AgentBehaviour.RotationSpeed * Time.deltaTime); //FramesCount uses Time.deltatime so that it works with TimeScale FrameCount -= Time.deltaTime; if (FrameCount <= 0) { bFire = false; } //If turret is in specified range, change to shoot state. if (AgentFunctions.GetTargetAngle(Turret, Target, transform, AgentBehaviour.RotationAccuracy) && !bFire) { Transition(Shoot(), "Target In Range"); } yield return(null); } }
private void OnTriggerStay(Collider other) { //Very simple Tank avoidance. if (other.gameObject.tag == "Tank") { float Dir = AgentFunctions.AngleDir(transform.up, (transform.position - other.transform.position), transform.forward); if (Dir == 1) { Body.AddTorque(transform.up * TurnSpeed * -0.50f); Debug.DrawLine(transform.position, transform.position + transform.right * TurnSpeed * -2); } else { Body.AddTorque(transform.up * TurnSpeed * 0.50f); Debug.DrawLine(transform.position, transform.position + transform.right * TurnSpeed * 2); } } //Very simple Mine avoidance. if (other.gameObject.tag == "Mine") { float Dir = AgentFunctions.AngleDir(transform.up, (transform.position - other.transform.position), transform.forward); if (Dir == 1) { Body.AddTorque(transform.up * TurnSpeed * -1.0f); Debug.DrawLine(transform.position, transform.position + transform.right * TurnSpeed * -2); } else { Body.AddTorque(transform.up * TurnSpeed * 1.0f); Debug.DrawLine(transform.position, transform.position + transform.right * TurnSpeed * 2); } } }
//Tank Shoot IEnumerator Shoot() { bFire = true; FrameCount = AgentBehaviour.ReloadTime; if (Target == null) { Transition(Move(), "No Target Return To Move"); } // Create an instance of the shell and store a reference to it's rigidbody. Rigidbody ShellInstance = Instantiate(ShellActor, MuzzleLocation.position, MuzzleLocation.rotation) as Rigidbody; // Set the shell's velocity to the launch force in the fire position's forward direction. // I divide by a random value to simulate it's accuracy if (ShellInstance != null && Target != null) { ShellInstance.velocity = AgentFunctions.BallisticVel(transform, Target, 25.0f) / Random.Range(AgentBehaviour.MinDistAccuracy, AgentBehaviour.MaxDistAccuracy); } Transition(Move(), "Fired At Target"); yield return(null); }
/// <summary> /// Get the array of method names for appropriate action group. /// </summary> private void GetFunctions() { _options = AgentFunctions.GetConditionStrings(_conditionGroup.enumValueIndex); Array.Sort(_options, StringComparer.InvariantCulture); ((ObserverNode)target).FuncNames = _options; }
/// <summary> /// Create InvokerNode from json string. /// </summary> /// <param name="node"></param> /// <param name="jObj"></param> /// <returns></returns> private static Node Serialize(this InvokerNode node, JsonObject jObj) { node.NodeName = jObj["type"].String; node.Id = jObj["ID"].String; node.ActionGroup = jObj["actionGroup"].ActionGroup; if (node.ActionGroup == ActionGroup.Skill) { node.FuncIndex = 0; node.FuncNames = new[] { jObj["functionID"].String }; try { node.FunctionName = jObj["functionName"].String; } catch (Exception) { /*Debug.Log("Your behaviour has a deprecated format");*/ } if (jObj["executeSkill"] != null) { node.ExecuteSkill = jObj["executeSkill"].Bool; } } else if (node.ActionGroup == ActionGroup.Inventory) { //node.FuncIndex = jObj["functionID"].Int; node.FuncNames = AgentFunctions.GetFunctions <InventoryActionInterface>(); try { node.FunctionName = jObj["functionName"].String; } catch (Exception) { /*Debug.Log("Your behaviour has a deprecated format");*/ } } else { //node.FuncIndex = jObj["functionID"].Int; node.FuncNames = AgentFunctions.GetFunctions <MotionActionInterface>(); try { node.FunctionName = jObj["functionName"].String; } catch (Exception) { /*Debug.Log("Your behaviour has a deprecated format");*/ } } var sortedFunctions = node.FuncNames; System.Array.Sort(sortedFunctions, StringComparer.InvariantCulture); if (node.FunctionName != null) { for (var i = 0; i < node.FuncNames.Length; i++) { if (node.FuncNames[i] == node.FunctionName) { node.FuncIndex = i; } } } if (node.FuncIndex == -1) { node.FuncIndex = jObj["functionID"].Int; } var x = jObj["rect"]["posX"].Float; var y = jObj["rect"]["posY"].Float; var w = jObj["rect"]["width"].Float; var h = jObj["rect"]["height"].Float; node.Rect = new Rect(x, y, w, h); return(node); }
/// <summary> /// Decipher the file and create methods and relations between them using reflection. /// </summary> /// <param name="behaviour"></param> /// <param name="gameObject"></param> /// <returns></returns> public static BehaviourCore GetCore(EliotBehaviour behaviour, GameObject gameObject) { var core = new BehaviourCore(); behaviour.Json = BehaviourVersionManager.UpdateJson(behaviour.Json); // See if there are any nodes in file. var jObj = new JsonObject(behaviour.Json); var jNodes = jObj["nodes"].Objects; if (jNodes == null) { return(null); } Entry entry = null; var particles = new List <EliotComponent>(); // If there are, create Behaviour Components from each piece of data. if (jNodes.Count > 0) { foreach (var node in jNodes) { var nodeObj = (JsonObject)node; var type = nodeObj["type"].String; switch (type) { case "Entry": { entry = new Entry(nodeObj["ID"].String); particles.Add(entry); break; } case "Invoker": { var actionGroup = nodeObj["actionGroup"].ActionGroup; string[] funcNames; string functionName; int funcIndex = -1; var execute = true; if (actionGroup == ActionGroup.Skill) { funcIndex = 0; funcNames = new[] { nodeObj["functionID"].String }; functionName = nodeObj["functionName"].String; if (nodeObj["executeSkill"] != null) { execute = nodeObj["executeSkill"].Bool; } } else if (actionGroup == ActionGroup.Inventory) { //funcIndex = nodeObj["functionID"].Int; funcNames = AgentFunctions.GetFunctions <InventoryActionInterface>(); functionName = nodeObj["functionName"].String; } else { //funcIndex = nodeObj["functionID"].Int; funcNames = AgentFunctions.GetFunctions <MotionActionInterface>(); functionName = nodeObj["functionName"].String; } //_____________________________________CAUTION WORK IN PROGRESS________________________ //Array.Sort(funcNames, StringComparer.InvariantCulture); for (var i = 0; i < funcNames.Length; i++) { if (funcNames[i] == functionName) { funcIndex = i; } } if (funcIndex == -1) { funcIndex = nodeObj["functionID"].Int; } //_____________________________________________________________________________________ var inv = new Invoker(AgentFunctions.CreateAction(funcNames[funcIndex], gameObject, actionGroup, execute), nodeObj["ID"].String); particles.Add(inv); break; } case "Observer": { var funcIndex = nodeObj["functionID"].Int; var conditionGroup = nodeObj["conditionGroup"].ConditionGroup; var funcNames = AgentFunctions.GetConditionStrings(conditionGroup); var functionName = nodeObj["functionName"].String; var obs = new Observer(AgentFunctions.CreateCondition(functionName, gameObject, conditionGroup, nodeObj["ID"].Int), nodeObj["ID"].String); particles.Add(obs); break; } case "Loop": { var funcIndex = nodeObj["functionID"].Int; var conditionGroup = nodeObj["conditionGroup"].ConditionGroup; var funcNames = AgentFunctions.GetConditionStrings(conditionGroup); var functionName = nodeObj["functionName"].String; var reverse = nodeObj["reverse"] != null && nodeObj["reverse"].Bool; var loop = new Loop(core, reverse, AgentFunctions.CreateCondition(functionName, gameObject, conditionGroup, nodeObj["ID"].Int), nodeObj["ID"].String); particles.Add(loop); break; } } } } // Now we need to connect the Components. var jTransitions = jObj["transitions"].Objects; foreach (var trans in jTransitions) { // Retrieve the needed information from data. var transition = (JsonObject)trans; var startId = transition["startID"].String; var endId = transition["endID"].String; var isNeg = transition["type"].String.Equals("negative"); int minRate, maxRate; float minCooldown, maxCooldown; bool terminate; try { minRate = transition["minRate"].Int; maxRate = transition["maxRate"].Int; minCooldown = transition["minCooldown"].Float; maxCooldown = transition["maxCooldown"].Float; terminate = transition["terminate"].Bool; } catch (Exception) { minRate = 1; maxRate = 1; minCooldown = 0f; maxCooldown = 0f; terminate = false; } // Connect proper Components by their IDs. try { var type = ComponentTypeById(particles, startId); if (type == "Observer") { if (isNeg) { ((Observer)particles.FirstOrDefault(particle => particle.Id == startId)) .ConnectWith_Else(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } else { particles.FirstOrDefault(particle => particle.Id == startId) .ConnectWith(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } } else if (type == "Loop") { if (isNeg) { ((Loop)particles.FirstOrDefault(particle => particle.Id == startId)) .ConnectWith_End(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } else { particles.FirstOrDefault(particle => particle.Id == startId) .ConnectWith(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } } else { particles.FirstOrDefault(particle => particle.Id == startId) .ConnectWith(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } } catch (NullReferenceException) { Debug.Log("Something is wrong with data."); } } // Set the Entry. core.Entry = entry; return(core); }