diff --git a/Assets/Scripts/Bots/CharacterFactory.cs b/Assets/Scripts/Bots/CharacterFactory.cs index e2c8be3..ab18289 100644 --- a/Assets/Scripts/Bots/CharacterFactory.cs +++ b/Assets/Scripts/Bots/CharacterFactory.cs @@ -25,10 +25,10 @@ public class CharacterFactory : MonoBehaviour private void Start() { - var attcNum = SettingsReader.Instance.GetSettings.numOfAttackers; - var defNum = SettingsReader.Instance.GetSettings.numOfDefenders; - var humanDef = SettingsReader.Instance.GetSettings.hasHumanDefender == true ? 1 : 0; - var humanAtc = SettingsReader.Instance.GetSettings.hasHumanAttacker == true ? 1 : 0; + var attcNum = SettingsReader.Instance.GetSettings.NumOfAttackers; + var defNum = SettingsReader.Instance.GetSettings.NumOfDefenders; + var humanDef = SettingsReader.Instance.GetSettings.HasHumanDefender == true ? 1 : 0; + var humanAtc = SettingsReader.Instance.GetSettings.HasHumanAttacker == true ? 1 : 0; if (humanAtc == 1 && humanDef == 1) throw new System.ArgumentException("Can be only one human player"); @@ -56,6 +56,10 @@ public class CharacterFactory : MonoBehaviour spawnPoint.position, Quaternion.identity); gameobject.SetActive(true); + if (team == Team.Attackers) + gameObject.tag = "Attacker"; + else + gameObject.tag = "Defender"; if (typeAi == TypeAI.HumanAI) { @@ -65,7 +69,7 @@ public class CharacterFactory : MonoBehaviour else { gameobject.GetComponent().GetCharacter.Team = team; - gameobject.GetComponent().currentPosition = spawnPoint; + gameobject.GetComponent().CurrentNavPoint = spawnPoint; Bots.Add(gameobject); } } @@ -81,8 +85,8 @@ public class CharacterFactory : MonoBehaviour else bot.transform.position = spawnPointsForDefendersTeam[Random.Range(0, spawnPointsForDefendersTeam.Count)].position; } - var player = Player.GetComponent(); - if (player != null) + Player player; + if (TryGetComponent(out player)) { player.ResetCharacter(); if (player.GetCharacter.Team == Team.Attackers) diff --git a/Assets/Scripts/Character/CharacterCondition.cs b/Assets/Scripts/Character/CharacterCondition.cs index d1ec569..b674222 100755 --- a/Assets/Scripts/Character/CharacterCondition.cs +++ b/Assets/Scripts/Character/CharacterCondition.cs @@ -21,6 +21,17 @@ public class CharacterCondition OnChangeHealthEvent?.Invoke(value); } } + + public int GetHealthPointsInQuantile() + { + if (health < 25) + return 0; + else if (health < 50) + return 1; + else if (health < 75) + return 2; + else return 3; + } private int armour; public int ArmourPoints { @@ -51,9 +62,9 @@ public class CharacterCondition public CharacterCondition() { var settings = SettingsReader.Instance.GetSettings; - ammo = settings.maxAmmo; - health = settings.maxHealth; - armour = settings.maxArmour; + ammo = settings.MaxAmmo; + health = settings.MaxHealth; + armour = settings.MaxArmour; } public void GiveHealth(int health) => HealthPoints = Mathf.Clamp(health + HealthPoints, 0, 100); diff --git a/Assets/Scripts/Character/MovementController.cs b/Assets/Scripts/Character/MovementController.cs index 20e1026..334b7d2 100644 --- a/Assets/Scripts/Character/MovementController.cs +++ b/Assets/Scripts/Character/MovementController.cs @@ -2,16 +2,31 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; +using System.Threading.Tasks; [RequireComponent(typeof(NavMeshAgent))] public class MovementController : MonoBehaviour { - public NavPoint currentPosition { get; set; } + public NavPoint CurrentNavPoint { get; set; } + public float FlagDistance { get; private set; } + private GameObject flag; + private const float updateFlagPositionDelay = 5; [SerializeField] private NavMeshAgent navMeshAgent; private void Start() { - navMeshAgent.speed = SettingsReader.Instance.GetSettings.movementSpeed; + navMeshAgent.speed = SettingsReader.Instance.GetSettings.MovementSpeed; + InvokeRepeating(nameof(UpdateFlagPosition), 0, updateFlagPositionDelay); + } + + private void OnDestroy() + { + CancelInvoke(nameof(UpdateFlagPosition)); + } + + private void UpdateFlagPosition() + { + FlagDistance = (flag.transform.position - gameObject.transform.position).magnitude; } public void MoveToRandomPoint() @@ -23,7 +38,7 @@ public class MovementController : MonoBehaviour public List getPointsCandidate() { return MapManager.navPoints - .Where(point => (currentPosition.position - point.position).magnitude < SettingsReader.Instance.GetSettings.movementSpeed) + .Where(point => (CurrentNavPoint.position - point.position).magnitude < SettingsReader.Instance.GetSettings.MovementSpeed) .ToList(); } diff --git a/Assets/Scripts/Character/NPC.cs b/Assets/Scripts/Character/NPC.cs index 1069d42..c738d0b 100644 --- a/Assets/Scripts/Character/NPC.cs +++ b/Assets/Scripts/Character/NPC.cs @@ -3,7 +3,6 @@ using UnityEngine; using Unity.MLAgents; using Unity.MLAgents.Sensors; using Unity.MLAgents.Actuators; -using System.Collections.Generic; [RequireComponent(typeof(MovementController))] public class NPC : Agent, ICharacter @@ -11,6 +10,7 @@ public class NPC : Agent, ICharacter [HideInInspector] public Character AgentCharacter; public CharacterCondition Condition; + private FlagZone flagZone; public NPC_BaseState NPC_State { get; private set; } @@ -47,29 +47,38 @@ public class NPC : Agent, ICharacter public override void OnEpisodeBegin() { NPC_State = DirectState; + flagZone = GameObject.FindObjectOfType(); } public override void CollectObservations(VectorSensor sensor) { + var candidates = moveController.getPointsCandidate(); + sensor.AddObservation(Condition.HealthPoints); sensor.AddObservation(Condition.ArmourPoints); sensor.AddObservation(Condition.Ammunition); sensor.AddObservation((int)NPC_State.State); - - var candidates = moveController.getPointsCandidate(); + sensor.AddObservation((!flagZone.isNotOccup).ToInt()); + sensor.AddObservation(AgentCharacter.LastTimeHit); + sensor.AddObservation(Condition.GetHealthPointsInQuantile()); + sensor.AddObservation(candidates.Count); + sensor.AddObservation(GameManager.IsEnemyNearby(gameObject.transform.position, AgentCharacter.Team)); + foreach (var point in candidates) { + Debug.Log((float)moveController.CurrentNavPoint.PointId); + bufferSensor.AppendObservation(new float[] { //1 position in navpointId - (float)moveController.currentPosition.PointId, + (float)moveController.CurrentNavPoint.PointId, //2 distance to flag - moveController.currentPosition.FlagDistance, + moveController.FlagDistance, //3 death count in point - moveController.currentPosition.DeathAttr, + moveController.CurrentNavPoint.DeathAttr, //4 flagEnemyDistance - GameManager.IsCloserToFlagFromNextNavPoint(point, transform.position)==true?1:0, + GameManager.IsCloserToFlagFromNextNavPoint(point, transform.position).ToInt(), //5 EnemyVsNavPointDistance - GameManager.IsCloserToEnemyThanToNextNavPoint(point,transform.position, AgentCharacter.Team)==true?1:0 + GameManager.IsCloserToEnemyThanToNextNavPoint(point,transform.position, AgentCharacter.Team).ToInt() }); } @@ -103,7 +112,7 @@ public class NPC : Agent, ICharacter if (Condition.HealthPoints < 0) { OnKilledEvent?.Invoke(this); - moveController.currentPosition.DeathAttr += 1; + moveController.CurrentNavPoint.DeathAttr += 1; } } diff --git a/Assets/Scripts/Managers/GameManager.cs b/Assets/Scripts/Managers/GameManager.cs index 54d1e1d..b91908d 100755 --- a/Assets/Scripts/Managers/GameManager.cs +++ b/Assets/Scripts/Managers/GameManager.cs @@ -51,6 +51,20 @@ public class GameManager : MonoBehaviour return false; } + public static bool IsEnemyNearby(Vector3 currentTransform, Team team) + { + SimpleMultiAgentGroup agentGroup; + if (team == Team.Attackers) + agentGroup = AttackersTeam; + else + agentGroup = DefendersTeam; + + foreach (var agent in agentGroup.GetRegisteredAgents()) + if ((currentTransform - agent.transform.position).magnitude < SettingsReader.Instance.GetSettings.ViewDistance) + return true; + return false; + } + public static bool IsCloserToFlagFromNextNavPoint(NavPoint navPoint, Vector3 currentTransform) => navPoint.FlagDistance < (currentTransform - GameObject.FindGameObjectWithTag("Flag").transform.position).magnitude; diff --git a/Assets/Scripts/Misc/FlagZone.cs b/Assets/Scripts/Misc/FlagZone.cs index 8cd4ab4..c6328dd 100755 --- a/Assets/Scripts/Misc/FlagZone.cs +++ b/Assets/Scripts/Misc/FlagZone.cs @@ -9,14 +9,14 @@ public class FlagZone : MonoBehaviour public float TimeStayDefenders { get; private set; } private int occupDefenders; private int occupAttackers; - private bool isOccupBoth => (occupDefenders>0) && (occupAttackers>0); - private bool isNotOccup => (occupDefenders == 0) && (occupAttackers == 0); + public bool isOccupBoth => (occupDefenders>0) && (occupAttackers>0); + public bool isNotOccup => (occupDefenders == 0) && (occupAttackers == 0); private float timeForWin; private void Start() { - timeForWin = SettingsReader.Instance.GetSettings.timeToWin; + timeForWin = SettingsReader.Instance.GetSettings.TimeToWin; TimeStayAttackers = 0; TimeStayDefenders = 0; occupAttackers = 0; diff --git a/Assets/Scripts/Misc/Settings.cs b/Assets/Scripts/Misc/Settings.cs index e01abc1..b1b7ea8 100755 --- a/Assets/Scripts/Misc/Settings.cs +++ b/Assets/Scripts/Misc/Settings.cs @@ -3,30 +3,32 @@ [CreateAssetMenu(fileName ="Game Settings", menuName = "Game/Settings", order = 51)] public class Settings : ScriptableObject { - public bool isTesting; + public bool IsTesting; - public float timeToWin; - public float timeOut; + public float TimeToWin; + public float TimeOut; [Header("movement")] - public float movementDistance; - public float movementSpeed; + public float MovementDistance; + public float MovementSpeed; - public TypeAI defTeamAI; - public TypeAI atcTeamAI; - public int numOfDefenders; - public int numOfAttackers; - public bool hasHumanDefender; - public bool hasHumanAttacker; + public TypeAI DefTeamAI; + public TypeAI AtcTeamAI; + public int NumOfDefenders; + public int NumOfAttackers; + public bool HasHumanDefender; + public bool HasHumanAttacker; - public int healthPickupAmount; - public int armourPickupAmount; - public int ammunitionPickupAmount; - public int pickupsAmount; + public int HealthPickupAmount; + public int ArmourPickupAmount; + public int AmmunitionPickupAmount; + public int PickupsAmount; - public int maxHealth; - public int maxArmour; - public int maxAmmo; + public int MaxHealth; + public int MaxArmour; + public int MaxAmmo; + + public float ViewDistance; public float GetHitChanceInDirectPoint; public float GetHitChanceInRunning; diff --git a/Assets/Scripts/Pickups/AmmoPickUp.cs b/Assets/Scripts/Pickups/AmmoPickUp.cs index 506598d..8439c21 100755 --- a/Assets/Scripts/Pickups/AmmoPickUp.cs +++ b/Assets/Scripts/Pickups/AmmoPickUp.cs @@ -13,7 +13,7 @@ public class AmmoPickUp : MonoBehaviour, IPickable public void PickObject(GameObject obj) { - obj.GetComponent()?.GetCharacter.Condition.TakeAmmo(SettingsReader.Instance.GetSettings.ammunitionPickupAmount); + obj.GetComponent()?.GetCharacter.Condition.TakeAmmo(SettingsReader.Instance.GetSettings.AmmunitionPickupAmount); gameObject.SetActive(false); } } diff --git a/Assets/Scripts/Pickups/ArmourPickUp.cs b/Assets/Scripts/Pickups/ArmourPickUp.cs index 86be289..c68e491 100755 --- a/Assets/Scripts/Pickups/ArmourPickUp.cs +++ b/Assets/Scripts/Pickups/ArmourPickUp.cs @@ -13,7 +13,7 @@ public class ArmourPickUp : MonoBehaviour, IPickable public void PickObject(GameObject obj) { - obj.GetComponent()?.GetCharacter.Condition.GiveArmour(SettingsReader.Instance.GetSettings.armourPickupAmount); + obj.GetComponent()?.GetCharacter.Condition.GiveArmour(SettingsReader.Instance.GetSettings.ArmourPickupAmount); gameObject.SetActive(false); } } diff --git a/Assets/Scripts/Pickups/HealthPickUp.cs b/Assets/Scripts/Pickups/HealthPickUp.cs index f92345a..36f81ba 100755 --- a/Assets/Scripts/Pickups/HealthPickUp.cs +++ b/Assets/Scripts/Pickups/HealthPickUp.cs @@ -13,7 +13,7 @@ public class HealthPickUp : MonoBehaviour, IPickable public void PickObject(GameObject obj) { - obj.GetComponent()?.GetCharacter.Condition.GiveHealth(SettingsReader.Instance.GetSettings.healthPickupAmount); + obj.GetComponent()?.GetCharacter.Condition.GiveHealth(SettingsReader.Instance.GetSettings.HealthPickupAmount); gameObject.SetActive(false); } } diff --git a/Assets/Scripts/Pickups/PickUpSpawner.cs b/Assets/Scripts/Pickups/PickUpSpawner.cs index 945c1d3..7a29705 100755 --- a/Assets/Scripts/Pickups/PickUpSpawner.cs +++ b/Assets/Scripts/Pickups/PickUpSpawner.cs @@ -27,7 +27,7 @@ public class PickUpSpawner : MonoBehaviour private void Start() { pickups = new List(); - var amount = SettingsReader.Instance.GetSettings.pickupsAmount; + var amount = SettingsReader.Instance.GetSettings.PickupsAmount; for (int i = 0; i < amount; i++) pickups.Add(GameObject.Instantiate(healthPrefab, spawnPoints[Random.Range(0, spawnPoints.Count)].transform.position, Quaternion.identity)); for (int i = 0; i < amount; i++) diff --git a/Assets/Scripts/Utils/BoolToInteger.cs b/Assets/Scripts/Utils/BoolToInteger.cs new file mode 100644 index 0000000..0d8090a --- /dev/null +++ b/Assets/Scripts/Utils/BoolToInteger.cs @@ -0,0 +1,7 @@ +public static class BoolExtension +{ + public static int ToInt(this bool _bool) + { + return _bool == true ? 1 : 0; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Utils/BoolToInteger.cs.meta b/Assets/Scripts/Utils/BoolToInteger.cs.meta new file mode 100644 index 0000000..3688775 --- /dev/null +++ b/Assets/Scripts/Utils/BoolToInteger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f48fff3c2eda14d4fba923fe8875f651 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: