latest changes
This commit is contained in:
59
Assets/Scripts/Bots/CharacterFactory.cs
Normal file
59
Assets/Scripts/Bots/CharacterFactory.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Unity;
|
||||
|
||||
public class CharacterFactory : MonoBehaviour
|
||||
{
|
||||
private CharacterFactory instance;
|
||||
public CharacterFactory Instance { get { return instance; } }
|
||||
|
||||
[SerializeField] private List<NavPoint> spawnPointsForDefendersTeam;
|
||||
[SerializeField] private List<NavPoint> spawnPointsForAttackersTeam;
|
||||
[SerializeField] private GameObject AIPrefab;
|
||||
[SerializeField] private GameObject PlayerPrefab;
|
||||
|
||||
private List<GameObject> Players;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = this;
|
||||
else
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (humanAtc == 1 && humanDef == 1)
|
||||
throw new System.ArgumentException("Can be only one human player");
|
||||
|
||||
for (int i = 0; i < attcNum - humanAtc; i++)
|
||||
InstanciateEntity(Team.Attackers, TypeAI.D0DiskAI,
|
||||
spawnPointsForAttackersTeam[Random.Range(0, spawnPointsForAttackersTeam.Count)]);
|
||||
for (int i = 0; i < defNum - humanDef; i++)
|
||||
InstanciateEntity(Team.Defenders, TypeAI.D0DiskAI,
|
||||
spawnPointsForDefendersTeam[Random.Range(0, spawnPointsForDefendersTeam.Count)]);
|
||||
if (humanAtc == 1)
|
||||
InstanciateEntity(Team.Attackers, TypeAI.HumanAI,
|
||||
spawnPointsForAttackersTeam[Random.Range(0, spawnPointsForAttackersTeam.Count)]);
|
||||
if (humanDef == 1)
|
||||
InstanciateEntity(Team.Defenders, TypeAI.HumanAI,
|
||||
spawnPointsForDefendersTeam[Random.Range(0, spawnPointsForDefendersTeam.Count)]);
|
||||
}
|
||||
|
||||
private void InstanciateEntity(Team team, TypeAI typeAi, NavPoint spawnPoint)
|
||||
{
|
||||
var gameobject = GameObject.Instantiate(
|
||||
typeAi == TypeAI.HumanAI ? PlayerPrefab : AIPrefab,
|
||||
spawnPoint.position,
|
||||
Quaternion.identity);
|
||||
|
||||
var character = gameObject.GetComponent<ICharacter>();
|
||||
character.GetCharacter.Team = team;
|
||||
}
|
||||
}
|
0
Assets/Scripts/Bots/CharacterPooler.cs.meta → Assets/Scripts/Bots/CharacterFactory.cs.meta
generated
Executable file → Normal file
0
Assets/Scripts/Bots/CharacterPooler.cs.meta → Assets/Scripts/Bots/CharacterFactory.cs.meta
generated
Executable file → Normal file
@ -1,4 +0,0 @@
|
||||
public class CharacterPooler
|
||||
{
|
||||
|
||||
}
|
22
Assets/Scripts/Character/Character.cs
Normal file
22
Assets/Scripts/Character/Character.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
public class Character
|
||||
{
|
||||
public Team Team { get; set; }
|
||||
public float LastTimeHit = 0;
|
||||
public CharacterCondition Condition;
|
||||
|
||||
public Character()
|
||||
{
|
||||
Condition = new CharacterCondition();
|
||||
}
|
||||
|
||||
public void ResetCharacter()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICharacter
|
||||
{
|
||||
Character GetCharacter { get; }
|
||||
}
|
11
Assets/Scripts/Character/Character.cs.meta
generated
Normal file
11
Assets/Scripts/Character/Character.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44d6a17ad31b31241928e1a17e9aba37
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,12 +1,6 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public enum NPCState
|
||||
{
|
||||
InCover,
|
||||
InBlancPoint,
|
||||
InRunning,
|
||||
}
|
||||
|
||||
public class CharacterCondition
|
||||
{
|
||||
@ -54,9 +48,6 @@ public class CharacterCondition
|
||||
}
|
||||
}
|
||||
|
||||
[HideInInspector]
|
||||
public NPCState npcState { get; private set; }
|
||||
|
||||
public CharacterCondition()
|
||||
{
|
||||
var settings = SettingsReader.Instance.GetSettings;
|
||||
|
@ -14,27 +14,19 @@ public class MovementController : MonoBehaviour
|
||||
navMeshAgent.speed = SettingsReader.Instance.GetSettings.movementSpeed;
|
||||
}
|
||||
|
||||
public void Move()
|
||||
{
|
||||
var pointCandidate = getPointCandidate();
|
||||
goToNextNavPoint(pointCandidate);
|
||||
}
|
||||
|
||||
public void MoveToRandomPoint()
|
||||
{
|
||||
Debug.Log(MapManager.navPoints == null);
|
||||
goToNextNavPoint(MapManager.navPoints[Random.Range(0, MapManager.navPoints.Count)]);
|
||||
}
|
||||
|
||||
private NavPoint getPointCandidate()
|
||||
public List<NavPoint> getPointsCandidate()
|
||||
{
|
||||
var NavPointsPositions = MapManager.navPoints
|
||||
.Select(point => point.transform.position)
|
||||
.Where(point => (currentPosition.transform.position - point).magnitude <= SettingsReader.Instance.GetSettings.movementSpeed)
|
||||
return MapManager.navPoints
|
||||
.Where(point => (currentPosition.position - point.position).magnitude <= SettingsReader.Instance.GetSettings.movementSpeed)
|
||||
.ToList();
|
||||
return null;
|
||||
}
|
||||
|
||||
public void goToNextNavPoint(NavPoint destination) =>
|
||||
navMeshAgent.SetDestination(destination.transform.position);
|
||||
navMeshAgent.SetDestination(destination.position);
|
||||
}
|
||||
|
@ -3,27 +3,50 @@ using UnityEngine;
|
||||
using Unity.MLAgents;
|
||||
using Unity.MLAgents.Sensors;
|
||||
using Unity.MLAgents.Actuators;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[RequireComponent(typeof(MovementController))]
|
||||
public class NPC : Agent
|
||||
public class NPC : Agent, ICharacter
|
||||
{
|
||||
public Team Team { get; set; }
|
||||
|
||||
[HideInInspector]
|
||||
private float LastTimeHit;
|
||||
public Character AgentCharacter;
|
||||
public CharacterCondition Condition;
|
||||
|
||||
public MovementController moveController;
|
||||
|
||||
public NPC_BaseState NPC_State { get; private set; }
|
||||
|
||||
public Character GetCharacter => AgentCharacter;
|
||||
|
||||
private NPC_DirectPointState DirectState;
|
||||
private NPC_InCoverState CoverState;
|
||||
private NPC_RunningState RunningState;
|
||||
|
||||
private MovementController moveController;
|
||||
private BufferSensorComponent bufferSensor;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
DirectState = new NPC_DirectPointState();
|
||||
CoverState = new NPC_InCoverState();
|
||||
RunningState = new NPC_RunningState();
|
||||
NPC_State = DirectState;
|
||||
|
||||
AgentCharacter = new Character();
|
||||
Condition = AgentCharacter.Condition;
|
||||
}
|
||||
private void Start()
|
||||
{
|
||||
Condition = new CharacterCondition();
|
||||
AgentCharacter = new Character();
|
||||
Condition = AgentCharacter.Condition;
|
||||
|
||||
moveController = gameObject.GetComponent<MovementController>();
|
||||
bufferSensor = gameObject.GetComponent<BufferSensorComponent>();
|
||||
|
||||
GameManager.OnResetScene += AgentCharacter.ResetCharacter;
|
||||
}
|
||||
|
||||
public override void OnEpisodeBegin()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void CollectObservations(VectorSensor sensor)
|
||||
@ -31,7 +54,28 @@ public class NPC : Agent
|
||||
sensor.AddObservation(Condition.HealthPoints);
|
||||
sensor.AddObservation(Condition.ArmourPoints);
|
||||
sensor.AddObservation(Condition.Ammunition);
|
||||
sensor.AddObservation((int)Condition.npcState);
|
||||
sensor.AddObservation((int)NPC_State.State);
|
||||
|
||||
|
||||
|
||||
var candidates = moveController.getPointsCandidate();
|
||||
foreach (var point in candidates)
|
||||
{
|
||||
|
||||
bufferSensor.AppendObservation(new float[] {
|
||||
//1 position in navpointId
|
||||
(float)moveController.currentPosition.PointId,
|
||||
//2 distance to flag
|
||||
moveController.currentPosition.FlagDistance,
|
||||
//3 death count in point
|
||||
moveController.currentPosition.DeathAttr,
|
||||
//4 flagEnemyDistance
|
||||
GameManager.IsCloserToFlagFromNextNavPoint(point, transform.position)==true?1:0,
|
||||
//5 EnemyVsNavPointDistance
|
||||
GameManager.IsCloserToEnemyThanToNextNavPoint(point,transform.position, AgentCharacter.Team)==true?1:0
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override void Heuristic(in ActionBuffers actionsOut)
|
||||
@ -46,16 +90,28 @@ public class NPC : Agent
|
||||
public override void OnActionReceived(ActionBuffers actions)
|
||||
{
|
||||
if (actions.DiscreteActions[0] == 1)
|
||||
{
|
||||
moveController.MoveToRandomPoint();
|
||||
NPC_State = RunningState;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<object> OnKilledEvent;
|
||||
public void GetDamage(float damage)
|
||||
{
|
||||
AgentCharacter.LastTimeHit = TimeManager.Instance.CurrentTime;
|
||||
Condition.GiveHealth(-Mathf.RoundToInt(damage * (1 - Condition.ArmourPoints * 0.5f)));
|
||||
Condition.GiveArmour(-Mathf.RoundToInt(Mathf.Sqrt(damage) * 5));
|
||||
|
||||
if (Condition.HealthPoints < 0)
|
||||
{
|
||||
OnKilledEvent?.Invoke(this);
|
||||
moveController.currentPosition.DeathAttr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Debug.LogWarning("Pooled object was destroyed");
|
||||
}
|
||||
}
|
||||
|
46
Assets/Scripts/Character/NPC_State.cs
Normal file
46
Assets/Scripts/Character/NPC_State.cs
Normal file
@ -0,0 +1,46 @@
|
||||
public enum NPC_EnumState
|
||||
{
|
||||
InCover,
|
||||
InDirectPoint,
|
||||
InRunning,
|
||||
}
|
||||
|
||||
public interface NPC_BaseState
|
||||
{
|
||||
NPC_EnumState State { get; }
|
||||
bool InCover { get; }
|
||||
bool IsRunning { get; }
|
||||
bool InDirectPoint { get; }
|
||||
float HitChance { get; }
|
||||
float DoDamageChance { get; }
|
||||
}
|
||||
|
||||
public class NPC_DirectPointState : NPC_BaseState
|
||||
{
|
||||
public bool InCover => false;
|
||||
public bool IsRunning => false;
|
||||
public bool InDirectPoint => false;
|
||||
public float HitChance => SettingsReader.Instance.GetSettings.GetHitChanceInDirectPoint;
|
||||
public float DoDamageChance => SettingsReader.Instance.GetSettings.DoDamageChanceInDirectPoint;
|
||||
public NPC_EnumState State => NPC_EnumState.InDirectPoint;
|
||||
}
|
||||
|
||||
public class NPC_RunningState : NPC_BaseState
|
||||
{
|
||||
public bool InCover => false;
|
||||
public bool IsRunning => true;
|
||||
public bool InDirectPoint => false;
|
||||
public float HitChance => SettingsReader.Instance.GetSettings.GetHitChanceInRunning;
|
||||
public float DoDamageChance => SettingsReader.Instance.GetSettings.DoDamageChanceInRunning;
|
||||
public NPC_EnumState State => NPC_EnumState.InRunning;
|
||||
}
|
||||
|
||||
public class NPC_InCoverState : NPC_BaseState
|
||||
{
|
||||
public bool InCover => true;
|
||||
public bool IsRunning => false;
|
||||
public bool InDirectPoint => false;
|
||||
public float HitChance => SettingsReader.Instance.GetSettings.GetHitChanceInCover;
|
||||
public float DoDamageChance => SettingsReader.Instance.GetSettings.DoDamageChanceInCover;
|
||||
public NPC_EnumState State => NPC_EnumState.InCover;
|
||||
}
|
11
Assets/Scripts/Character/NPC_State.cs.meta
generated
Normal file
11
Assets/Scripts/Character/NPC_State.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a192e433e26797745ad0b46de2586de3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
34
Assets/Scripts/Character/Player.cs
Normal file
34
Assets/Scripts/Character/Player.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class Player : MonoBehaviour, ICharacter
|
||||
{
|
||||
[HideInInspector]
|
||||
public Character PlayerCharacter;
|
||||
public CharacterCondition Condition;
|
||||
|
||||
public Character GetCharacter => PlayerCharacter;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
PlayerCharacter = new Character();
|
||||
Condition = PlayerCharacter.Condition;
|
||||
GameManager.OnResetScene += PlayerCharacter.ResetCharacter;
|
||||
}
|
||||
|
||||
public event Action<object> OnKilledEvent;
|
||||
public void GetDamage(float damage)
|
||||
{
|
||||
PlayerCharacter.LastTimeHit = TimeManager.Instance.CurrentTime;
|
||||
Condition.GiveHealth(-Mathf.RoundToInt(damage * (1 - Condition.ArmourPoints * 0.5f)));
|
||||
Condition.GiveArmour(-Mathf.RoundToInt(Mathf.Sqrt(damage) * 5));
|
||||
|
||||
if (Condition.HealthPoints < 0)
|
||||
OnKilledEvent?.Invoke(this);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Debug.LogWarning("Pooled object was destroyed");
|
||||
}
|
||||
}
|
11
Assets/Scripts/Character/Player.cs.meta
generated
Normal file
11
Assets/Scripts/Character/Player.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8c9a8e604d395c4ab9d03d28adc4982
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,14 +1,14 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditorInternal;
|
||||
using Unity.MLAgents;
|
||||
using UnityEngine;
|
||||
|
||||
public class GameManager : MonoBehaviour
|
||||
{
|
||||
|
||||
private static GameManager instance;
|
||||
public static GameManager Instance { get { return instance; } }
|
||||
|
||||
private static SimpleMultiAgentGroup DefendersTeam = new SimpleMultiAgentGroup();
|
||||
private static SimpleMultiAgentGroup AttackersTeam = new SimpleMultiAgentGroup();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance == null)
|
||||
@ -21,13 +21,36 @@ public class GameManager : MonoBehaviour
|
||||
{
|
||||
GlobalEventManager.onCaptureFlag += flagCaptured;
|
||||
GlobalEventManager.onTimeLeft += timeOut;
|
||||
|
||||
var agents = GameObject.FindObjectsOfType<Agent>();
|
||||
foreach (var item in agents)
|
||||
{
|
||||
var agent = item as NPC;
|
||||
if (agent.GetCharacter.Team == Team.Attackers)
|
||||
AttackersTeam.RegisterAgent(agent);
|
||||
else
|
||||
DefendersTeam.RegisterAgent(agent);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
public static bool IsCloserToEnemyThanToNextNavPoint(NavPoint navPoint, Vector3 currentTransform, Team team)
|
||||
{
|
||||
|
||||
SimpleMultiAgentGroup agentGroup;
|
||||
if (team == Team.Attackers)
|
||||
agentGroup = AttackersTeam;
|
||||
else
|
||||
agentGroup = DefendersTeam;
|
||||
|
||||
var distToNavPoint = (currentTransform - navPoint.position).magnitude;
|
||||
foreach (var agent in agentGroup.GetRegisteredAgents())
|
||||
if (distToNavPoint > (currentTransform - agent.transform.position).magnitude)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsCloserToFlagFromNextNavPoint(NavPoint navPoint, Vector3 currentTransform)
|
||||
=> navPoint.FlagDistance < (currentTransform - GameObject.FindGameObjectWithTag("Flag").transform.position).magnitude;
|
||||
|
||||
private void flagCaptured(Team team)
|
||||
{
|
||||
switch(team)
|
||||
|
@ -6,12 +6,14 @@ public class MapManager : MonoBehaviour
|
||||
public static List<NavPoint> navPoints { get; private set; }
|
||||
private void Start()
|
||||
{
|
||||
var i = 0;
|
||||
navPoints = new List<NavPoint>();
|
||||
var navPointsGameObj = GameObject.FindGameObjectsWithTag("Point");
|
||||
foreach (var gameobj in navPointsGameObj)
|
||||
{
|
||||
Debug.Log(" a ");
|
||||
navPoints.Add(gameobj.GetComponent<NavPoint>());
|
||||
var navpoint = gameobj.GetComponent<NavPoint>();
|
||||
navpoint.PointId = i; i++;
|
||||
navPoints.Add(navpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,10 @@ using UnityEngine;
|
||||
|
||||
public class TimeManager : MonoBehaviour
|
||||
{
|
||||
public static TimeManager instance = null;
|
||||
public float CurrentTime;
|
||||
private static TimeManager instance;
|
||||
public static TimeManager Instance { get { return instance; } }
|
||||
|
||||
public float CurrentTime { get; private set; }
|
||||
void Start()
|
||||
{
|
||||
if (instance == null)
|
||||
|
@ -6,22 +6,15 @@ public class NavPoint : MonoBehaviour
|
||||
{
|
||||
public Vector3 position => gameObject.transform.position;
|
||||
public float FlagDistance { get; private set; }
|
||||
[System.NonSerialized] public float DeathAttr;
|
||||
[System.NonSerialized] public List<Vector3> EnemiesSeen;
|
||||
|
||||
[HideInInspector]
|
||||
public int? PointId;
|
||||
public float DeathAttr = 0;
|
||||
public List<Vector3> EnemiesSeen = new List<Vector3>();
|
||||
//Here other attributes;
|
||||
|
||||
[SerializeField]
|
||||
public int PointId;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
//DO NOT DELETE
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
FlagDistance = (GameObject.FindGameObjectWithTag("Flag").transform.position - position).magnitude;
|
||||
EnemiesSeen = new List<Vector3>();
|
||||
DeathAttr = 0;
|
||||
FlagDistance = (GameObject.FindGameObjectWithTag("Flag").transform.position - position).magnitude;
|
||||
}
|
||||
}
|
||||
|
@ -27,4 +27,11 @@ public class Settings : ScriptableObject
|
||||
public int maxHealth;
|
||||
public int maxArmour;
|
||||
public int maxAmmo;
|
||||
|
||||
public float GetHitChanceInDirectPoint;
|
||||
public float GetHitChanceInRunning;
|
||||
public float GetHitChanceInCover;
|
||||
public float DoDamageChanceInDirectPoint;
|
||||
public float DoDamageChanceInRunning;
|
||||
public float DoDamageChanceInCover;
|
||||
}
|
||||
|
@ -16,6 +16,14 @@ public class PickUpSpawner : MonoBehaviour
|
||||
|
||||
[SerializeField] private List<NavPoint> spawnPoints;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = this;
|
||||
else
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
pickups = new List<GameObject>();
|
||||
|
Reference in New Issue
Block a user