unity3d 2020年统一二维:我如何让这个代码检查两个不同的组件?

pw136qt2  于 2023-03-19  发布在  其他
关注(0)|答案(1)|浏览(118)

我有一个攻击脚本,它检查对象是否有“敌人脚本”,如下所示:

// Damage them
foreach (Collider2D enemy in hitEnemies)
{
    // Debug log showing the attack connected
    Debug.Log("We hit " + enemy.name);`

    // the enemy takes damage from the player, could be rewritten
    enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
}

现在的问题是,它只检查对象是否有那个脚本,我还需要让它检查一个包含加载区域方法的boss脚本。
我可以让它只是一个敌人脚本或敌人装载区脚本。我的想法是,只有老板有敌人装载区脚本。如果我把它从“敌人.getComponent”改为“敌人. getComponent”,统一不再识别伤害,敌人不会死。
也许有一个更好的方法来加载老板死亡的场景,但我不知道是否有。
我不能在Unity中将字段留空,所以我不能在敌人脚本中设置加载区域代码。我如何才能让它检查两个不同的游戏对象?或者甚至,我如何才能重写代码来检查Unity中的标记?所以它不是查找敌人脚本,而是检查NPC是否被标记为敌人,然后受到伤害?
我试过用

enemy.GetComponent<Enemy || EnemyLoadArea>().TakeDamage(attackDamage);

以及

enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
enemy.GetComponent<EnemyLoadArea>().TakeDamage(attackDamage);

并且还尝试在组件从“”更改为〈“EnemyLoadArea”〉的情况下重用相同的foreach方法,但也不起作用。
我尝试过的每个不同的修复都返回错误,如“||无法使用”,或者
空引用异常:对象引用未设置为对象的示例PlayerAttack.Attack()(位于资产/脚本/播放器/PlayerAttack.cs:53)PlayerAttack.Update()(位于资产/脚本/播放器/PlayerAttack.cs:30)

km0tfn4u

km0tfn4u1#

如果你想从一个对象中检索一个组件,但你不确定这个对象是否真的有这个组件,你可以使用TryGetComponent()。如果对象有你要找的组件,它返回true,如果有,这个组件被赋给out参数。代码如下所示:

if (enemy.TryGetComponent<Enemy>(out Enemy _) ||
    enemy.TryGetComponent<EnemyLoadArea>(out EnemyLoadArea _))
{
    enemy.TakeDamage(attackDamage);
}

但是解决这个问题的更好的方法是使用interface重构类层次结构。interface的主要目的是将具有相关功能的类组合在一起。因为EnemyEnemyLoadArea都可能被攻击,所以这是为它们实现公共接口的最佳情况。您可以定义如下内容:

public interface IAttackable
{
    public void TakeDamage(float amount);
}

然后,您可以让EnemyEnemyLoadArea都实现该接口。

public class Enemy : MonoBehaviour, IAttackable
{
    // ...
    
    public void TakeDamage(float amount)
    {
        // Do something
    }
}

public class EnemyLoadArea : MonoBehaviour, IAttackable
{
    // ...
    
    public void TakeDamage(float amount)
    {
        // Do something
    }
}

稍后,要对可攻击对象造成伤害,你不需要关心它是Enemy还是EnemyLoadArea,你可以这样做:

if (enemy.TryGetComponent<IAttackable>(out IAttackable attackable))
{
    attackable.TakeDamage(attackDamage);
}

你可以在谷歌上找到更多关于interface的信息,或者快速浏览一下this answer on another question

相关问题