Files
real-shooter/Assets/Scripts/Character/NPC.cs
Andrey Gumirov aae98595d3 Small fizes
2022-04-19 19:24:53 +07:00

123 lines
3.9 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)
{
var parray = 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
};
// var _parray = string.Join(" ", parray);
// Debug.Log("OBS: " + _parray);
bufferSensor.AppendObservation(parray);
}
}
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;
} else if (actions.DiscreteActions[0] == 2)
{
moveController.MoveToPointById(actions.DiscreteActions[1]);
}
}
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");
}
}