在c# Unity中可以将脚本设置为函数的参数吗?

问题描述 投票:0回答:4

我在两个脚本中具有相同的功能 - Attack(),我想从具有此功能的类继承它们。所以我的问题是可以将脚本设置为 c# Unity 中函数的参数吗?

public void Attack()
{
    _animator.SetTrigger("Attack");

    Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(_attackPoint.position, _attackRange, _enemyLayer);
    foreach (Collider2D enemy in hitEnemies)
    {
        enemy.GetComponent<PlayerAnimator>().TakeDamage(_attackDamage);// in second script there is <EnemyAnimator>
    }
}
c# unity3d
4个回答
0
投票

是的,在unity c#中可以将脚本设置为函数的参数。您需要做的就是首先是脚本的名称,然后是您想要给它起的名字。像这样:

public void Attack(EnemyAnimator enemyAnimator)
{
    _animator.SetTrigger("Attack");

    Collider2D[] hitEnemies = 
    Physics2D.OverlapCircleAll(_attackPoint.position, _attackRange, 
    _enemyLayer);
    foreach (Collider2D enemy in hitEnemies)
    {
        enemy.GetComponent<PlayerAnimator>().TakeDamage(_attackDamage);
    }
}

0
投票

如果我理解正确的话,你的 EnemyAnimator 和 PlayerAnimator 类都是从 Animator 类派生的。如果你想将 Attack 脚本与两个 Animators 一起使用,你需要添加一个通用的 Animator 对象作为参数:

public void Attack(Animator animator)
{
    _animator.SetTrigger("Attack");

    Collider2D[] hitEnemies = 
    Physics2D.OverlapCircleAll(_attackPoint.position, _attackRange, 
    _enemyLayer);
    foreach (Collider2D enemy in hitEnemies)
    {
        enemy.GetComponent<animator>().TakeDamage(_attackDamage);
    }
}

这样你就可以在调用函数时同时使用 EnemyAnimator 和 PlayerAnimator 作为参数。

不同班级的例子

如果你想使用另一种类型的脚本,你需要查找脚本派生自哪个类。例如,标准的 Unity 脚本源自类 MonoBehaviour。然后你只需要把前面例子中的 Animator 基类换成你的其他基类。

public class NewBehaviourScript : MonoBehaviour { 
//Class name after ":" is the class your script is derived from.

0
投票

那是 OOP 基础知识——在这种情况下,您主要有两个选择:

你应该有

  • 一个接口,如果它只是关于具有相同的方法签名但完全不同的行为

    public interface IDamageable
    {
        void TakeDamage(float damage);
    }
    

    然后

    public class PlayerAnimator : MonoBehaviour, IDamageable
    {
        public void TakeDamage(float damage)
        {
            Debug.Log($"I'm a player and do a certain thing when I take {damage} amount of damage");
        }
    }
    
    public class EnemyAnimator : MonoBehaviour, IDamageable
    {
        public void TakeDamage(float damage)
        {
            Debug.Log($"I'm an enmy and do something completely different when I take {damage} amount of damage");
        }
    }
    
  • 通过继承并拥有一个共同的父类,它已经实现了共同的行为,然后可以扩展——如果需要的话

    // Careful with this naming in that case!
    public class Damageable : MonoBehaviour
    {
        virtual void TakeDamage(float damage)
        {
            Debug.Log("This is the common default behavior for my inheritors - except the overwrite or extend it");
        }
    }
    

    public class PlayerAnimator : Damageable 
    {
        public override void TakeDamage(float damage)
        {
            // First call the default implementation
            base.TakeDamage(damage);
    
            Debug.Log($"I'm a player and do some additional stuff");
        }
    }
    
    public class EnemyAnimator : Damageable 
    {
        public override void TakeDamage(float damage)
        {
            Debug.Log($"I'm an enmy and decided to not do the default thing but something completely different");
        }
    }
    

    在这里,如果您不需要

    EnemyAnimator
    PlayerAnimator
    之间的任何不同行为,那么答案很简单:那就坚持一个班级吧!

然后我会去

public void Attack()
{
    _animator.SetTrigger("Attack");

    var hitEnemies = Physics2D.OverlapCircleAll(_attackPoint.position, _attackRange, _enemyLayer);

    foreach (Collider2D enemy in hitEnemies)
    {
        // OPTION A
        if(enemy.TryGetComponent<IDamagable>(out var damageable))
        // or OPTION B
        //if(enemy.TryGetComponent<Damagable>(out var damageable))
        {
            damageable.TakeDamage(_attackDamage)
        }
    }
}

0
投票

你在这里有各种各样的答案可以帮助你学到很多东西,我已经开始写一个并从字面上解决你的问题,尽管在大多数情况下我会采用不同的方法。话虽如此:

要将

Type
作为参数传递,您可以让您的方法接受泛型类型并将其约束到您的基类。

public class AttackManager : MonoBehaviour
{
    public void Attack<T>(float damage) where T : AnimatorBase
    {
       GetComponent<T>().TakeDamage(damage);
    }
}

假设您的

PlayerAnimator
EnemyAnimator
来自基类,例如:

public class AnimatorBase : MonoBehaviour
{
    public void TakeDamage(float damage)
    {
        //
    }
}
public class PlayerAnimator : AnimatorBase
public class EnemyAnimator : AnimatorBase

现在您只需将函数称为:

    AttackManager attackManager;
    // Start is called before the first frame update
    void AnyMethod()
    {
        attackManager.Attack<PlayerAnimator>(1f);
    }

现在这就是您要传递类型的方式。尽管我没有看到我的示例是最佳方法的上下文。

© www.soinside.com 2019 - 2024. All rights reserved.