ai settings, autoaim,

This commit is contained in:
dddushesss 2022-01-17 13:01:19 +03:00
parent 3304c858d0
commit 2183deb840
16 changed files with 179 additions and 115 deletions

View File

@ -0,0 +1,19 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 39f9814b967541eeaf31ef497d721a87, type: 3}
m_Name: AIData
m_EditorClassIdentifier:
_distanceToAgr: 6
_percentToRetreet: 0.25
_percentToUseProtectBonus: 0.25
_manaPercentToCollectBonus: 0.4
_distaceToCollectBonus: 3

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7d4b05a041108bc409b1126fa890ed12
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -19,4 +19,5 @@ MonoBehaviour:
uiDataPath: UIData
musicDataPath: MusicData
itemDataPath: ItemData
aiDataPath: AIData
chosenWeaponDataPath: ChosenWeapon.json

View File

@ -13,26 +13,25 @@ namespace DefaultNamespace.AI
{
public class AIAgent : IFixedExecute, IExecute
{
private Unit _enemy;
private Unit _unit;
private Camera _camera;
private AIManager _manager;
private BotState curentState;
public Queue<HexDirection> currentPath;
public Action<AIAgent> OnAgentInited;
private Vector2 _attackDirection;
public Unit Enemy => _enemy;
public Unit Unit => _unit;
public BotState CurentState => curentState;
public AIAgent(UnitInfo enemyInfo, Unit enemy, AIManager manager)
public AIAgent(UnitInfo enemyInfo, Unit unit)
{
currentPath = new Queue<HexDirection>();
_enemy = enemy;
_unit = unit;
_camera = Camera.main;
_enemy.OnDeath += AgentDeath;
enemy.onPlayerSpawned += InitAgent;
_manager = manager;
_unit.OnDeath += AgentDeath;
unit.onPlayerSpawned += InitAgent;
}
@ -44,7 +43,7 @@ namespace DefaultNamespace.AI
private void InitAgent(GameObject unit)
{
_manager.AddAgent(this);
AIManager.Instance.AddAgent(this);
HexManager.agents.Add(unit, this);
OnAgentInited?.Invoke(this);
}
@ -57,33 +56,33 @@ namespace DefaultNamespace.AI
public void FixedExecute()
{
if (curentState == BotState.Attack && !_enemy.IsBusy)
if (curentState == BotState.Attack && !_unit.IsBusy)
{
_enemy.Aim(_attackDirection);
_enemy.StartAttack();
curentState = _manager.GetNewBehaviour(this);
_unit.Aim(_attackDirection);
_unit.StartAttack();
curentState = AIManager.Instance.GetNewBehaviour(this);
}
if (currentPath.Count > 0 && !_enemy.IsBusy)
if (currentPath.Count > 0 && !_unit.IsBusy)
{
var dir = currentPath.Dequeue();
while (HexManager.UnitCurrentCell[_enemy.Color].cell.GetNeighbor(dir) == null)
while (HexManager.UnitCurrentCell[_unit.Color].cell.GetNeighbor(dir) == null)
{
dir = dir.PlusSixtyDeg();
}
_enemy.Move(dir);
_unit.Move(dir);
}
if(currentPath.Count == 0 && !_enemy.IsBusy)
if(currentPath.Count == 0 && !_unit.IsBusy)
{
curentState = _manager.GetNewBehaviour(this);
curentState = AIManager.Instance.GetNewBehaviour(this);
}
}
public void Execute()
{
if (_enemy.UnitView != null)
if (_unit.UnitView != null)
{
_enemy.UnitView.BarCanvas.transform.DOLookAt(
_enemy.UnitView.BarCanvas.transform.position + _camera.transform.rotation * Vector3.back, 0f,
_unit.UnitView.BarCanvas.transform.DOLookAt(
_unit.UnitView.BarCanvas.transform.position + _camera.transform.rotation * Vector3.back, 0f,
up: _camera.transform.rotation * Vector3.up);
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Controller;
using Data;
using DefaultNamespace;
using DefaultNamespace.AI;
using HexFiled;
@ -20,6 +21,7 @@ namespace AI
private List<AIAgent> _agents;
private int _triesToCalculatePath = 0;
private int _maxTriesToCalculatePath = 5;
private AIData _data;
private static AIManager _instance;
@ -30,17 +32,11 @@ namespace AI
private set => _instance ??= value;
}
public AIManager(List<AIAgent> agents)
{
_agents = agents;
agents.ForEach(agent => { SetBehaviour(BotState.Patrol, agent); });
}
public AIManager()
public AIManager(AIData data)
{
_agents = new List<AIAgent>();
_data = data;
Instance = this;
HexManager.agents = new Dictionary<GameObject, AIAgent>();
}
@ -65,38 +61,48 @@ namespace AI
private void StartPatrolBehaviour(AIAgent agent)
{
HexManager.GetNearestDifferCell(agent.Enemy.Color, agent.currentPath);
HexManager.GetNearestDifferCell(agent.Unit.Color, agent.currentPath);
while (agent.currentPath.Count == 0 && _triesToCalculatePath < _maxTriesToCalculatePath)
{
HexManager.GetNearestDifferCell(agent.Enemy.Color, agent.currentPath);
HexManager.GetNearestDifferCell(agent.Unit.Color, agent.currentPath);
_triesToCalculatePath++;
}
_triesToCalculatePath = 0;
}
private Unit GetNearestUnit(int cellDist, AIAgent agent)
public static Unit GetNearestUnit(int cellDist, Unit agent)
{
return (from unit in HexManager.UnitCurrentCell
where unit.Key != agent.Enemy.Color &&
where unit.Key != agent.Color &&
Vector3.Distance(unit.Value.unit.Instance.transform.position,
agent.Enemy.Instance.transform.position) <= cellDist * HexGrid.HexDistance
agent.Instance.transform.position) <= cellDist * HexGrid.HexDistance
select unit.Value.unit).FirstOrDefault();
}
public BotState GetNewBehaviour(AIAgent agent)
{
var attack = agent.Enemy.Inventory.Where(x => x is Bonus { Type: BonusType.Attack }).ToList();
if (agent.CurentState is BotState.Attack && agent.Enemy.AttackBonus == 0 && attack.Count > 0)
var attack = agent.Unit.Inventory.Where(x => x is Bonus { Type: BonusType.Attack }).ToList();
if (agent.CurentState is BotState.Attack && agent.Unit.AttackBonus == 0 && attack.Count > 0)
{
SetBehaviour(BotState.AttackBonusUsage, agent);
return BotState.AttackBonusUsage;
}
var enemy = GetNearestUnit(6, agent);
if (enemy != null && agent.Enemy.Hp > agent.Enemy.Data.maxHP / 4 && enemy.IsAlive)
var enemy = GetNearestUnit(_data.DistanceToAgr, agent.Unit);
if (enemy != null && agent.Unit.Hp > agent.Unit.Data.maxHP * _data.PercentToRetreet && enemy.IsAlive)
{
if (Vector3.Distance(agent.Enemy.Instance.transform.position, enemy.Instance.transform.position) < 4)
if (agent.Unit.Hp <= agent.Unit.Data.maxHP * _data.PercentToRetreet ||
agent.Unit.UnitView.AvailableShots == 0)
{
SetBehaviour(BotState.Retreet, agent);
return BotState.Retreet;
}
if (Vector3.Distance(agent.Unit.Instance.transform.position, enemy.Instance.transform.position) <=
agent.Unit.Weapon.disnatce)
{
SetBehaviour(BotState.Attack, agent);
return BotState.Attack;
@ -106,25 +112,23 @@ namespace AI
return BotState.Agressive;
}
if (agent.Enemy.Mana <= agent.Enemy.Data.maxMana / 3 &&
agent.Enemy.Inventory.Count < agent.Enemy.InventoryCapacity)
var item = GetNearestItem(agent);
if (((item.dist > 0 && item.dist <= _data.DistaceToCollectBonus) ||
agent.Unit.Mana <= agent.Unit.Data.maxMana * _data.ManaPercentToCollectBonus) &&
agent.Unit.Inventory.Count < agent.Unit.InventoryCapacity)
{
SetBehaviour(BotState.CollectingBonus, agent);
return BotState.CollectingBonus;
}
var protect = agent.Enemy.Inventory.Where(x => x is Bonus { Type: BonusType.Defence }).ToList();
if (protect.Count > 0 && agent.Enemy.Hp <= agent.Enemy.Data.maxHP / 4 && agent.Enemy.DefenceBonus == 0)
var protect = agent.Unit.Inventory.Where(x => x is Bonus { Type: BonusType.Defence }).ToList();
if (protect.Count > 0 && agent.Unit.Hp <= agent.Unit.Data.maxHP * _data.PercentToUseProtectBonus &&
agent.Unit.DefenceBonus == 0)
{
SetBehaviour(BotState.ProtectBonusUsage, agent);
return BotState.ProtectBonusUsage;
}
if (agent.Enemy.Hp <= agent.Enemy.Data.maxHP / 4 && GetNearestUnit(5, agent) != null)
{
SetBehaviour(BotState.Retreet, agent);
return BotState.Retreet;
}
SetBehaviour(BotState.Patrol, agent);
return BotState.Patrol;
@ -164,7 +168,7 @@ namespace AI
private void UseBonus(AIAgent agent, BonusType type)
{
var attack = agent.Enemy.Inventory.Where(x => x is Bonus bonus && bonus.Type == type).ToList();
var attack = agent.Unit.Inventory.Where(x => x is Bonus bonus && bonus.Type == type).ToList();
if (attack.Count == 0)
{
GetNewBehaviour(agent);
@ -176,44 +180,49 @@ namespace AI
private void Retreet(AIAgent agent)
{
var enemy = GetNearestUnit(6, agent)?.Instance.transform;
var enemy = GetNearestUnit(6, agent.Unit)?.Instance.transform;
if (enemy == null)
{
return;
}
var dir = -DirectionHelper.DirectionTo(agent.Enemy.Instance.transform.position,
var dir = -DirectionHelper.DirectionTo(agent.Unit.Instance.transform.position,
enemy.position);
agent.currentPath.Clear();
agent.currentPath.Enqueue(DirectionHelper.VectorToDirection(new Vector2(dir.x, dir.z)));
}
private (int dist, HexCell hex) GetNearestItem(AIAgent agent)
{
var itemsToMove =
(from entry in ItemFabric.Items
where Vector3.Distance(agent.Unit.Instance.transform.position, entry.Value.transform.position) <
10 * HexGrid.HexDistance
orderby Vector3.Distance(agent.Unit.Instance.transform.position, entry.Value.transform.position)
select entry).ToList();
if (itemsToMove.Count == 0)
{
return (0, null);
}
var itemToMove = itemsToMove.First();
return (
(int)(Vector3.Distance(itemToMove.Value.transform.position, agent.Unit.Instance.transform.position) /
HexGrid.HexDistance), itemToMove.Value);
}
private void MoveToBonus(AIAgent agent)
{
HexCell itemToMove = null;
var min = 10 * HexGrid.HexDistance;
foreach (var itemCell in ItemFabric.Items)
{
if (Vector3.Distance(agent.Enemy.Instance.transform.position, itemCell.Key.transform.position) < min)
{
min = Vector3.Distance(agent.Enemy.Instance.transform.position, itemCell.Key.transform.position);
itemToMove = itemCell.Value;
}
}
if (itemToMove == null)
{
return;
}
Pathfinding.FindPath(HexManager.UnitCurrentCell[agent.Enemy.Color].cell, itemToMove, agent.currentPath);
Pathfinding.FindPath(HexManager.UnitCurrentCell[agent.Unit.Color].cell, GetNearestItem(agent).hex,
agent.currentPath);
}
private void AttackEnemy(AIAgent agent)
{
var enemy = GetNearestUnit(3, agent);
var dir = DirectionHelper.DirectionTo(agent.Enemy.Instance.transform.position,
var enemy = GetNearestUnit(agent.Unit.Weapon.disnatce, agent.Unit);
var dir = DirectionHelper.DirectionTo(agent.Unit.Instance.transform.position,
enemy.Instance.transform.position);
agent.AttackTarget(new Vector2(dir.x, dir.z));
}
@ -222,11 +231,11 @@ namespace AI
{
var enemies = HexManager.UnitCurrentCell
.Where(unit =>
unit.Value.unit.Color != agent.Enemy.Color &&
unit.Value.unit.Color != agent.Unit.Color &&
Vector3.Distance(unit.Value.unit.Instance.transform.position,
agent.Enemy.Instance.transform.position) <= 6 * HexGrid.HexDistance).ToList();
agent.Unit.Instance.transform.position) <= 6 * HexGrid.HexDistance).ToList();
Pathfinding.FindPath(HexManager.UnitCurrentCell[agent.Enemy.Color].cell,
Pathfinding.FindPath(HexManager.UnitCurrentCell[agent.Unit.Color].cell,
enemies[Random.Range(0, enemies.Count)].Value.cell, agent.currentPath);
}
}

View File

@ -23,10 +23,10 @@ namespace Controller
public GameInit(Controllers controllers, Data.Data data)
{
AIManager aiManager = new AIManager();
new AIManager(data.AIData);
var hexGrid = new HexGrid(data.FieldData);
new MusicController();
new VFXController(data.VFXData);
new VFXController();
MusicController.Instance.SetMusicData(data.MusicData);
controllers.Add(hexGrid);
@ -65,7 +65,7 @@ namespace Controller
var enemyController = new EnemyController(unit, enemy);
controllers.Add(enemyController);
units.Add(enemy);
AIAgent agent = new AIAgent(unit, enemy, aiManager);
AIAgent agent = new AIAgent(unit, enemy);
controllers.Add(agent);
enemy.OnDeath += x => {controllers.Remove(agent);};
}

View File

@ -0,0 +1,24 @@
using UnityEngine;
namespace Data
{
[CreateAssetMenu(fileName = "AIData", menuName = "Data/AIData", order = 0)]
public class AIData : ScriptableObject
{
[SerializeField] private int _distanceToAgr;
[SerializeField][Range(0,1)] private float _percentToRetreet;
[SerializeField][Range(0,1)] private float _percentToUseProtectBonus;
[SerializeField][Range(0,1)] private float _manaPercentToCollectBonus;
[SerializeField] private int _distaceToCollectBonus;
public int DistanceToAgr => _distanceToAgr;
public float PercentToUseProtectBonus => _percentToUseProtectBonus;
public float PercentToRetreet => _percentToRetreet;
public float ManaPercentToCollectBonus => _manaPercentToCollectBonus;
public int DistaceToCollectBonus => _distaceToCollectBonus;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 39f9814b967541eeaf31ef497d721a87
timeCreated: 1642409153

View File

@ -22,21 +22,22 @@ namespace Data
private MusicData _musicData;
[SerializeField] private string itemDataPath;
private ItemsData _itemsData;
[SerializeField] private string vfxDataPath;
private VFXData _vfxData;
[SerializeField] private string aiDataPath;
private AIData _aiData;
[SerializeField] private string chosenWeaponDataPath;
public string ChosenWeapon => File.ReadAllText(Application.persistentDataPath + "/" + chosenWeaponDataPath);
public VFXData VFXData {
public AIData AIData
{
get
{
if (_vfxData == null)
if (_aiData == null)
{
_vfxData = Load<VFXData>("Data/" + vfxDataPath);
_aiData = Load<AIData>("Data/" + aiDataPath);
}
return _vfxData;
return _aiData;
}
}
public ItemsData ItemsData

View File

@ -1,10 +0,0 @@
using UnityEngine;
namespace Data
{
[CreateAssetMenu(fileName = "VFXData", menuName = "Data/VFXData", order = 0)]
public class VFXData : ScriptableObject
{
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 20727ea91acd422788176450128f9251
timeCreated: 1641837401

View File

@ -2,7 +2,7 @@ using HexFiled;
using TMPro;
using UnityEngine;
#if UNITY_EDITOR
public class Score : MonoBehaviour
@ -27,4 +27,3 @@ public class Score : MonoBehaviour
_text.text += sum;
}
}
#endif

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AI;
using Chars;
using Data;
using DefaultNamespace;
@ -59,6 +60,8 @@ namespace Units
public int Mana => _mana;
public int Hp => _hp;
public List<Item> Inventory => _inventory;
public Weapon Weapon => _weapon;
public Unit(UnitInfo unitData, Weapon weapon, HexGrid hexGrid)
{
_weapon = weapon;
@ -75,26 +78,25 @@ namespace Units
switch (type)
{
case BonusType.Attack:
TimerHelper.Instance.StartTimer(() => _weapon.SetModifiedDamage(0), duration);
TimerHelper.Instance.StartTimer(() => _weapon.SetModifiedDamage(0), duration);
_weapon.SetModifiedDamage(value);
break;
case BonusType.Defence:
TimerHelper.Instance.StartTimer(()=> _defenceBonus = 0, duration);
TimerHelper.Instance.StartTimer(() => _defenceBonus = 0, duration);
_defenceBonus = value;
break;
default:
break;
}
}
public void Move(HexDirection direction)
{
if (!_cell.GetNeighbor(direction) || _isBusy || _cell.GetNeighbor(direction).Color != UnitColor.GREY &&
(!HexManager.UnitCurrentCell.TryGetValue(_cell.GetNeighbor(direction).Color, out var value)
|| value.cell == _cell.GetNeighbor(direction))) return;
_unitView.StopHardCapture();
if (_cell.GetNeighbor(direction).Color == _data.color)
{
@ -255,11 +257,8 @@ namespace Units
private void Attacking()
{
if (_direction.Equals(Vector2.zero))
{
_direction = new Vector2(_unitView.transform.forward.x, _unitView.transform.forward.z); //TODO автовыстрел
Aim(_direction);
}
Aim(_direction);
_weapon.Fire(_instance.transform, _direction);
}
@ -312,9 +311,22 @@ namespace Units
if (!_isBusy && _unitView.Shoot())
{
_isBusy = true;
if (!_direction.Equals(Vector2.zero))
RotateUnit(_direction);
if (_direction.Equals(Vector2.zero))
{
var enemy = AIManager.GetNearestUnit(_weapon.disnatce, this);
if (enemy == null)
_direction =
new Vector2(_unitView.transform.forward.x, _unitView.transform.forward.z);
else
{
var dir = DirectionHelper.DirectionTo(_instance.transform.position,
enemy.Instance.transform.position);
_direction = new Vector2(dir.x, dir.z);
RotateUnit(_direction);
}
}
_animator.SetTrigger("Attack");
}
}
@ -350,8 +362,10 @@ namespace Units
{
_defenceBonus -= dmg;
}
else
{
SetUpBonus(0,0, BonusType.Defence);
_hp -= dmg;
}

View File

@ -42,6 +42,7 @@ public class UnitView : MonoBehaviour
public BarCanvas BarCanvas => barCanvas;
public GameObject AimCanvas => aimCanvas;
public UnitColor Color => _unit.Color;
public int AvailableShots => _shootUIStack.Count;
public void SetUp(Stack<ShotUIView> shots, Weapon weapon, Action regenMana, int manaRegen, Action captureHex,
Unit unit, float hardCaptureTime)

View File

@ -12,13 +12,11 @@ namespace DefaultNamespace
private set => _instance = value;
}
private VFXData _data;
public VFXData Data => _data;
public VFXController(VFXData data)
public VFXController()
{
Instance ??= this;
_data = data;
}
public GameObject PlayEffect(GameObject effect, Vector3 pos)

File diff suppressed because one or more lines are too long