Зміст курсу
Бійцівська гра в Unity
Бійцівська гра в Unity
Стан атаки
public class AttackState : State
{
string attackStateName;
bool isAttacking;
Animator animator;
Transform transform;
float range;
int damage;
LayerMask playerLayer;
public AttackState(Transform t, Animator animator, LayerMask playerLayer, string attackStateName, int damage, float range = 2.1f)
{
this.animator = animator;
this.attackStateName = attackStateName;
this.range = range;
transform = t;
this.damage = damage;
this.playerLayer = playerLayer;
}
public override void StartState()
{
isStateFinished = false;
animator.SetBool(attackStateName, true);
isAttacking = false;
}
public override void EndState()
{
animator.SetBool(attackStateName, false);
}
public override void UpdateState(float deltaTime)
{
Attack();
}
public override void StartAction()
{
isAttacking = true;
}
public override void FinishMovement()
{
isAttacking = false;
}
void Attack()
{
if (!isAttacking) return;
RaycastHit2D rayCastHit = Physics2D.Raycast(transform.position, Vector2.right * transform.localScale.x, range, playerLayer);
if (rayCastHit)
{
if (rayCastHit.transform.TryGetComponent(out IGetAttacked getAttacked))
{
getAttacked.GetAttacked(damage);
isAttacking = false;
}
}
}
}
Пояснення класу AttackState
Клас AttackState
є специфічним станом, який обробляє поведінку атаки ворога. Цей клас наслідує від класу State
і включає методи для початку, оновлення та завершення стану атаки, а також обробки дії атаки.
Визначення класу та змінні-члени
Визначення класу:
public class AttackState : State
;
Цей клас наслідує від класу State
, що означає, що він повинен реалізувати абстрактні методи, визначені в State
.
Змінні-члени:
string attackStateName;
Ім'я стану атаки, яке використовується в аніматорі.
bool isAttacking;
Прапорець, що вказує, чи ворог зараз атакує.
Animator animator;
Контролює анімації.
Transform transform;
Трансформація ворога, використовується для позиціонування та променевого відстеження.
float range;
Діапазон атаки.
int damage;
Шкода, завдана атакою.
LayerMask playerLayer;
Маска шару, що використовується для ідентифікації гравця.
Конструктор
Конструктор ініціалізує AttackState
з необхідними компонентами: Transform
для позиціонування, Animator
для анімацій, маска шару для ідентифікації гравця, ім'я стану атаки, значення шкоди та діапазон атаки. Він встановлює ці значення відповідним змінним-членам.
Метод StartState
Цей метод встановлює isStateFinished
в false
, запускає анімацію атаки, встановлюючи відповідний булевий параметр в аніматорі в true
, і скидає прапорець isAttacking
в false
.
Метод EndState
Цей метод зупиняє анімацію атаки, встановлюючи відповідний булевий параметр в аніматорі в false
.
Метод UpdateState
Цей метод викликається кожен кадр і запускає метод Attack
для виконання дії атаки.
Метод StartAction
Цей метод встановлює isAttacking
в true
, вказуючи, що дія атаки розпочалася.
Метод FinishMovement
Цей метод встановлює isAttacking
в false
, вказуючи, що дія атаки завершилася.
Метод Attack
Цей метод виконує дію атаки. Якщо isAttacking
дорівнює true
, він кидає промінь у напрямку, в якому дивиться ворог. Якщо промінь влучає в об'єкт на playerLayer
, він викликає метод GetAttacked
на влученому об'єкті, завдаючи шкоди та завершуючи дію атаки.
Чому ми зробили це так
-
Контроль над поведінкою атаки: Прапорець
isAttacking
дозволяє точно контролювати, коли повинна відбутися атака, роблячи поведінку більш чутливою до подій гри; -
Динамічне виконання атаки: Постійно оновлюючи стан атаки ворога,
AttackState
забезпечує точну та динамічну атаку на гравця; -
Інтеграція анімації: Використання параметрів аніматора забезпечує правильну синхронізацію анімацій ворога з його атаками, надаючи плавний та реалістичний досвід.
Як це працює в контексті
Вхід у стан атаки: Коли ворог входить у AttackState
, викликається метод StartState
, запускаючи анімацію атаки та скидаючи прапорець isAttacking
.
Під час атаки: Метод UpdateState
викликається кожен кадр. Він запускає метод Attack
, щоб перевірити, чи повинна відбутися атака.
Початок атаки: Метод StartAction
встановлює isAttacking
в true
, дозволяючи методу Attack
виконати дію атаки.
Виконання атаки: Метод Attack
кидає промінь для виявлення гравця та завдає шкоди, якщо гравець влучений.
Завершення атаки: Метод FinishMovement
встановлює isAttacking
в false
, зупиняючи дію атаки.
Вихід зі стану атаки: Коли ворог залишає AttackState
, викликається метод EndState
, зупиняючи анімацію атаки.
Структуруючи AttackState
таким чином, ми забезпечуємо, що ворог може виконувати чутливі та динамічні атаки на гравця, з плавними переходами між анімаціями та станами.
Перехід Close:
closeTransition = new Transition(() =>
{
return (ThresholdDistance >= Mathf.Abs(transform.position.x - player.position.x));
}, new StatePourcentage(attack2, 50f), new StatePourcentage(attack1, 50f));
stateManager.AddStateTransition(idle, closeTransition);
stateManager.AddStateTransition(idle, FarAwayTransition);
stateManager.AddStateTransition(dashState, toIdleTransition);
stateManager.AddStateTransition(dashState, finishRunning);
stateManager.AddStateTransition(runState, finishRunning);
stateManager.AddStateTransition(attack2, toIdleTransition);
stateManager.AddStateTransition(attack1, toIdleTransition);
closeTransition:
Цей перехід перевіряє, чи знаходиться гравець на певній горизонтальній відстані (ThresholdDistance
) від ворога.
Якщо умова виконується, він випадково переходить до attack1
або attack2
з рівною ймовірністю (по 50% кожен);
Приклад коду:
```csharp
closeTransition = new Transition(() =>
{
return (ThresholdDistance >= Mathf.Abs(transform.position.x - player.position.x));
}, new StatePourcentage(attack2, 50f), new StatePourcentage(attack1, 50f));
```
Додавання closeTransition до стану Idle:
stateManager.AddStateTransition(idle, closeTransition);
Цей рядок додає closeTransition
до стану idle
, дозволяючи машині станів перевіряти цю умову, коли ворог знаходиться в стані очікування.
Чому ми зробили це так
Система переходів дозволяє ворогу переходити в стан атаки на основі близькості гравця, підвищуючи залученість. Ймовірнісний підхід до вибору між різними атаками додає непередбачуваності, збільшуючи складність та інтерес гри.
Як це працює в контексті
Стан очікування:
Поки ворог знаходиться в стані idle
, він постійно перевіряє, чи знаходиться гравець в межах ThresholdDistance
за допомогою closeTransition
.
Якщо гравець достатньо близько, closeTransition
спрацьовує, і ворог переходить до attack1
або attack2
.
Стан атаки:
Опинившись у attack1
або attack2
, ворог виконує атаку.
Після завершення атаки існуючий toIdleTransition
повертає ворога в стан idle
, готового знову перевірити умову closeTransition
.
Додавши цей closeTransition
, ми забезпечуємо, що ворог може більш динамічно і непередбачувано взаємодіяти з гравцем, коли гравець знаходиться в близькому діапазоні. Це покращує ігровий процес, роблячи поведінку ворога більш чутливою та захоплюючою.
Дякуємо за ваш відгук!