【问题标题】:Unity3d Roguelike 2D: How to expand on Enemy "OnCantMove" script to attack walls?Unity3d Roguelike 2D:如何扩展 Enemy “OnCantMove”脚本来攻击墙壁?
【发布时间】:2015-10-01 12:07:35
【问题描述】:

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

我希望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);}
}

两者都没有按照我希望的方式工作。我什至尝试将EnemyOnCantMove 功能替换为与Player 撞墙时相同,但这只会删除Enemy 必须撞到Player 的能力,而无需启用它撞墙。接下来我应该尝试什么,看看我是否能解决这个问题?

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

【问题讨论】:

标签: c# unity3d unity3d-2dtools roguelike


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    谢谢!我也完成了本教程并决定扩展游戏以了解更多关于 Unity 的信息。由于这个挑战,我能够重构代码并使其按预期工作(见结果here

    确实,正如Jonatan Hedborg 指出的那样,该问题与AttempMove&lt;Player&gt; 有关。

    由于MovingObject.cs 中的AttemptMove &lt;T&gt; (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;
    

    然后只需将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;
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      • 2018-09-15
      • 2020-06-12
      • 2020-02-24
      相关资源
      最近更新 更多