1

这是我第一次在 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由 Enemy 脚本wallDamage设置,由 Player 脚本设置(意味着两者都由造成伤害的一方设置。)由 PlayerLoseFoodDamageWallWall 脚本设置(意味着两者都由受到伤害的一方设置。)

我希望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,而不会使其撞墙。接下来我应该尝试什么,看看我是否能解决这个问题?

如果我设法让它发挥作用,我希望我也可以继续以其他方式扩展这款游戏,但我对此很陌生。感谢您的任何帮助和建议。

4

2 回答 2

1

问题在于敌人脚本的 MoveEnemy 方法。它调用AttemptMove<Player>,因此它只会将玩家对象发送到 OnCantMove 方法。不知道我会如何解决它,但你可能需要重新构建一点以获得你想要的行为。

于 2015-07-13T09:42:08.650 回答
1

谢谢!我也完成了本教程并决定扩展游戏以了解更多关于 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()fromEnemy.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;
}

在教程的原始代码中跳过一个动作很重要。否则,由于僵尸可以到达没有墙挡路的地步,玩家真的会永远被卡住!

于 2016-05-19T17:58:40.267 回答