public void Remove(AI_Character oldVillager) { if (villagerList.Contains(oldVillager)) { villagerList.Remove(oldVillager); totalVillagers--; switch (oldVillager.myRole) { case AI_Character.Role.Villager: villagers--; break; case AI_Character.Role.Woodcutter: woodcutters--; break; case AI_Character.Role.Miner: miners--; break; case AI_Character.Role.Militia: militia--; break; default: break; } } else { Debug.Log("Tried to remove non-existing villager"); } }
/// <summary> /// Used by any character to find a path to a building target /// </summary> /// <returns>The building.</returns> /// <param name="character">Character.</param> /// <param name="buildingType">Building type.</param> public Building FindBuilding(AI_Character character, Building.Structure buildingType) { int num = -1; float dist = 9999; NavMeshPath path = new NavMeshPath(); for (int i = 0; i < buildingsList.Count; i++) { if (buildingsList [i].structure != buildingType) { continue; } if (!Distance.GetPath(character.transform.position, buildingsList [i].buildingTarget.transform.position, NavMesh.AllAreas, path)) { continue; } else { if (Distance.GetPathLength(path) < dist) { dist = Distance.GetPathLength(path); num = i; } } } if (num == -1) { return(null); } return(buildingsList [num]); }
public EnemyCharacter FindClosestEnemy(AI_Character character, float detectionRange) { int num = -1; float dist = detectionRange + 0.1f; NavMeshPath path = new NavMeshPath(); for (int i = 0; i < enemyList.Count; i++) { if (!Distance.GetPath(character.transform.position, enemyList [i].transform.position, NavMesh.AllAreas, path)) { break; } else { if (Distance.GetPathLength(path) < dist) { dist = Distance.GetPathLength(path); num = i; } } } if (num == -1) { return(null); } return(enemyList [num]); }
// Character dealt damage public void OnDamageDealt(AI_Character target, float damage_dealt) { if (this.CurrentAction != null) { this.CurrentAction.OnActionDamageDealt(damage_dealt); } }
// Character took damage public void OnDamageTaken(AI_Character caster, float damage_taken) { if (this.CurrentAction != null) { this.CurrentAction.OnActionDamageTaken(damage_taken); } }
/// <summary> /// Called when a character finishes its current action. /// </summary> /// <param name="caster">Caster</param> public void OnCharacterActionFinished(AI_Character caster) { Debug.Log("[AI] Action finished (Caster ID: " + caster.CharacterID + ")."); AI_Action action = caster.OnActionFinished(this.LastUpdateTime); this.TrainAction(action); }
public AI_Action(EActionCode action_code, AI_Character caster, AI_Character target) { this.ActionCode = action_code; this.Caster = caster; this.Target = target; this.Success = false; }
public void CheckLook() { UIManager.instance.HideTargetText(); UIManager.instance.HideCenterText(); UIManager.instance.HideHealthBar(); Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward); RaycastHit hit; if (Physics.Raycast(ray, out hit, 4.0f)) { if (hit.transform.tag == "Resource") { Resource resource = hit.transform.GetComponent <Resource> (); UIManager.instance.UpdateHealthBar(resource.amount, resource.maxAmount, hit.transform.name); if (hitCount < maxHitCount) { if (resource.resourceType == Resource.ResourceType.Wood) { UIManager.instance.ShowCenterText("Press LMB with the AXE to collect"); } else { UIManager.instance.ShowCenterText("Press LMB with the PICKAXE to collect"); } } else { UIManager.instance.ShowCenterText("Can't carry anymore!"); } } if (hit.transform.tag == "ResourceDrop" && hit.transform.root.gameObject.GetComponent <Building> ().structure == Building.Structure.ResourceDrop && myItem != Resource.ResourceType.None) { UIManager.instance.ShowCenterText("Press 'G' to drop off resources!"); } if (hit.transform.tag == "Building") { Building currentBuilding = hit.transform.root.gameObject.GetComponent <Building> (); UIManager.instance.ShowFlavourText(currentBuilding); } if (hit.transform.root.tag == "Ally") { AI_Character ally = hit.transform.root.gameObject.GetComponent <AI_Character> (); UIManager.instance.UpdateHealthBar(ally.health, ally.maxHealth, ally.transform.name); } if (hit.transform.root.tag == "Enemy") { EnemyCharacter enemy = hit.transform.root.gameObject.GetComponent <EnemyCharacter> (); UIManager.instance.UpdateHealthBar(enemy.health, enemy.maxHealth, enemy.transform.name); } } else { //not seeing anything } }
public static void DecreaseRole(AI_Character.Role removingRole) { if (CheckVillagerInRole(removingRole)) { AI_Character chosenVillager = GetVillagerInRole(removingRole); UpdateRoleCount(chosenVillager.myRole, AI_Character.Role.Villager); chosenVillager.SetRole(AI_Character.Role.Villager); } }
public static void IncreaseRole(AI_Character.Role newRole) { if (CheckAvailableVillager()) { AI_Character chosenVillager = GetAvailableVillager(); UpdateRoleCount(chosenVillager.myRole, newRole); chosenVillager.SetRole(newRole); } }
public void Add(AI_Character newVillager) { if (villagerList.Contains(newVillager)) { return; } villagerList.Add(newVillager); villagers++; totalVillagers++; }
/// <summary> /// Update all characters. /// </summary> /// <param name="p">Update parameters</param> public void UpdateCharacters(AI_Params p) { foreach (AI_Params.AI_ParamCharacter c in p.Characters) { // Create a new character if ID doesn't already exist if (!this.Characters.ContainsKey(c.CharacterID)) { Debug.Log("Adding new character (Character ID: " + c.CharacterID + ")."); this.Characters[c.CharacterID] = new AI_Character(c.CharacterID, c.CharacterType); } // Update character information AI_Character character = this.Characters[c.CharacterID]; character.OnSeenByAI(this.LastUpdateTime, c.Position, c.Direction, c.Velocity); } }
/// <summary> /// Trains the anticipation network. /// </summary> /// <param name="player">Player</param> /// <param name="action_code">Code of the action performed</param> public void TrainAnticipation(AI_Character player, EActionCode action_code) { AI_DeepLearningNetwork network; float[] outputs = new float[(int)EActionCode.Count]; for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { outputs[(int)code] = (code == action_code) ? 1.0f : 0.0f; } foreach (AI_Character c in this.Characters.Values) { if (c.CharacterType == ECharacterType.CharacterTypeEnemy && c.IsAlive) { if (player.PreviousAction != null) { network = this.Networks_Anticipation_1[player.PreviousAction.ActionCode]; network.Learn(new float[] { Vector3.Distance(c.Position, player.Position), Vector3.Angle(player.Direction, c.Position - player.Position), Vector3.Angle(c.Direction, player.Position - c.Position), this.LastUpdateTime - player.PreviousAction.CastTime }, outputs); } if (c.CurrentAction != null) { network = this.Networks_Anticipation_2[c.CurrentAction.ActionCode]; network.Learn(new float[] { Vector3.Distance(c.Position, player.Position), Vector3.Angle(player.Direction, c.Position - player.Position), Vector3.Angle(c.Direction, player.Position - c.Position), this.LastUpdateTime - c.CurrentAction.CastTime }, outputs); } else { network = this.Networks_Anticipation_2[EActionCode.ActionCodeNoAction]; network.Learn(new float[] { Vector3.Distance(c.Position, player.Position), Vector3.Angle(player.Direction, c.Position - player.Position), Vector3.Angle(c.Direction, player.Position - c.Position), this.LastUpdateTime - c.CurrentAction.CastTime }, outputs); } } } }
/// <summary> /// Called when a character starts a new action. /// </summary> /// <param name="caster">Caster</param> /// <param name="action_code">Code of the action (see EActionCode)</param> public void OnCharacterActionStarted(AI_Character caster, EActionCode action_code) { Debug.Log("[AI] Action started (Caster ID: " + caster.CharacterID + ", Action Code: " + action_code + ")."); AI_Character target = null; // Determining the target switch (caster.CharacterType) { case ECharacterType.CharacterTypeEnemy: Debug.Assert(this.Characters.ContainsKey(AI_Params.PlayerID), "[AI] Invalid player ID (" + AI_Params.PlayerID + ")."); target = this.Characters[AI_Params.PlayerID]; break; case ECharacterType.CharacterTypePlayer: float distance = 10000.0f; foreach (AI_Character c in this.Characters.Values) { if (distance > Vector3.Distance(c.Position, caster.Position) + Mathf.Abs(Vector3.Angle(caster.Direction, c.Position - caster.Position))) { distance = Vector3.Distance(c.Position, caster.Position) + Mathf.Abs(Vector3.Angle(caster.Direction, c.Position - caster.Position)); target = c; } } break; } // Registering the action AI_Action action = caster.OnActionStarted(this.LastUpdateTime, action_code, target); foreach (AI_Character c in this.Characters.Values) { if ((c.CurrentAction != null) && (c.CurrentAction.Target.CharacterID == caster.CharacterID)) { c.CurrentAction.OnTargetActionStarted(action); } } // Training anticipation network if (caster.CharacterType == ECharacterType.CharacterTypePlayer) { this.TrainAnticipation(caster, action_code); } }
/// <summary> /// used specifically for dropping off resources at the correcct building /// </summary> /// <returns>The building resource drop.</returns> /// <param name="character">Character requesting path.</param> /// <param name="buildingType">Building type.</param> /// <param name="resourceType">Resource type.</param> public Building FindBuildingResourceDrop(AI_Character character, Building.Structure buildingType, Resource.ResourceType resourceType) { int num = -1; float dist = 9999; NavMeshPath path = new NavMeshPath(); for (int i = 0; i < buildingsList.Count; i++) { //check for right structure if (buildingsList [i].structure != buildingType) { continue; } //check for right drop type if (buildingsList [i].dropType != Building.ResourceDropType.All && buildingsList [i].dropType.ToString() != resourceType.ToString()) { continue; } if (!Distance.GetPath(character.transform.position, buildingsList [i].buildingTarget.transform.position, NavMesh.AllAreas, path)) { continue; } else { if (Distance.GetPathLength(path) < dist) { dist = Distance.GetPathLength(path); num = i; } } } if (num == -1) { return(null); } return(buildingsList [num]); }
// Update is called once per frame void Update() { #region Check for AI Follow Link if (OtherAI_Object == null) { if (this.gameObject.name != "AI Matt" && GameObject.Find("AI Matt") != null) { if (GameObject.Find("AI Matt").GetComponent<AI_Character>().Action == AI_Action.FollowPlayer) OtherAI_Object = GameObject.Find("AI Matt"); } if (this.gameObject.name != "AI Josh" && GameObject.Find("AI Josh") != null) { if (GameObject.Find("AI Josh").GetComponent<AI_Character>().Action == AI_Action.FollowPlayer) OtherAI_Object = GameObject.Find("AI Josh"); } if (this.gameObject.name != "AI Kate" && GameObject.Find("AI Kate") != null) { if (GameObject.Find("AI Kate").GetComponent<AI_Character>().Action == AI_Action.FollowPlayer) OtherAI_Object = GameObject.Find("AI Kate"); } if (this.gameObject.name != "AI April" && GameObject.Find("AI April") != null) { if (GameObject.Find("AI April").GetComponent<AI_Character>().Action == AI_Action.FollowPlayer) OtherAI_Object = GameObject.Find("AI April"); } if (this.gameObject.name != "AI Ethan" && GameObject.Find("AI Ethan") != null) { if (GameObject.Find("AI Ethan").GetComponent<AI_Character>().Action == AI_Action.FollowPlayer) OtherAI_Object = GameObject.Find("AI Ethan"); } if (OtherAI_Object != null) Script_OtherAIObject = OtherAI_Object.GetComponent<AI_Character>(); } #endregion //var CircleCollision.enabled = true; if (Action == AI_Action.Stationary) //Stay at complete rest { #region Completely Stationary Body.isKinematic = true; #endregion } else if (Action == AI_Action.StationaryWithDir) //Stay at rest, but occationaly change directions { #region Stationary With Direction Body.isKinematic = true; if (Random.Range(0, 150) == 69) //Choose random number from 1 - 150. If the number is 69, change directions { int DirectionRange = Random.Range(0, 4); //Randomly choose a direction: 0 is down, 1 is right, 2 is up, 3 is left if (DirectionRange == 0) //Look up AI! { Anim.SetInteger("Direction", 0); } else if (DirectionRange == 1) //Look right AI! { Anim.SetInteger("Direction", 1); } else if (DirectionRange == 2) //Look down AI! { Anim.SetInteger("Direction", 2); } else if (DirectionRange == 3) //Look left AI! { Anim.SetInteger("Direction", 3); } } #endregion } else if (Action == AI_Action.FollowPlayer) //Follow player { #region Follow Player #region SavePosition //Check if you need to write AI position to save data CounterPos++; if (CounterPos >= 150) { //Read in SaveGame.xml XmlDocument SaveGameDoc = new XmlDocument(); SaveGameDoc.LoadXml(DoSaveGame.FetchSaveData()); foreach (XmlNode node in SaveGameDoc.SelectNodes("SaveData/SaveState/Scenes/Scene")) { if (Application.loadedLevelName == node.SelectSingleNode("SceneName").InnerText) { if (this.gameObject.name == "AI Josh") { node.SelectSingleNode("AI/JoshAI/X").InnerText = transform.position.x.ToString(); node.SelectSingleNode("AI/JoshAI/Y").InnerText = transform.position.y.ToString(); node.SelectSingleNode("AI/JoshAI/Action").InnerText = "FollowPlayer"; } else if (this.gameObject.name == "AI Matt") { node.SelectSingleNode("AI/MattAI/X").InnerText = transform.position.x.ToString(); node.SelectSingleNode("AI/MattAI/Y").InnerText = transform.position.y.ToString(); node.SelectSingleNode("AI/MattAI/Action").InnerText = "FollowPlayer"; } else if (this.gameObject.name == "AI Kate") { node.SelectSingleNode("AI/KateAI/X").InnerText = transform.position.x.ToString(); node.SelectSingleNode("AI/KateAI/Y").InnerText = transform.position.y.ToString(); node.SelectSingleNode("AI/KateAI/Action").InnerText = "FollowPlayer"; } else if (this.gameObject.name == "AI April") { node.SelectSingleNode("AI/AprilAI/X").InnerText = transform.position.x.ToString(); node.SelectSingleNode("AI/AprilAI/Y").InnerText = transform.position.y.ToString(); node.SelectSingleNode("AI/AprilAI/Action").InnerText = "FollowPlayer"; } else if (this.gameObject.name == "AI Ethan") { node.SelectSingleNode("AI/EthanAI/X").InnerText = transform.position.x.ToString(); node.SelectSingleNode("AI/EthanAI/Y").InnerText = transform.position.y.ToString(); node.SelectSingleNode("AI/EthanAI/Action").InnerText = "FollowPlayer"; } //Save XML DoSaveGame.UpdateSaveData(SaveGameDoc); } } CounterPos = 0; } #endregion //Var for AI x and y float XMove = 0; float YMove = 0; Body.isKinematic = false; if (FindPath() > 1.75) //If AI far away from Player, go to the player { //if game just started and everything is set to 0 (and if everything is 0, it causes problems) if (PlayerPreviousPosition[0, 0] == 0 && PlayerPreviousPosition[0, 1] == 0 && AIarrayPart == 0) { for (int i = 0; i < 120; i++) //fill entire array with players position (better than 0) { PlayerPreviousPosition[i, 0] = Player.Body.position.x; PlayerPreviousPosition[i, 1] = Player.Body.position.y; } } //find players position every 10 frames (1/6 a second). This is so it remembers the players path. (history path) if (PlayerPositionCounter >= 10) { if (ArrayCount >= 120) //Go to beginning of array { ArrayCount = 0; } PlayerPreviousPosition[ArrayCount, 0] = Player.Body.position.x; PlayerPreviousPosition[ArrayCount, 1] = Player.Body.position.y; ArrayCount++; PlayerPositionCounter = 0; } PlayerPositionCounter++; //AI follow the history path of player //Follow to interval if (Counter7 >= 11) //Do not make is 11 or less!!! { AIarrayPart++; if (AIarrayPart >= 120) { AIarrayPart = 0; } Counter7 = 0; //---Check if skip is needed--- //check 1 behind ai count to see if the (x,y) is the same, and if so, preform a skip (for a max skip length of one full period (120) //special case of when array index is 0, it looks back at index 119 if (AIarrayPart == 0) //Special Case { //Look back in time if (PlayerPreviousPosition[AIarrayPart, 0] == PlayerPreviousPosition[119, 0] && PlayerPreviousPosition[AIarrayPart, 1] == PlayerPreviousPosition[119, 1]) { //If the same, do a skip for (int i = 0; i < 120; i++) { AIarrayPart++; //Increment AIarrayPart counter if (AIarrayPart >= 120) //Check if is at end of array so it can start from beginning. Kinda like a special case { AIarrayPart = 0; if (ArrayCount == 119 || PlayerPreviousPosition[AIarrayPart, 0] != PlayerPreviousPosition[119, 0] || PlayerPreviousPosition[AIarrayPart, 1] != PlayerPreviousPosition[119, 1]) { break; //Exit loop } } else //non-special case / regular case { if (AIarrayPart == ArrayCount + 1 || PlayerPreviousPosition[AIarrayPart, 0] != PlayerPreviousPosition[AIarrayPart - 1, 0] || PlayerPreviousPosition[AIarrayPart, 1] != PlayerPreviousPosition[AIarrayPart - 1, 1]) { break; //Exit loop } } } } } else //Regular Case { //Look back in time if (PlayerPreviousPosition[AIarrayPart, 0] == PlayerPreviousPosition[AIarrayPart - 1, 0] && PlayerPreviousPosition[AIarrayPart, 1] == PlayerPreviousPosition[AIarrayPart - 1, 1]) { //If the same, do a skip for (int i = 0; i < 120; i++) { AIarrayPart++; //Increment AIarrayPart counter if (AIarrayPart >= 120) //Check if is at end of array so it can start from beginning. Kinda like a special case { AIarrayPart = 0; if (ArrayCount == 119 || PlayerPreviousPosition[AIarrayPart, 0] != PlayerPreviousPosition[119, 0] || PlayerPreviousPosition[AIarrayPart, 1] != PlayerPreviousPosition[119, 1]) { break; //Exit loop } } else //non-special case / regular case { if (AIarrayPart == ArrayCount + 1 || PlayerPreviousPosition[AIarrayPart, 0] != PlayerPreviousPosition[AIarrayPart - 1, 0] || PlayerPreviousPosition[AIarrayPart, 1] != PlayerPreviousPosition[AIarrayPart - 1, 1]) { break; //Exit loop } } } } } } Counter7++; if (Body.position.x != PlayerPreviousPosition[AIarrayPart, 0]) { XMove = Find_X_Distance(); } if (Body.position.y != PlayerPreviousPosition[AIarrayPart, 1]) { YMove = Find_Y_Distance(); } } else if (FindPath() < 1.75) //If Player and AI collide { //Let Player go through AI, temporarily disable circle collider //(gameObject.GetComponent(typeof(Collider)) as Collider).isTrigger = true; CircleCollision.enabled = false; if (FollowOtherAI == true && Script_OtherAIObject.FindPath() > 1.75) { //Do Nothing } else { //Reset PreviousPlayerPosition Array AIarrayPart = 0; for (int i = 0; i < 120; i++) { PlayerPreviousPosition[i, 0] = Player.Body.position.x; PlayerPreviousPosition[i, 1] = Player.Body.position.y; } } } //Execute Movement PlayerMovement.PlayerMove(Body, WalkSpeed, Anim, XMove, YMove); #endregion } else if (Action == AI_Action.Event) //Do an event { #region Preform Event Body.isKinematic = true; if (EventType == PreviousEventType) //Continue on with event { EventStepCase = Body.GetComponent<AI_Events>().PreformEvent(Body, WalkSpeed, Anim, EventType, Original_X, Original_Y, EventStepCase); //Execute Event while retrieving the CaseStep } else //Start a new event { Original_X = Body.position.x; Original_Y = Body.position.y; EventStepCase = 1; PreviousEventType = EventType; Body.GetComponent<AI_Events>().GetLocation(Body, EventType, EventStepCase); //---Set values for save data--- //Read in SaveGame.xml XmlDocument SaveGameDoc = new XmlDocument(); SaveGameDoc.LoadXml(DoSaveGame.FetchSaveData()); //Find current scene then find ScenePart. foreach (XmlNode node in SaveGameDoc.SelectNodes("SaveData/SaveState/Scenes/Scene")) { if (Application.loadedLevelName == node.SelectSingleNode("SceneName").InnerText) { if (Body.name == "AI Josh") { node.SelectSingleNode("AI/JoshAI/X").InnerText = Body.position.x.ToString(); node.SelectSingleNode("AI/JoshAI/Y").InnerText = Body.position.y.ToString(); node.SelectSingleNode("AI/JoshAI/Action").InnerText = "Event"; node.SelectSingleNode("AI/JoshAI/EventType").InnerText = EventType.ToString(); node.SelectSingleNode("AI/JoshAI/CaseStep").InnerText = EventStepCase.ToString(); } else if (Body.name == "AI Matt") { node.SelectSingleNode("AI/MattAI/X").InnerText = Body.position.x.ToString(); node.SelectSingleNode("AI/MattAI/Y").InnerText = Body.position.y.ToString(); node.SelectSingleNode("AI/MattAI/Action").InnerText = "Event"; node.SelectSingleNode("AI/MattAI/EventType").InnerText = EventType.ToString(); node.SelectSingleNode("AI/MattAI/CaseStep").InnerText = EventStepCase.ToString(); } else if (Body.name == "AI Kate") { node.SelectSingleNode("AI/KateAI/X").InnerText = Body.position.x.ToString(); node.SelectSingleNode("AI/KateAI/Y").InnerText = Body.position.y.ToString(); node.SelectSingleNode("AI/KateAI/Action").InnerText = "Event"; node.SelectSingleNode("AI/KateAI/EventType").InnerText = EventType.ToString(); node.SelectSingleNode("AI/KateAI/CaseStep").InnerText = EventStepCase.ToString(); } else if (Body.name == "AI April") { node.SelectSingleNode("AI/AprilAI/X").InnerText = Body.position.x.ToString(); node.SelectSingleNode("AI/AprilAI/Y").InnerText = Body.position.y.ToString(); node.SelectSingleNode("AI/AprilAI/Action").InnerText = "Event"; node.SelectSingleNode("AI/AprilAI/EventType").InnerText = EventType.ToString(); node.SelectSingleNode("AI/AprilAI/CaseStep").InnerText = EventStepCase.ToString(); } else if (Body.name == "AI Ethan") { node.SelectSingleNode("AI/EthanAI/X").InnerText = Body.position.x.ToString(); node.SelectSingleNode("AI/EthanAI/Y").InnerText = Body.position.y.ToString(); node.SelectSingleNode("AI/EthanAI/Action").InnerText = "Event"; node.SelectSingleNode("AI/EthanAI/EventType").InnerText = EventType.ToString(); node.SelectSingleNode("AI/EthanAI/CaseStep").InnerText = EventStepCase.ToString(); } break; } } //Save XML DoSaveGame.UpdateSaveData(SaveGameDoc); Body.GetComponent<AI_Events>().PreformEvent(Body, WalkSpeed, Anim, EventType, Original_X, Original_Y, EventStepCase); } #endregion } }
/// <summary> /// Called when a character takes damage. /// </summary> /// <param name="caster">Caster</param> /// <param name="target">Target</param> /// <param name="damage">Damage dealt</param> public void OnCharacterDamageDealt(AI_Character caster, AI_Character target, float damage) { Debug.Log("[AI] Damage dealt (Caster ID: " + caster.CharacterID + ", Target ID: " + target.CharacterID + ", Damage: " + damage + ")."); caster.OnDamageDealt(target, damage); target.OnDamageTaken(caster, damage); }
/// Character started an action public AI_Action OnActionStarted(float game_time, EActionCode action_code, AI_Character target) { this.CurrentAction = new AI_Action(action_code, this, target); this.CurrentAction.OnActionStarted(game_time); return(this.CurrentAction); }
/// <summary> /// Called when a character dies. /// </summary> /// <param name="caster">Character</param> public void OnCharacterDeath(AI_Character character) { Debug.Log("[AI] Character died (Character ID: " + character.CharacterID + ")."); character.OnDeath(); }
public Resource FindClosestResource(AI_Character character, Resource.ResourceType resource) { int num = -1; float dist = 9999; List <Resource> resourceList; if (resource == Resource.ResourceType.Wood) { resourceList = treeList; } else if (resource == Resource.ResourceType.Stone) { resourceList = stoneList; } else { return(null); } if (resourceList.Count <= 0) { //Debug.Log ("no resource found"); return(null); } NavMeshPath path = new NavMeshPath(); for (int i = 0; i < resourceList.Count; i++) { if (resourceList [i].Activated == false) { continue; } if (!resourceList [i]) { continue; } if (!Distance.GetPath(character.transform.position, resourceList [i].transform.position, NavMesh.AllAreas, path)) { break; } else { if (Distance.GetPathLength(path) < dist) { dist = Distance.GetPathLength(path); num = i; } } } if (num == -1) { return(null); } return(resourceList [num]); }
/// <summary> /// Thinks the next player action. /// </summary> public void ThinkAnticipation() { Debug.Assert(this.Characters.ContainsKey(AI_Params.PlayerID), "[AI] Invalid player ID (" + AI_Params.PlayerID + ")."); AI_Character player = this.Characters[AI_Params.PlayerID]; bool changed = false; // Training guard if ((player.CurrentAction != null) && (player.CurrentAction.ActionCode == EActionCode.ActionCodeGuard)) { this.TrainAnticipation(player, EActionCode.ActionCodeGuard); } // Training idle if ((player.CurrentAction == null) || (player.CurrentAction.ActionCode == EActionCode.ActionCodeNoAction)) { this.TrainAnticipation(player, EActionCode.ActionCodeNoAction); } // Decaying anticipation probability if (this.LastUpdateTime > this.Anticipation_ActionTime) { this.Anticipation_Probability -= this.LastUpdateTime - this.Anticipation_ActionTime; this.Anticipation_ActionTime = this.LastUpdateTime; // Reset anticipation after a while if (this.Anticipation_Probability < 0.0f) { this.Anticipation_Probability = 0.0f; this.Anticipation_ActionCode = EActionCode.ActionCodeNoAction; } } float[] outputs; AI_DeepLearningNetwork network; // Trying different anticipation timings for (float t = 0.1f; t <= 1.0f; t += 0.1f) { // We will add the anticipation results from each AI for each action in this array float[] actions = new float[(int)EActionCode.Count]; for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { actions[(int)code] = 0.0f; } // Each AI character participates in the anticipation foreach (AI_Character c in this.Characters.Values) { if (c.CharacterType == ECharacterType.CharacterTypeEnemy && c.IsAlive) { // Anticipation from current/previous player action if (player.CurrentAction != null) { network = this.Networks_Anticipation_1[player.CurrentAction.ActionCode]; outputs = network.Think(new float[] { Vector3.Distance(c.PositionIn(t), player.PositionIn(t)), Vector3.Angle(player.Direction, c.PositionIn(t) - player.PositionIn(t)), Vector3.Angle(c.Direction, player.PositionIn(t) - c.PositionIn(t)), t + this.LastUpdateTime - player.CurrentAction.CastTime }, network.Variance); for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { actions[(int)code] += outputs[(int)code]; } } else if (player.PreviousAction != null) { network = this.Networks_Anticipation_1[player.PreviousAction.ActionCode]; outputs = network.Think(new float[] { Vector3.Distance(c.PositionIn(t), player.PositionIn(t)), Vector3.Angle(player.Direction, c.PositionIn(t) - player.PositionIn(t)), Vector3.Angle(c.Direction, player.PositionIn(t) - c.PositionIn(t)), t + this.LastUpdateTime - player.PreviousAction.CastTime }, network.Variance); for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { actions[(int)code] += outputs[(int)code]; } } // Anticipation from current AI action if (c.CurrentAction != null) { network = this.Networks_Anticipation_2[c.CurrentAction.ActionCode]; outputs = network.Think(new float[] { Vector3.Distance(c.PositionIn(t), player.PositionIn(t)), Vector3.Angle(player.Direction, c.PositionIn(t) - player.PositionIn(t)), Vector3.Angle(c.Direction, player.PositionIn(t) - c.PositionIn(t)), t + this.LastUpdateTime - c.CurrentAction.CastTime }, network.Variance); for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { actions[(int)code] += outputs[(int)code]; } } else { network = this.Networks_Anticipation_2[EActionCode.ActionCodeNoAction]; outputs = network.Think(new float[] { Vector3.Distance(c.PositionIn(t), player.PositionIn(t)), Vector3.Angle(player.Direction, c.PositionIn(t) - player.PositionIn(t)), Vector3.Angle(c.Direction, player.PositionIn(t) - c.PositionIn(t)), t }, network.Variance); for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { actions[(int)code] += outputs[(int)code]; } } } } // Choosing the most likely action for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { if (this.Anticipation_Probability < actions[(int)code]) { this.Anticipation_Probability = actions[(int)code]; this.Anticipation_ActionCode = code; this.Anticipation_ActionTime = this.LastUpdateTime + t; changed = true; } } } if (changed) { Debug.Log("[AI] Anticipating player action " + this.Anticipation_ActionCode + " in " + (this.Anticipation_ActionTime - this.LastUpdateTime) + "s."); } }
/// <summary> /// Thinks the orders for AI characters. /// </summary> public void ThinkAction() { Debug.Assert(this.Characters.ContainsKey(AI_Params.PlayerID), "[AI] Invalid player ID (" + AI_Params.PlayerID + ")."); AI_Character player = this.Characters[AI_Params.PlayerID]; foreach (AI_Character c in this.Characters.Values) { if (!c.IsPlayer && c.IsAlive && c.IsIdle) { AI_DeepLearningNetwork network; float[] outputs; float[] actions = new float[(int)EActionCode.Count]; for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { actions[(int)code] = 0.0f; } for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { // Action network = this.Networks_Action[code]; outputs = network.Think(new float[] { Vector3.Distance(c.Position, player.Position), Vector3.Angle(c.Direction, player.Position - c.Position), Vector3.Angle(player.Direction, c.Position - player.Position) }, network.Variance); actions[(int)code] = outputs[0]; // Reaction if (player.CurrentAction != null) { network = this.Networks_Reaction[code][player.CurrentAction.ActionCode]; outputs = network.Think(new float[] { Vector3.Distance(c.Position, player.Position), Vector3.Angle(c.Direction, player.Position - c.Position), Vector3.Angle(player.Direction, c.Position - player.Position), this.LastUpdateTime - player.CurrentAction.CastTime }, network.Variance); actions[(int)code] = actions[(int)code] * outputs[0] - outputs[1]; } else { network = this.Networks_Reaction[code][this.Anticipation_ActionCode]; outputs = network.Think(new float[] { Vector3.Distance(c.Position, player.Position), Vector3.Angle(c.Direction, player.Position - c.Position), Vector3.Angle(player.Direction, c.Position - player.Position), this.LastUpdateTime - this.Anticipation_ActionTime }, network.Variance); actions[(int)code] = actions[(int)code] * outputs[0] - outputs[1]; } } // Choosing the best action float best_action_value = 0.0f; EActionCode best_action_code = EActionCode.ActionCodeNoAction; for (EActionCode code = EActionCode.ActionCodeNoAction; code < EActionCode.Count; code++) { if (best_action_value < actions[(int)code]) { best_action_value = actions[(int)code]; best_action_code = code; } } // Setting the new order switch (best_action_code) { case EActionCode.ActionCodeAttackLight: case EActionCode.ActionCodeAttackHeavy: case EActionCode.ActionCodeGuard: Debug.Log("[AI] Set order for character " + c.CharacterID + " : " + best_action_code + "."); AI_Orders.SetOrderForCharacter(c.CharacterID, best_action_code, c.Position, Vector3.Normalize(player.Position - c.Position)); break; case EActionCode.ActionCodeRoll: Debug.Log("[AI] Set order for character " + c.CharacterID + " : " + best_action_code + "."); float left_or_right = (UnityEngine.Random.value >= 0.5) ? 1.0f : -1.0f; Vector3 direction_player = Vector3.Normalize(player.Position - c.Position); Vector3 direction_roll = new Vector3(-direction_player.x, direction_player.y, direction_player.z) * left_or_right; AI_Orders.SetOrderForCharacter(c.CharacterID, best_action_code, c.Position, direction_roll); break; case EActionCode.ActionCodeNoAction: if (Vector3.Distance(player.Position, c.Position) < 100.0f) { Debug.Log("[AI] Set order for character " + c.CharacterID + " : " + best_action_code + " (stay in position)."); AI_Orders.SetOrderForCharacter(c.CharacterID, EActionCode.ActionCodeNoAction, c.Position, Vector3.Normalize(player.Position - c.Position)); } else { Debug.Log("[AI] Set order for character " + c.CharacterID + " : " + best_action_code + " (move towards player)."); AI_Orders.SetOrderForCharacter(c.CharacterID, EActionCode.ActionCodeNoAction, player.Position, Vector3.Normalize(player.Position - c.Position)); } break; } } } }