Unity3d Roguelike 2D: как расширить сценарий Enemy "OnCantMove" для атаки на стены?
Я впервые задаю вопрос здесь, в Stackru.
Я закончил официальный учебник Unity 3D "Roguelike 2D" и пытаюсь расширить его самостоятельно. Когда Player
пытается войти в стену, он вместо этого повреждает ее, в конце концов пробиваясь.
Я удалил звуки и команды аниматора для ясности.
protected override void OnCantMove<T> (T component)
{
Wall hitWall = component as Wall;
hitWall.DamageWall (wallDamage);
}
И когда Enemy
пытается войти в Player
Повреждает его, причиняя ему боль.
protected override void OnCantMove <T> (T component)
{
Player hitPlayer = component as Player;
hitPlayer.LoseFood (playerDamage);
}
playerDamage
устанавливается сценарием Enemy, и wallDamage
устанавливается скриптом Player (имеется в виду тот, кто наносит урон.) LoseFood
а также DamageWall
устанавливаются сценариями Player и Wall (т.е. оба устанавливаются тем, кто получает урон).
Я хочу Enemy
чтобы быть в состоянии повредить стены, как Player
является. Итак, я попытался изменить сценарий Enemy OnCantMove
часть чего-то вроде этого:
protected override void OnCantMove<T> (T component)
{
Wall hitWall = component as Wall;
hitWall.DamageWall (wallDamage);
Player hitPlayer = component as Player;
hitPlayer.LoseFood (playerDamage);
}
и это:
protected override void OnCantMove<T> (T component)
{
Wall hitWall = component as Wall;
Player hitPlayer = component as Player;
if (hitWall) {hitWall.DamageWall (wallDamage);}
else if (hitPlayer) {hitPlayer.LoseFood (playerDamage);}
}
Ни один из них не работал так, как я хотел. Я даже пытался заменить OnCantMove
функция Enemy
быть таким же, как когда Player
ударяется о стены, но это только убрало способность Enemy
должен был ударить Player
, не позволяя ему поразить стены. Что мне следует попробовать дальше, чтобы посмотреть, смогу ли я решить эту проблему?
Если мне удастся заставить это работать, я надеюсь, что смогу продолжить расширять эту игру и другими способами, но я очень новичок в этом. Спасибо за любую помощь и совет.
2 ответа
Проблема заключается в MoveEnemy-методе вражеского скрипта. Это вызывает AttemptMove<Player>
поэтому он будет отправлять только объект проигрывателя в метод OnCantMove. Не уверен, как бы я решил это, но вам, вероятно, нужно немного перестроить, чтобы получить желаемое поведение.
Спасибо! Я также закончил этот урок и решил расширить игру, чтобы узнать немного больше об Unity. Благодаря этой задаче я смог повторно кодировать код и заставить его работать как положено (см. Результат здесь)
Действительно, проблема была связана с AttempMove<Player>
как указал Jonatan Hedborg.
Из-за общего типа в AttemptMove <T> (int xDir, int yDir)
функция в MovingObject.cs
Я решил сделать так, чтобы он возвращал целое число, чтобы сказать, попадет ли он в упомянутый компонент или нет, аналогично:
protected virtual int AttemptMove <T> (int xDir, int yDir)
where T : Component
{
RaycastHit2D hit;
bool canMove = Move(xDir, yDir, out hit);
if (hit.transform == null)
return MOVE_ATTEMPT_NO_HIT;
T hitComponent = hit.transform.GetComponent<T>();
if (!canMove && hitComponent != null)
{
OnCantMove(hitComponent);
return MOVE_ATTEMPT_HIT;
}
return MOVE_ATTEMPT_NO_HIT;
}
MOVE_ATTEMPT_HIT
а также MOVE_ATTEMPT_NO_HIT
просто целочисленные константы, определенные в MovingObject.cs
как:
public const int MOVE_ATTEMPT_NO_HIT = 0;
public const int MOVE_ATTEMPT_HIT = 1;
Тогда это было просто вопрос изменения MoveEnemy()
от Enemy.cs
чтобы проверить, был ли поражен игрок, а если нет, то пытается прижать его к стене, аналогично:
....
// Check if player was hit
int hitCode = AttemptMove<Player>(xDir, yDir);
// if player was hit, exit (don't forget to skip next move)
if (hitCode == MOVE_ATTEMPT_HIT)
{
skipMove = true;
return;
}
// else, check if a wall was hit
else if (hitCode == MOVE_ATTEMPT_NO_HIT)
AttemptMove<Wall>(xDir, yDir);
skipMove = true;
}
Пропуск хода, как в оригинальном коде учебника, очень важен. В противном случае, поскольку зомби могут достичь точки, где у них нет стен, преграждающих путь, игрок действительно может застрять навсегда!