115 lines
3.5 KiB
C#
115 lines
3.5 KiB
C#
using System;
|
|
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
|
|
{
|
|
[HideInInspector]
|
|
public Character AgentCharacter;
|
|
public 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;
|
|
|
|
private void Awake()
|
|
{
|
|
DirectState = new NPC_DirectPointState();
|
|
CoverState = new NPC_InCoverState();
|
|
RunningState = new NPC_RunningState();
|
|
NPC_State = DirectState;
|
|
|
|
AgentCharacter = new Character();
|
|
Condition = AgentCharacter.Condition;
|
|
|
|
moveController = gameObject.GetComponent<MovementController>();
|
|
bufferSensor = gameObject.GetComponent<BufferSensorComponent>();
|
|
}
|
|
|
|
|
|
public void ResetCharacter()
|
|
{
|
|
Condition = new CharacterCondition();
|
|
EndEpisode();
|
|
}
|
|
|
|
public override void OnEpisodeBegin()
|
|
{
|
|
NPC_State = DirectState;
|
|
}
|
|
|
|
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)
|
|
{
|
|
var discreteActionsOut = actionsOut.DiscreteActions;
|
|
if (Input.GetKeyDown(KeyCode.W))
|
|
{
|
|
discreteActionsOut[0] = 1;
|
|
}
|
|
}
|
|
|
|
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");
|
|
}
|
|
}
|