Это первая версия. Далее буду обновлять, мне хотелось бы чтобы вы отписывались, что лучше и как подправить, буду благодарен.
Скрипты сейчас рабочие. Можете использовать.
В данный момент не реализовано:
Отнимание маны, ярости, энергии при атаке
Восстановление маны, ярости, энергии когда НПЦ не в бою
Изменение скорости НПЦ, в зависимости от ситуации.
и еще чего то)
в NPC_BASE я думаю убрать структуру _stats. Но возможно я реализую влияние этих характеристик на НПЦ. Просто эти параметры для Игрока,
и меня просто понесло как всегда так бывает, пишешь НПЦ и приписываешь ему плюшки от игрока
Скрипт игрока сделан чисто для проверки работоспособности, поэтому он такой убогий.
Вот скрипты.
BASE_STATS
Синтаксис:
Используется csharp
//PLAYER SCRIPT
//RPG TEST NPC BASE CLASS
//Это базовый класс. Сделан для того чтобы из него читались все дефолтные значения для НПЦ 1 уровня.
//В принципе переписать для разных уровней не составляет труда, но увы я уже устал... да и печатная машинка сломалась
//Тут я думаю ничего комментировать не нужно, у кого с английским плохо, как у меня: Google Translate Welcome
using UnityEngine;
public class NPC_BASE
{
[System.Serializable]
public struct _main
{
const float _HEALTHMAX = 60f;
const float _MANAMAX = 40f;
const float _RAGEMAX = 100f;
const float _ENERGYMAX = 100f;
public float HealthMax { get { return _HEALTHMAX; }}
public float ManaMax { get { return _MANAMAX; }}
public float RageMax { get { return _RAGEMAX; }}
public float EnergyMax { get { return _ENERGYMAX; }}
}
[System.Serializable]
public struct _stats
{
const byte _STAMINA = 2;
const byte _INTELLECT = 3;
const byte _AGILITY = 3;
const byte _STRENGH = 4;
const byte _SPIRIT = 2;
public byte Stamina { get { return _STAMINA; }}
public byte Intellect { get { return _INTELLECT; }}
public byte Agility { get { return _AGILITY; }}
public byte Strengh { get { return _STRENGH; }}
public byte Spirit { get { return _SPIRIT; }}
}
[System.Serializable]
public struct _protection
{
const float _ARMOR = 0f;
const float _RANGE_ARMOR_PERCENT = 0f;
const float _MAGIC_ARMOR_PERCENT = 0f;
public float Armor { get { return _ARMOR; } }
public float RangeArmorPercent { get { return _RANGE_ARMOR_PERCENT; }}
public float MagicArmorPercent { get { return _MAGIC_ARMOR_PERCENT; }}
}
[System.Serializable]
public struct _level
{
const byte _LEVEL = 1;
public byte Level { get { return _LEVEL; }}
}
[System.Serializable]
public struct _speed
{
const float _WALK_SPEED = 1.5f;
const float _FASTWALK_SPEED = 2.5f;
const float _RUN_SPEED = 3.5f;
const float _SWIM_SPEED = 3f;
const float _FLY_SPEED = 7.5f;
public float WalkSpeed { get { return _WALK_SPEED; }}
public float FastWalkSpeed { get { return _FASTWALK_SPEED; }}
public float RunSpeed { get { return _RUN_SPEED; }}
public float SwimSpeed { get { return _SWIM_SPEED; }}
public float FlySpeed { get { return _FLY_SPEED; }}
}
[System.Serializable]
public struct _attack
{
const float _ATTACK_SPEED = 1.7f;
const float _ATTACK_CRITICAL_CHANCE = 4.5f;
const float _MIN_DAMAGE = 1f;
const float _MAX_DAMAGE = 4f;
const float _ATTACK_DISTANCE = 2.5f;
const float _VISIBLE_DISTANCE = 10f;
public float AttackSpeed { get { return _ATTACK_SPEED;}}
public float AttackCriticalChance { get { return _ATTACK_CRITICAL_CHANCE; }}
public float MinDamage { get { return _MIN_DAMAGE; }}
public float MaxDamage { get { return _MAX_DAMAGE; }}
public float AttackDistance { get { return _ATTACK_DISTANCE; }}
public float VisibleDistance { get { return _VISIBLE_DISTANCE; }}
}
[System.Serializable]
public struct _walking
{
const float _MAX_DISTANCE = 5f;
const float _MAX_FOLLOWING_DISTANCE = 20f;
const float _STAY_ON_NEW_POSITION = 15f;
public float MaxWalkingDistance { get { return _MAX_DISTANCE; }}
public float MaxFollowingDistance { get { return _MAX_FOLLOWING_DISTANCE; }}
public float StayOnPosition { get { return _STAY_ON_NEW_POSITION; }}
}
[System.Serializable]
public struct _chance
{
const float _MISS_CHANCE = 4f;
const float _BLOCK_CHANCE = 2.5f;
const float _PARRY_CHANCE = 1.75f;
public float MissChance { get { return _MISS_CHANCE; }}
public float BlockChance { get { return _BLOCK_CHANCE; }}
public float ParryChance { get { return _PARRY_CHANCE; }}
}
public static _main Main;
public static _stats Stats;
public static _speed Speed;
public static _attack Attack;
public static _chance Chance;
public static _protection Protection;
public static _level level;
public static _walking Walking;
}
//RPG TEST NPC BASE CLASS
//Это базовый класс. Сделан для того чтобы из него читались все дефолтные значения для НПЦ 1 уровня.
//В принципе переписать для разных уровней не составляет труда, но увы я уже устал... да и печатная машинка сломалась
//Тут я думаю ничего комментировать не нужно, у кого с английским плохо, как у меня: Google Translate Welcome
using UnityEngine;
public class NPC_BASE
{
[System.Serializable]
public struct _main
{
const float _HEALTHMAX = 60f;
const float _MANAMAX = 40f;
const float _RAGEMAX = 100f;
const float _ENERGYMAX = 100f;
public float HealthMax { get { return _HEALTHMAX; }}
public float ManaMax { get { return _MANAMAX; }}
public float RageMax { get { return _RAGEMAX; }}
public float EnergyMax { get { return _ENERGYMAX; }}
}
[System.Serializable]
public struct _stats
{
const byte _STAMINA = 2;
const byte _INTELLECT = 3;
const byte _AGILITY = 3;
const byte _STRENGH = 4;
const byte _SPIRIT = 2;
public byte Stamina { get { return _STAMINA; }}
public byte Intellect { get { return _INTELLECT; }}
public byte Agility { get { return _AGILITY; }}
public byte Strengh { get { return _STRENGH; }}
public byte Spirit { get { return _SPIRIT; }}
}
[System.Serializable]
public struct _protection
{
const float _ARMOR = 0f;
const float _RANGE_ARMOR_PERCENT = 0f;
const float _MAGIC_ARMOR_PERCENT = 0f;
public float Armor { get { return _ARMOR; } }
public float RangeArmorPercent { get { return _RANGE_ARMOR_PERCENT; }}
public float MagicArmorPercent { get { return _MAGIC_ARMOR_PERCENT; }}
}
[System.Serializable]
public struct _level
{
const byte _LEVEL = 1;
public byte Level { get { return _LEVEL; }}
}
[System.Serializable]
public struct _speed
{
const float _WALK_SPEED = 1.5f;
const float _FASTWALK_SPEED = 2.5f;
const float _RUN_SPEED = 3.5f;
const float _SWIM_SPEED = 3f;
const float _FLY_SPEED = 7.5f;
public float WalkSpeed { get { return _WALK_SPEED; }}
public float FastWalkSpeed { get { return _FASTWALK_SPEED; }}
public float RunSpeed { get { return _RUN_SPEED; }}
public float SwimSpeed { get { return _SWIM_SPEED; }}
public float FlySpeed { get { return _FLY_SPEED; }}
}
[System.Serializable]
public struct _attack
{
const float _ATTACK_SPEED = 1.7f;
const float _ATTACK_CRITICAL_CHANCE = 4.5f;
const float _MIN_DAMAGE = 1f;
const float _MAX_DAMAGE = 4f;
const float _ATTACK_DISTANCE = 2.5f;
const float _VISIBLE_DISTANCE = 10f;
public float AttackSpeed { get { return _ATTACK_SPEED;}}
public float AttackCriticalChance { get { return _ATTACK_CRITICAL_CHANCE; }}
public float MinDamage { get { return _MIN_DAMAGE; }}
public float MaxDamage { get { return _MAX_DAMAGE; }}
public float AttackDistance { get { return _ATTACK_DISTANCE; }}
public float VisibleDistance { get { return _VISIBLE_DISTANCE; }}
}
[System.Serializable]
public struct _walking
{
const float _MAX_DISTANCE = 5f;
const float _MAX_FOLLOWING_DISTANCE = 20f;
const float _STAY_ON_NEW_POSITION = 15f;
public float MaxWalkingDistance { get { return _MAX_DISTANCE; }}
public float MaxFollowingDistance { get { return _MAX_FOLLOWING_DISTANCE; }}
public float StayOnPosition { get { return _STAY_ON_NEW_POSITION; }}
}
[System.Serializable]
public struct _chance
{
const float _MISS_CHANCE = 4f;
const float _BLOCK_CHANCE = 2.5f;
const float _PARRY_CHANCE = 1.75f;
public float MissChance { get { return _MISS_CHANCE; }}
public float BlockChance { get { return _BLOCK_CHANCE; }}
public float ParryChance { get { return _PARRY_CHANCE; }}
}
public static _main Main;
public static _stats Stats;
public static _speed Speed;
public static _attack Attack;
public static _chance Chance;
public static _protection Protection;
public static _level level;
public static _walking Walking;
}
NPC
Синтаксис:
Используется csharp
//Это мозг всего НПЦ! он и будет отвечать у вас за бла бла бла.. Ну вы поняли)) за ничего он будет отвечать.))
//Этот скрипт хранит в себе все текущие переменные типа статистик и прочего от вашего НПЦ.
using UnityEngine;
[System.Serializable]
public class NPC_STATS : NPC_BASE //Наследуем от Базы.
{
[HideInInspector] // Скрывает Public переменные в инспекторе
public float currentHealth;
[HideInInspector]
public float currentMana;
[HideInInspector]
public float currentEnergy;
[HideInInspector]
public float currentRage;
//MAIN
[Tooltip("Default: 60")] // Показывает подсказки в инспекторе при наведение на название функции
public float HealthMax;
[Tooltip("Default: 40")]
public float ManaMax;
[Tooltip("Default: 100")]
public float EnergyMax;
[Tooltip("Default: 100")]
public float RageMax;
//STATS
[Space(10)]
[Tooltip("Default: 2")]
public byte Stamina;
[Tooltip("Default: 3")]
public byte Intellect;
[Tooltip("Default: 3")]
public byte Agility;
[Tooltip("Default: 4")]
public byte Strengh;
[Tooltip("Default: 2")]
public byte Spirit;
//###PROTECTION
[Space(10)]
[Tooltip("Default: 0")]
public float Armor;
[Tooltip("Default: 0")]
public float RangeArmorPercent;
[Tooltip("Default: 0")]
public float MagicArmorPercent;
//###LEVEL
[Space(10)]
[Tooltip("Default: 1")]
public byte Level;
//###SPEED
[Space(10)]
[Tooltip("Default: 1.7")]
public float AttackSpeed;
[Tooltip("Default: 1.5")]
public float WalkSpeed;
[Tooltip("Default: 2.5")]
public float FastWalkSpeed;
[Tooltip("Default: 3.5")]
public float RunSpeed;
[Tooltip("Default: 3")]
public float SwimSpeed;
[Tooltip("Default: 7.5")]
public float FlySpeed;
//###ATTACK
[Space(10)]
[Tooltip("Default: 1")]
public float MinDamage;
[Tooltip("Default: 4")]
public float MaxDamage;
[Tooltip("Default: 4.5")]
public float AttackCriticalChance;
[Tooltip("Default: 2.5")]
public float AttackDistance;
[Tooltip("Default: 7.5")]
public float VisibleDistance;
//###CHANCE
[Space(10)]
[Tooltip("Default: 4")]
public float MissChance;
[Tooltip("Default: 2.5")]
public float BlockChance;
[Tooltip("Default: 1.75")]
public float ParryChance;
//###WALKING
[Space(10)]
public bool isWalking;
[Tooltip("Default: 5")]
public float MaxWalkingDistance;
[Tooltip("Default: 20")]
public float MaxFollowingDistance;
[Tooltip("Default: 15")]
public float StayOnPosition;
//###ENUMS
public enum _class { Melee, Range, Magic };
public enum _friction { Neutral, Agressive, Friend };
public _class Class;
public _friction Friction;
//###OTHER
[HideInInspector]
public bool isDead;
[HideInInspector]
public bool inCombat;
[HideInInspector]
public GameObject target;
#region CheckOnEmptyAttributes
//Метод сравнивающий значения, и если из тела метода он находит переменную которая равна нулю, заменяет это значение
//на значение из NPC_BASE
public void CheckOnEmptyAttributes ()
{
//###MAIN
switch (Class)
{
case _class.Melee:
if (HealthMax == 0)
HealthMax = NPC_STATS.Main.HealthMax;
if (RageMax == 0)
RageMax = NPC_STATS.Main.RageMax;
break;
case _class.Range:
if (HealthMax == 0)
HealthMax = NPC_STATS.Main.HealthMax;
if (EnergyMax == 0)
EnergyMax = NPC_STATS.Main.EnergyMax;
break;
case _class.Magic:
if (HealthMax == 0)
HealthMax = NPC_STATS.Main.HealthMax;
if (ManaMax == 0)
ManaMax = NPC_STATS.Main.ManaMax;
break;
}
//###STATS
if (Stamina == 0)
Stamina = NPC_STATS.Stats.Stamina;
if (Intellect == 0)
Intellect = NPC_STATS.Stats.Intellect;
if (Agility == 0)
Agility = NPC_STATS.Stats.Agility;
if (Strengh == 0)
Strengh = NPC_STATS.Stats.Strengh;
if (Spirit == 0)
Spirit = NPC_STATS.Stats.Spirit;
//###PROTECTION
//Все статы брони равны нулю в NPC_BASE скрипте, по этому тут нет присвоения значений
//Если в NPC_BASE вы ввели значения не равные нулю, то расскоментируйте ниже написаное.
/*
if (Armor == 0)
Armor = NPC_STATS.Protection.Armor;
if (RangeArmorPercent == 0)
RangeArmorPercent = NPC_STATS.Protection.RangeArmorPercent;
if (MagicArmorPercent == 0)
MagicArmorPercent = NPC_STATS.Protection.MagicArmorPercent;
*/
//###LEVEL
if (Level == 0)
Level = NPC_STATS.level.Level;
//###SPEED
if (WalkSpeed == 0)
WalkSpeed = NPC_STATS.Speed.WalkSpeed;
if (FastWalkSpeed == 0)
FastWalkSpeed = NPC_STATS.Speed.FastWalkSpeed;
if (RunSpeed == 0)
RunSpeed = NPC_STATS.Speed.RunSpeed;
if (SwimSpeed == 0)
SwimSpeed = NPC_STATS.Speed.SwimSpeed;
if (FlySpeed == 0)
FlySpeed = NPC_STATS.Speed.FlySpeed;
//###ATTACK
if (AttackSpeed == 0)
AttackSpeed = NPC_STATS.Attack.AttackSpeed;
if (MinDamage == 0)
MinDamage = NPC_STATS.Attack.MinDamage;
if (MaxDamage == 0)
MaxDamage = NPC_STATS.Attack.MaxDamage;
if (AttackCriticalChance == 0)
AttackCriticalChance = NPC_STATS.Attack.AttackCriticalChance;
if (AttackDistance == 0)
AttackDistance = NPC_STATS.Attack.AttackDistance;
if (VisibleDistance == 0)
VisibleDistance = NPC_STATS.Attack.VisibleDistance;
//###CHANCE
if (MissChance == 0)
MissChance = NPC_STATS.Chance.MissChance;
if (BlockChance == 0)
BlockChance = NPC_STATS.Chance.BlockChance;
if (ParryChance == 0)
ParryChance = NPC_STATS.Chance.ParryChance;
//###WALKING
if (isWalking)
{
if (MaxWalkingDistance == 0)
MaxWalkingDistance = NPC_STATS.Walking.MaxWalkingDistance;
if (MaxFollowingDistance == 0)
MaxFollowingDistance = NPC_STATS.Walking.MaxFollowingDistance;
if (StayOnPosition == 0)
StayOnPosition = NPC_STATS.Walking.StayOnPosition;
}
AssignCurrentVariables();
}
private void AssignCurrentVariables ()
{
currentHealth = HealthMax;
currentMana = ManaMax;
currentEnergy = EnergyMax;
currentRage = RageMax;
}
#endregion
}
[RequireComponent(typeof(NPC_AI))]
public class NPC : MonoBehaviour
{
public NPC_STATS Stats;
void Start ()
{
Stats.CheckOnEmptyAttributes ();
}
}
//Этот скрипт хранит в себе все текущие переменные типа статистик и прочего от вашего НПЦ.
using UnityEngine;
[System.Serializable]
public class NPC_STATS : NPC_BASE //Наследуем от Базы.
{
[HideInInspector] // Скрывает Public переменные в инспекторе
public float currentHealth;
[HideInInspector]
public float currentMana;
[HideInInspector]
public float currentEnergy;
[HideInInspector]
public float currentRage;
//MAIN
[Tooltip("Default: 60")] // Показывает подсказки в инспекторе при наведение на название функции
public float HealthMax;
[Tooltip("Default: 40")]
public float ManaMax;
[Tooltip("Default: 100")]
public float EnergyMax;
[Tooltip("Default: 100")]
public float RageMax;
//STATS
[Space(10)]
[Tooltip("Default: 2")]
public byte Stamina;
[Tooltip("Default: 3")]
public byte Intellect;
[Tooltip("Default: 3")]
public byte Agility;
[Tooltip("Default: 4")]
public byte Strengh;
[Tooltip("Default: 2")]
public byte Spirit;
//###PROTECTION
[Space(10)]
[Tooltip("Default: 0")]
public float Armor;
[Tooltip("Default: 0")]
public float RangeArmorPercent;
[Tooltip("Default: 0")]
public float MagicArmorPercent;
//###LEVEL
[Space(10)]
[Tooltip("Default: 1")]
public byte Level;
//###SPEED
[Space(10)]
[Tooltip("Default: 1.7")]
public float AttackSpeed;
[Tooltip("Default: 1.5")]
public float WalkSpeed;
[Tooltip("Default: 2.5")]
public float FastWalkSpeed;
[Tooltip("Default: 3.5")]
public float RunSpeed;
[Tooltip("Default: 3")]
public float SwimSpeed;
[Tooltip("Default: 7.5")]
public float FlySpeed;
//###ATTACK
[Space(10)]
[Tooltip("Default: 1")]
public float MinDamage;
[Tooltip("Default: 4")]
public float MaxDamage;
[Tooltip("Default: 4.5")]
public float AttackCriticalChance;
[Tooltip("Default: 2.5")]
public float AttackDistance;
[Tooltip("Default: 7.5")]
public float VisibleDistance;
//###CHANCE
[Space(10)]
[Tooltip("Default: 4")]
public float MissChance;
[Tooltip("Default: 2.5")]
public float BlockChance;
[Tooltip("Default: 1.75")]
public float ParryChance;
//###WALKING
[Space(10)]
public bool isWalking;
[Tooltip("Default: 5")]
public float MaxWalkingDistance;
[Tooltip("Default: 20")]
public float MaxFollowingDistance;
[Tooltip("Default: 15")]
public float StayOnPosition;
//###ENUMS
public enum _class { Melee, Range, Magic };
public enum _friction { Neutral, Agressive, Friend };
public _class Class;
public _friction Friction;
//###OTHER
[HideInInspector]
public bool isDead;
[HideInInspector]
public bool inCombat;
[HideInInspector]
public GameObject target;
#region CheckOnEmptyAttributes
//Метод сравнивающий значения, и если из тела метода он находит переменную которая равна нулю, заменяет это значение
//на значение из NPC_BASE
public void CheckOnEmptyAttributes ()
{
//###MAIN
switch (Class)
{
case _class.Melee:
if (HealthMax == 0)
HealthMax = NPC_STATS.Main.HealthMax;
if (RageMax == 0)
RageMax = NPC_STATS.Main.RageMax;
break;
case _class.Range:
if (HealthMax == 0)
HealthMax = NPC_STATS.Main.HealthMax;
if (EnergyMax == 0)
EnergyMax = NPC_STATS.Main.EnergyMax;
break;
case _class.Magic:
if (HealthMax == 0)
HealthMax = NPC_STATS.Main.HealthMax;
if (ManaMax == 0)
ManaMax = NPC_STATS.Main.ManaMax;
break;
}
//###STATS
if (Stamina == 0)
Stamina = NPC_STATS.Stats.Stamina;
if (Intellect == 0)
Intellect = NPC_STATS.Stats.Intellect;
if (Agility == 0)
Agility = NPC_STATS.Stats.Agility;
if (Strengh == 0)
Strengh = NPC_STATS.Stats.Strengh;
if (Spirit == 0)
Spirit = NPC_STATS.Stats.Spirit;
//###PROTECTION
//Все статы брони равны нулю в NPC_BASE скрипте, по этому тут нет присвоения значений
//Если в NPC_BASE вы ввели значения не равные нулю, то расскоментируйте ниже написаное.
/*
if (Armor == 0)
Armor = NPC_STATS.Protection.Armor;
if (RangeArmorPercent == 0)
RangeArmorPercent = NPC_STATS.Protection.RangeArmorPercent;
if (MagicArmorPercent == 0)
MagicArmorPercent = NPC_STATS.Protection.MagicArmorPercent;
*/
//###LEVEL
if (Level == 0)
Level = NPC_STATS.level.Level;
//###SPEED
if (WalkSpeed == 0)
WalkSpeed = NPC_STATS.Speed.WalkSpeed;
if (FastWalkSpeed == 0)
FastWalkSpeed = NPC_STATS.Speed.FastWalkSpeed;
if (RunSpeed == 0)
RunSpeed = NPC_STATS.Speed.RunSpeed;
if (SwimSpeed == 0)
SwimSpeed = NPC_STATS.Speed.SwimSpeed;
if (FlySpeed == 0)
FlySpeed = NPC_STATS.Speed.FlySpeed;
//###ATTACK
if (AttackSpeed == 0)
AttackSpeed = NPC_STATS.Attack.AttackSpeed;
if (MinDamage == 0)
MinDamage = NPC_STATS.Attack.MinDamage;
if (MaxDamage == 0)
MaxDamage = NPC_STATS.Attack.MaxDamage;
if (AttackCriticalChance == 0)
AttackCriticalChance = NPC_STATS.Attack.AttackCriticalChance;
if (AttackDistance == 0)
AttackDistance = NPC_STATS.Attack.AttackDistance;
if (VisibleDistance == 0)
VisibleDistance = NPC_STATS.Attack.VisibleDistance;
//###CHANCE
if (MissChance == 0)
MissChance = NPC_STATS.Chance.MissChance;
if (BlockChance == 0)
BlockChance = NPC_STATS.Chance.BlockChance;
if (ParryChance == 0)
ParryChance = NPC_STATS.Chance.ParryChance;
//###WALKING
if (isWalking)
{
if (MaxWalkingDistance == 0)
MaxWalkingDistance = NPC_STATS.Walking.MaxWalkingDistance;
if (MaxFollowingDistance == 0)
MaxFollowingDistance = NPC_STATS.Walking.MaxFollowingDistance;
if (StayOnPosition == 0)
StayOnPosition = NPC_STATS.Walking.StayOnPosition;
}
AssignCurrentVariables();
}
private void AssignCurrentVariables ()
{
currentHealth = HealthMax;
currentMana = ManaMax;
currentEnergy = EnergyMax;
currentRage = RageMax;
}
#endregion
}
[RequireComponent(typeof(NPC_AI))]
public class NPC : MonoBehaviour
{
public NPC_STATS Stats;
void Start ()
{
Stats.CheckOnEmptyAttributes ();
}
}
NPC_AI
Синтаксис:
Используется csharp
//А Это наше ТЕЛО! тут вся логика не до логика)).
//В комментариях приведенны строки, они могут не совпадать, т.к возможно я что то до писал и строка сбилась.
//Делать Было нечего вот и решил навалять вот это..
using UnityEngine;
public class NPC_AI : MonoBehaviour
{
private NPC NPC; //Наш МОЗГ!!!
private NavMeshAgent NAV_MESH_AGENT; //Агент 007
private Vector3 PLAYER_POSITION; //Позиция игрока
private Vector3 START_POSITION; //Стартовая позиция
private float _distanceToPlayer; //Дистанция до игрока 40строка
private float _distanceToStartPosition; //Дистанция до позиции старта 42строка
private PLAYER PLAYER_SCRIPT; //Ссылка на скрипт игрока.
private int _frictionNumber; //Локальная переменная под фракцию НПЦ при старте.
private float _attackSpeed; //Локальная переменная под счетчик задержки между ударами.
private float _stayOnPosition; //Локальная переменная под счетчик ожидания на новой позиции.
private float _timeOutBattle; //Название может и не правильное. Это для выхода из боя
private float _visibleDistance; //Нужна для исправления бага.
void Start ()
{
PLAYER_SCRIPT = GameObject.FindGameObjectWithTag("Player").GetComponent<PLAYER>();
NPC = this.GetComponent<NPC>(); //Добавляем скрипт с этого же объекта
//Если на объекте нет Агента 007 -> Добавляем его и сразу забиваем на него ссылку
if (gameObject.GetComponent<NavMeshAgent>() == null)
NAV_MESH_AGENT = gameObject.AddComponent<NavMeshAgent>();
//Или же просто забиваем его в ссылку
else
NAV_MESH_AGENT = gameObject.GetComponent<NavMeshAgent>();
//Указываем что останавливатся нужно на дистанции атаки, а не нюхать модельку игрока
NAV_MESH_AGENT.stoppingDistance = NPC.Stats.AttackDistance;
//Забиваем число его фракции. (Нужен для того чтобы вернуть его из агрессивного в нейтральный)
_frictionNumber = (int)NPC.Stats.Friction; //0-neutral, 1-agressive, 2-friend : friction enum
//Ну и стартовая позиция записывается при спавне
START_POSITION = this.transform.position;
//Сохранение начального значение переменной
_visibleDistance = NPC.Stats.VisibleDistance;
}
void Update ()
{
//Записываем в переменную позицию игрока
PLAYER_POSITION = GameObject.FindGameObjectWithTag("Player").transform.position;
//Записываем в переменную дистанцию до игрока.
_distanceToPlayer = Vector3.Distance(this.transform.position, PLAYER_POSITION);
//Записываем в переменную дистанцию до спавна.
_distanceToStartPosition = Vector3.Distance(this.transform.position, START_POSITION);
//Если НПЦ НЕ МЕРТВ!
if (!NPC.Stats.isDead)
{
//Проверяем статус нпц ( Фракцией называется потому что изначально у него были фракции в дальнейшем убрал)
if (NPC.Stats.Friction == NPC_STATS._friction.Agressive && !PLAYER_SCRIPT.isDead)
{
//Если игрок в зони видимости нпц -> Преследуем игрока
if (_distanceToPlayer <= NPC.Stats.VisibleDistance)
FollowingPlayer();
}
#region ПРОВЕРКИ НА БОЙ
//Если НПЦ не в бою
if (!NPC.Stats.inCombat)
{
//Если здоровья меньше максимального -> Восстанавливаем здоровье игроку.
if (NPC.Stats.currentHealth < NPC.Stats.HealthMax)
NPC.Stats.currentHealth += (5 * NPC.Stats.Level) * Time.deltaTime;
}
//Если НПЦ в бою
if (NPC.Stats.inCombat)
{
//Если дистанция до игрока больше видимой, или игрок умер
if (_distanceToPlayer > NPC.Stats.VisibleDistance || PLAYER_SCRIPT.isDead)
{
//Считаем время до выхода из боя
if (_timeOutBattle > 0)
_timeOutBattle -= Time.deltaTime;
else
//Выходим из боя
NPC.Stats.inCombat = false;
}
}
#endregion
#region ПРОВЕРКИ НА ХП
//Если здоровье вышло за границы -> Выравниваем его по максимальному
if(NPC.Stats.currentHealth > NPC.Stats.HealthMax)
NPC.Stats.currentHealth = NPC.Stats.HealthMax;
//Если здоровье ушло. -> Включаем смерть
if (NPC.Stats.currentHealth <= 0f)
{
NPC.Stats.isDead = true;
NPC.Stats.currentHealth = 0f;
}
#endregion
}
//Если НПЦ может ходить и не в бою и не мертв.
if (NPC.Stats.isWalking && !NPC.Stats.inCombat && !NPC.Stats.isDead)
{
//Вызываем метод.
Walking ();
}
//Возвращение обзора для НПЦ, когда он почти добежал до точки старта
Debug.Log(Vector3.Distance(transform.position, START_POSITION));
if (Vector3.Distance(transform.position, START_POSITION) < 5f)
NPC.Stats.VisibleDistance = _visibleDistance;
}
//А вот и он.
private void Walking ()
{
//Если таймер простоя на точке больше 0 -> Считаем таймер
if (_stayOnPosition > 0)
_stayOnPosition -= Time.deltaTime;
//Или же Выдаем ему новую позицию, отправляем его туда и обнуляем таймер.
else
{
/*
ЭТОТ ВАРИАНТ Я ИСПОЛЬЗОВАЛ РАНЬШЕ.
float x = Random.Range(0f, NPC.Stats.MaxWalkingDistance);
float z = Random.Range(0f, NPC.Stats.MaxWalkingDistance);
Vector3 newPosition = new Vector3(x, transform.position.y, z);
NAV_MESH_AGENT.SetDestination(newPosition);
*/
//СЕЙЧАС РЕШИЛ ПОПРОБОВАТЬ ВОТ ТАК.
//+ Тут его мы не отпускаем от стартовой позиции. иначе он бы ушел через 30 минут в африку пешком)))
NAV_MESH_AGENT.SetDestination(new Vector3(
START_POSITION.x + Random.Range(0f, NPC.Stats.MaxWalkingDistance), //x
transform.position.y, //y
START_POSITION.z + Random.Range(0f, NPC.Stats.MaxWalkingDistance))); //z
//Обнуление таймера
_stayOnPosition = NPC.Stats.StayOnPosition;
}
}
//Преследование игрока
private void FollowingPlayer ()
{
//Включаем режим боя.
NPC.Stats.inCombat = true;
//Если наш моб убежал за максимальную дистанцию преследования -> заставляем его бежать на респаун, и отключаем режим боя.
if (_distanceToStartPosition > NPC.Stats.MaxFollowingDistance && NPC.Stats.inCombat)
{
//Вот как раз тут и пригодится нам переменная _frictionNumber
//Здесь НПЦ изначально был нейтральным, но когда мы его ударили(стр.205) и он стал агрессивным, и тут мы все возвращаем назад
if (NPC.Stats.Friction == NPC_STATS._friction.Agressive && _frictionNumber == 0)
NPC.Stats.Friction = (NPC_STATS._friction)_frictionNumber;
NAV_MESH_AGENT.SetDestination(START_POSITION);
NPC.Stats.inCombat = false;
//Обнуляем ему таймер на тупняк.
_stayOnPosition = 0f;
//Ограничиваем обзор для того чтобы небыло бага, когда моб дрыгается из стороны в сторону, так как SetDestanation пересекаются
NPC.Stats.VisibleDistance = 2f;
}
//Или же бежим за игроком
else
NAV_MESH_AGENT.SetDestination(PLAYER_POSITION);
//Если дистанция до игрока уже позволяет бить игрока -> Бъем игрока
if (_distanceToPlayer <= NPC.Stats.AttackDistance)
Attack ();
}
//Бъем игрока здесь
private void Attack ()
{
//Если есть задержка перед ударом -> считаем ее.
if (_attackSpeed > 0)
_attackSpeed -= Time.deltaTime;
//Или же наносим игрока повреждения
else
{
//Кидаем монетку от 0 до 100 на промах
float randChance = Random.Range (0f, 100f);
//Если выпало больше, то бьем (если <= то промах)
if (randChance > NPC.Stats.MissChance)
{
//Снова выбрасываем монетку, только теперь на крит.
randChance = Random.Range (0f, 100f);
//Если выпало больше, то бьем обычный удар
if (randChance > NPC.Stats.AttackCriticalChance)
//атака во врага обычная
PLAYER_SCRIPT.TAKE_DAMAGE (Random.Range(NPC.Stats.MinDamage, NPC.Stats.MaxDamage));
else
//атака во врага критом
PLAYER_SCRIPT.TAKE_DAMAGE (Random.Range(NPC.Stats.MinDamage * 2, NPC.Stats.MaxDamage * 2));
}
else
//Можно вывести на экран, что атака не удалась
Debug.Log("NPC MISS");
//Обнуляем задержку между атаками.
_attackSpeed = NPC.Stats.AttackSpeed;
}
}
//Публичная переменная т.к получаем урон из другого скрипта.
public void TakeDamage (float Damage)
{
//Если наш тупоголовый нейтрал, и мы его ударяем то он становиться агрессивным
//151-152 строка возвращает положение на изначальное.
if (NPC.Stats.Friction == NPC_STATS._friction.Neutral)
NPC.Stats.Friction = NPC_STATS._friction.Agressive;
//Вводим НПЦ в режим боя
NPC.Stats.inCombat = true;
//Устанавливаем Таймер для выхода из боя, реализация его здесь нужна для постоянного обновления при получении урона
_timeOutBattle = 5f;
//И снова тут мы будем бросать монетку на паррирование удара.
float randChance = Random.Range (0f, 100f);
//Если монетка выкинула больше, то нпц не с паррировал удар
if (randChance > NPC.Stats.ParryChance)
{
//Снова монетка, теперь уже на блокировку удара
randChance = Random.Range (0f, 100f);
//Если больше то не блокировали...
if (randChance > NPC.Stats.BlockChance)
{
//Заводим локальную переменную под логику деления урона на броню
//пример: 44 урон, 100 брони.
//damageDivider = ((100 брони + 100 = 200) / 100) = 2
//HP -= 44 / (2) = 22.
//пример: 44 урон, 75 брони.
//Делитель = ((75 брони + 100 = 200) / 100) = 1.75
//ХП -= 44 / (1.75) = 25
//ХП ИГРОКА УРОН ДЕЛИТЕЛЬ
NPC.Stats.currentHealth -= Damage / ((NPC.Stats.Armor + 100) / 100);
}
else
Debug.Log("Attack Blocked");
}
else
Debug.Log("Parry Attack");
}
//Можете сами заменить на что хотите, мне подходит и такой вариант.
//Если у нас мышка находится на объекте и мы нажали ЛКМ. Добавляем в таргет этот объект
//Если нажимаем ПКМ то добавляем в таргет объект и включаем атаку.
void OnMouseOver ()
{
if (Input.GetButtonDown("Fire1"))
PLAYER_SCRIPT.Target = this.gameObject;
if (Input.GetButtonDown("Fire2"))
{
PLAYER_SCRIPT.blaAttack = true;
PLAYER_SCRIPT.Target = this.gameObject;
}
}
}
//В комментариях приведенны строки, они могут не совпадать, т.к возможно я что то до писал и строка сбилась.
//Делать Было нечего вот и решил навалять вот это..
using UnityEngine;
public class NPC_AI : MonoBehaviour
{
private NPC NPC; //Наш МОЗГ!!!
private NavMeshAgent NAV_MESH_AGENT; //Агент 007
private Vector3 PLAYER_POSITION; //Позиция игрока
private Vector3 START_POSITION; //Стартовая позиция
private float _distanceToPlayer; //Дистанция до игрока 40строка
private float _distanceToStartPosition; //Дистанция до позиции старта 42строка
private PLAYER PLAYER_SCRIPT; //Ссылка на скрипт игрока.
private int _frictionNumber; //Локальная переменная под фракцию НПЦ при старте.
private float _attackSpeed; //Локальная переменная под счетчик задержки между ударами.
private float _stayOnPosition; //Локальная переменная под счетчик ожидания на новой позиции.
private float _timeOutBattle; //Название может и не правильное. Это для выхода из боя
private float _visibleDistance; //Нужна для исправления бага.
void Start ()
{
PLAYER_SCRIPT = GameObject.FindGameObjectWithTag("Player").GetComponent<PLAYER>();
NPC = this.GetComponent<NPC>(); //Добавляем скрипт с этого же объекта
//Если на объекте нет Агента 007 -> Добавляем его и сразу забиваем на него ссылку
if (gameObject.GetComponent<NavMeshAgent>() == null)
NAV_MESH_AGENT = gameObject.AddComponent<NavMeshAgent>();
//Или же просто забиваем его в ссылку
else
NAV_MESH_AGENT = gameObject.GetComponent<NavMeshAgent>();
//Указываем что останавливатся нужно на дистанции атаки, а не нюхать модельку игрока
NAV_MESH_AGENT.stoppingDistance = NPC.Stats.AttackDistance;
//Забиваем число его фракции. (Нужен для того чтобы вернуть его из агрессивного в нейтральный)
_frictionNumber = (int)NPC.Stats.Friction; //0-neutral, 1-agressive, 2-friend : friction enum
//Ну и стартовая позиция записывается при спавне
START_POSITION = this.transform.position;
//Сохранение начального значение переменной
_visibleDistance = NPC.Stats.VisibleDistance;
}
void Update ()
{
//Записываем в переменную позицию игрока
PLAYER_POSITION = GameObject.FindGameObjectWithTag("Player").transform.position;
//Записываем в переменную дистанцию до игрока.
_distanceToPlayer = Vector3.Distance(this.transform.position, PLAYER_POSITION);
//Записываем в переменную дистанцию до спавна.
_distanceToStartPosition = Vector3.Distance(this.transform.position, START_POSITION);
//Если НПЦ НЕ МЕРТВ!
if (!NPC.Stats.isDead)
{
//Проверяем статус нпц ( Фракцией называется потому что изначально у него были фракции в дальнейшем убрал)
if (NPC.Stats.Friction == NPC_STATS._friction.Agressive && !PLAYER_SCRIPT.isDead)
{
//Если игрок в зони видимости нпц -> Преследуем игрока
if (_distanceToPlayer <= NPC.Stats.VisibleDistance)
FollowingPlayer();
}
#region ПРОВЕРКИ НА БОЙ
//Если НПЦ не в бою
if (!NPC.Stats.inCombat)
{
//Если здоровья меньше максимального -> Восстанавливаем здоровье игроку.
if (NPC.Stats.currentHealth < NPC.Stats.HealthMax)
NPC.Stats.currentHealth += (5 * NPC.Stats.Level) * Time.deltaTime;
}
//Если НПЦ в бою
if (NPC.Stats.inCombat)
{
//Если дистанция до игрока больше видимой, или игрок умер
if (_distanceToPlayer > NPC.Stats.VisibleDistance || PLAYER_SCRIPT.isDead)
{
//Считаем время до выхода из боя
if (_timeOutBattle > 0)
_timeOutBattle -= Time.deltaTime;
else
//Выходим из боя
NPC.Stats.inCombat = false;
}
}
#endregion
#region ПРОВЕРКИ НА ХП
//Если здоровье вышло за границы -> Выравниваем его по максимальному
if(NPC.Stats.currentHealth > NPC.Stats.HealthMax)
NPC.Stats.currentHealth = NPC.Stats.HealthMax;
//Если здоровье ушло. -> Включаем смерть
if (NPC.Stats.currentHealth <= 0f)
{
NPC.Stats.isDead = true;
NPC.Stats.currentHealth = 0f;
}
#endregion
}
//Если НПЦ может ходить и не в бою и не мертв.
if (NPC.Stats.isWalking && !NPC.Stats.inCombat && !NPC.Stats.isDead)
{
//Вызываем метод.
Walking ();
}
//Возвращение обзора для НПЦ, когда он почти добежал до точки старта
Debug.Log(Vector3.Distance(transform.position, START_POSITION));
if (Vector3.Distance(transform.position, START_POSITION) < 5f)
NPC.Stats.VisibleDistance = _visibleDistance;
}
//А вот и он.
private void Walking ()
{
//Если таймер простоя на точке больше 0 -> Считаем таймер
if (_stayOnPosition > 0)
_stayOnPosition -= Time.deltaTime;
//Или же Выдаем ему новую позицию, отправляем его туда и обнуляем таймер.
else
{
/*
ЭТОТ ВАРИАНТ Я ИСПОЛЬЗОВАЛ РАНЬШЕ.
float x = Random.Range(0f, NPC.Stats.MaxWalkingDistance);
float z = Random.Range(0f, NPC.Stats.MaxWalkingDistance);
Vector3 newPosition = new Vector3(x, transform.position.y, z);
NAV_MESH_AGENT.SetDestination(newPosition);
*/
//СЕЙЧАС РЕШИЛ ПОПРОБОВАТЬ ВОТ ТАК.
//+ Тут его мы не отпускаем от стартовой позиции. иначе он бы ушел через 30 минут в африку пешком)))
NAV_MESH_AGENT.SetDestination(new Vector3(
START_POSITION.x + Random.Range(0f, NPC.Stats.MaxWalkingDistance), //x
transform.position.y, //y
START_POSITION.z + Random.Range(0f, NPC.Stats.MaxWalkingDistance))); //z
//Обнуление таймера
_stayOnPosition = NPC.Stats.StayOnPosition;
}
}
//Преследование игрока
private void FollowingPlayer ()
{
//Включаем режим боя.
NPC.Stats.inCombat = true;
//Если наш моб убежал за максимальную дистанцию преследования -> заставляем его бежать на респаун, и отключаем режим боя.
if (_distanceToStartPosition > NPC.Stats.MaxFollowingDistance && NPC.Stats.inCombat)
{
//Вот как раз тут и пригодится нам переменная _frictionNumber
//Здесь НПЦ изначально был нейтральным, но когда мы его ударили(стр.205) и он стал агрессивным, и тут мы все возвращаем назад
if (NPC.Stats.Friction == NPC_STATS._friction.Agressive && _frictionNumber == 0)
NPC.Stats.Friction = (NPC_STATS._friction)_frictionNumber;
NAV_MESH_AGENT.SetDestination(START_POSITION);
NPC.Stats.inCombat = false;
//Обнуляем ему таймер на тупняк.
_stayOnPosition = 0f;
//Ограничиваем обзор для того чтобы небыло бага, когда моб дрыгается из стороны в сторону, так как SetDestanation пересекаются
NPC.Stats.VisibleDistance = 2f;
}
//Или же бежим за игроком
else
NAV_MESH_AGENT.SetDestination(PLAYER_POSITION);
//Если дистанция до игрока уже позволяет бить игрока -> Бъем игрока
if (_distanceToPlayer <= NPC.Stats.AttackDistance)
Attack ();
}
//Бъем игрока здесь
private void Attack ()
{
//Если есть задержка перед ударом -> считаем ее.
if (_attackSpeed > 0)
_attackSpeed -= Time.deltaTime;
//Или же наносим игрока повреждения
else
{
//Кидаем монетку от 0 до 100 на промах
float randChance = Random.Range (0f, 100f);
//Если выпало больше, то бьем (если <= то промах)
if (randChance > NPC.Stats.MissChance)
{
//Снова выбрасываем монетку, только теперь на крит.
randChance = Random.Range (0f, 100f);
//Если выпало больше, то бьем обычный удар
if (randChance > NPC.Stats.AttackCriticalChance)
//атака во врага обычная
PLAYER_SCRIPT.TAKE_DAMAGE (Random.Range(NPC.Stats.MinDamage, NPC.Stats.MaxDamage));
else
//атака во врага критом
PLAYER_SCRIPT.TAKE_DAMAGE (Random.Range(NPC.Stats.MinDamage * 2, NPC.Stats.MaxDamage * 2));
}
else
//Можно вывести на экран, что атака не удалась
Debug.Log("NPC MISS");
//Обнуляем задержку между атаками.
_attackSpeed = NPC.Stats.AttackSpeed;
}
}
//Публичная переменная т.к получаем урон из другого скрипта.
public void TakeDamage (float Damage)
{
//Если наш тупоголовый нейтрал, и мы его ударяем то он становиться агрессивным
//151-152 строка возвращает положение на изначальное.
if (NPC.Stats.Friction == NPC_STATS._friction.Neutral)
NPC.Stats.Friction = NPC_STATS._friction.Agressive;
//Вводим НПЦ в режим боя
NPC.Stats.inCombat = true;
//Устанавливаем Таймер для выхода из боя, реализация его здесь нужна для постоянного обновления при получении урона
_timeOutBattle = 5f;
//И снова тут мы будем бросать монетку на паррирование удара.
float randChance = Random.Range (0f, 100f);
//Если монетка выкинула больше, то нпц не с паррировал удар
if (randChance > NPC.Stats.ParryChance)
{
//Снова монетка, теперь уже на блокировку удара
randChance = Random.Range (0f, 100f);
//Если больше то не блокировали...
if (randChance > NPC.Stats.BlockChance)
{
//Заводим локальную переменную под логику деления урона на броню
//пример: 44 урон, 100 брони.
//damageDivider = ((100 брони + 100 = 200) / 100) = 2
//HP -= 44 / (2) = 22.
//пример: 44 урон, 75 брони.
//Делитель = ((75 брони + 100 = 200) / 100) = 1.75
//ХП -= 44 / (1.75) = 25
//ХП ИГРОКА УРОН ДЕЛИТЕЛЬ
NPC.Stats.currentHealth -= Damage / ((NPC.Stats.Armor + 100) / 100);
}
else
Debug.Log("Attack Blocked");
}
else
Debug.Log("Parry Attack");
}
//Можете сами заменить на что хотите, мне подходит и такой вариант.
//Если у нас мышка находится на объекте и мы нажали ЛКМ. Добавляем в таргет этот объект
//Если нажимаем ПКМ то добавляем в таргет объект и включаем атаку.
void OnMouseOver ()
{
if (Input.GetButtonDown("Fire1"))
PLAYER_SCRIPT.Target = this.gameObject;
if (Input.GetButtonDown("Fire2"))
{
PLAYER_SCRIPT.blaAttack = true;
PLAYER_SCRIPT.Target = this.gameObject;
}
}
}
TEST PLAYER
Синтаксис:
Используется csharp
//Простенький скрипт игрока. Чисто для проверок
using UnityEngine;
public class PLAYER : MonoBehaviour
{
private float _currentHealth; //Текущее ХП
public float MaxHealth; //Максимальное ХП
public bool isDead; //Мертв или нет
public bool blaAttack; //Атакуем ли врага (bla ничего не значит, просто чтобы не совподало с методом название)
public GameObject Target; //Цель наша
float _attackDelay; //Задержка при атаки
void Awake () //http://unity3d.com/learn/tutorials/modules/beginner/scripting/awake-and-start
{
tag = "Player"; name = "Player"; //Присваение имени и тэга
_currentHealth = MaxHealth; //Присвоение текущему ХП максимального ХП
}
void Update () //http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate
{
if (!isDead)
{
if (Target && Input.GetButtonDown("Cancel")) //Проверка на наличие цели и нажатие на ESCAPE (Esc)
{
Target = null; //Убираем таргет
blaAttack = false; //Убираем атаку
_attackDelay = 2f; //Обнуляем таймер
}
if (Target && blaAttack && !Target.GetComponent<NPC>().Stats.isDead) //Если есть цель, если атакуем, если НПЦ не мертв
Attack(); //Вызов метода атаки (почему то всегда когда я пишу метод, мне на голову приходит "МЕТАДОН!!!" (Я НЕ НАРКОМАН!!!) <img src="./images/smilies/4.gif" alt=":D" title="Гы" />
}
}
//Метод получения урона ничего сложного. Есть входящая переменная типа Float которая записывает в себя урон
public void TAKE_DAMAGE (float Damage)
{
_currentHealth -= Damage;
}
//Атака
private void Attack ()
{
if (Target.GetComponent<NPC>().Stats.Friction != NPC_STATS._friction.Friend)
{
//Таймер
if (_attackDelay > 0)
_attackDelay -= Time.deltaTime;
else
{
Target.GetComponent<NPC_AI>().TakeDamage (Random.Range(1f, 10f)); //Наносим урон от 1 до 10
_attackDelay = 2f; //Обнуляем таймер
}
}
else
{
//Так как Атака у нас включается из НПЦ, придется добавить отключение атаки.
//Или там сделать проверку, но мне и так норм <img src="./images/smilies/4.gif" alt=":D" title="Гы" />
Debug.Log("Извини, я немогу бить друзей!");
blaAttack = false;
}
}
}
using UnityEngine;
public class PLAYER : MonoBehaviour
{
private float _currentHealth; //Текущее ХП
public float MaxHealth; //Максимальное ХП
public bool isDead; //Мертв или нет
public bool blaAttack; //Атакуем ли врага (bla ничего не значит, просто чтобы не совподало с методом название)
public GameObject Target; //Цель наша
float _attackDelay; //Задержка при атаки
void Awake () //http://unity3d.com/learn/tutorials/modules/beginner/scripting/awake-and-start
{
tag = "Player"; name = "Player"; //Присваение имени и тэга
_currentHealth = MaxHealth; //Присвоение текущему ХП максимального ХП
}
void Update () //http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate
{
if (!isDead)
{
if (Target && Input.GetButtonDown("Cancel")) //Проверка на наличие цели и нажатие на ESCAPE (Esc)
{
Target = null; //Убираем таргет
blaAttack = false; //Убираем атаку
_attackDelay = 2f; //Обнуляем таймер
}
if (Target && blaAttack && !Target.GetComponent<NPC>().Stats.isDead) //Если есть цель, если атакуем, если НПЦ не мертв
Attack(); //Вызов метода атаки (почему то всегда когда я пишу метод, мне на голову приходит "МЕТАДОН!!!" (Я НЕ НАРКОМАН!!!) <img src="./images/smilies/4.gif" alt=":D" title="Гы" />
}
}
//Метод получения урона ничего сложного. Есть входящая переменная типа Float которая записывает в себя урон
public void TAKE_DAMAGE (float Damage)
{
_currentHealth -= Damage;
}
//Атака
private void Attack ()
{
if (Target.GetComponent<NPC>().Stats.Friction != NPC_STATS._friction.Friend)
{
//Таймер
if (_attackDelay > 0)
_attackDelay -= Time.deltaTime;
else
{
Target.GetComponent<NPC_AI>().TakeDamage (Random.Range(1f, 10f)); //Наносим урон от 1 до 10
_attackDelay = 2f; //Обнуляем таймер
}
}
else
{
//Так как Атака у нас включается из НПЦ, придется добавить отключение атаки.
//Или там сделать проверку, но мне и так норм <img src="./images/smilies/4.gif" alt=":D" title="Гы" />
Debug.Log("Извини, я немогу бить друзей!");
blaAttack = false;
}
}
}