Files
real-shooter/Assets/Scripts/Character/NPC.cs
2022-05-09 22:43:31 +07:00

125 lines
3.7 KiB
C#

using System;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
using Unity.MLAgents.Actuators;
using System.Collections.Generic;
using JetBrains.Annotations;
[RequireComponent(typeof(MovementController))]
public class NPC : Agent, ICharacter
{
private Character AgentCharacter;
private CharacterCondition Condition;
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;
[SerializeField] [NotNull]
private NavPoint DumbAIDestination;
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()
{
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)
{
sensor.AddObservation(Condition.HealthPoints);
sensor.AddObservation(Condition.ArmourPoints);
sensor.AddObservation(Condition.Ammunition);
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)
{
moveController.goToNextNavPoint(DumbAIDestination);
}
public void DumbAIAction()
{
}
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");
}
}