Unity3d Roguelike 2D:如何扩展敌人"OnCantMove"攻击城墙的脚本

本文关键字:quot OnCantMove 攻击 脚本 城墙 敌人 2D Roguelike 何扩展 扩展 Unity3d | 更新日期: 2023-09-27 18:02:20

这是我第一次在StackOverflow上提问。

我已经完成了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是由敌人脚本设置的,wallDamage是由玩家脚本设置的(意味着两者都是由造成伤害的人设置的)。LoseFoodDamageWall是由Player和Wall脚本设置的(也就是说两者都是由受到伤害的一方设置的)

我希望Enemy能够像Player一样破坏墙壁。所以,我试着改变敌人脚本的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);}
}

都没有按我想要的方式工作。我甚至试图将EnemyOnCantMove功能替换为与Player撞墙时相同的功能,但这只删除了Enemy必须撞击Player的能力,而没有使其能够撞击墙壁。接下来我该怎么做,看看能不能解决这个问题?

如果我设法让这个工作,我希望我可以继续扩大这款游戏在其他方面,以及,但我是一个新手。谢谢你的帮助和建议。

Unity3d Roguelike 2D:如何扩展敌人"OnCantMove"攻击城墙的脚本

问题出在敌人脚本的moveenemy -方法上。它调用AttemptMove<Player>,所以它只会向oncantmove方法发送一个播放器对象。我不知道如何解决它,但你可能需要重建一点,以获得你想要的行为

谢谢!我也完成了这个教程,并决定扩展游戏来学习更多关于Unity的知识。由于这个挑战,我能够重构代码并使其按预期工作(见这里的结果)

事实上,正如jonathan Hedborg指出的那样,这个问题与AttempMove<Player>有关。

由于MovingObject.csAttemptMove <T> (int xDir, int yDir)函数的泛型类型,我决定让它返回一个整数来告诉它是否击中了提到的组件,同样:

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_HITMOVE_ATTEMPT_NO_HIT是在MovingObject.cs中定义的整数常量:

public const int MOVE_ATTEMPT_NO_HIT  = 0;
public const int MOVE_ATTEMPT_HIT     = 1;

然后它只是一个简单的问题,从Enemy.cs更改MoveEnemy()来检查玩家是否被击中,如果没有,然后尝试将他移动到墙上,同样:

....
// 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;
}

跳过一个移动,就像在教程的原始代码中一样,这很重要。否则,因为僵尸可以到达一个没有墙挡道的地方,玩家就会永远被困住!