如何正确继承Unity的回调函数,如Awake(),Start()和Update和FixedUpdate()?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何正确继承Unity的回调函数,如Awake(),Start()和Update和FixedUpdate()?相关的知识,希望对你有一定的参考价值。

我已经创建了一个父类,我希望它具有与测试相关的所有函数,如果GameObject是基于水,空中等等......考虑到这个函数将被玩家以及其他游戏对象使用。但是,子类似乎没有正确地继承函数。

父脚本如下:

public class CharacterPhysic : MonoBehaviour {
  [SerializeField] protected Transform groundPoints;
  float grounRadius;
  private void Start ()
  {
     whatIsGround = LayerMask.GetMask("Ground");
     groundRadius = 0.01f;
  }
  protected bool IsGrounded()
  {
     Collider2D[] colliders = Physics2D.OverlapCircleAll(groundPoints.position, groundRadius, whatIsGround);
     if (colliders.Length > 0)
     {
         return true;
     }
     else return false;
  }
  private void FixedUpdate()
  {
     Debug.Log(IsGrounded());
  }
}

儿童剧本只是:

public class ErrantMove : CharacterPhysic {
  private void FixedUpdate()
  {
     Debug.Log(IsGrounded());
  }
}

将第一个脚本作为组件添加到Gameobject时(在定义grounPoint之后),Debug.Log(IsGrounded());返回TRUE

但是,当将第二个脚本作为组件添加到同一个Gameobject时(在定义grounPoint并删除第一个脚本之后),即使在相同的情况下,Debug.Log(IsGrounded());也会返回FALSE。

我希望能够在第二个脚本中添加移动功能,但这取决于测试它是否接地的能力。

答案

您的Start方法不会在子类中执行。如果您不打算使用父类,请将其移至子类。

public class ErrantMove : CharacterPhysic {

  protected void Start ()
  {
     whatIsGround = LayerMask.GetMask("Ground");
     groundRadius = 0.01f;
  }

  private void FixedUpdate()
  {
     Debug.Log(IsGrounded());
  }

}

您可以注意到,如果您将有多个子类,您将被迫在每个子类中初始化基类的Start方法,因此您可以创建一个virtual Start方法,然后在子类中调用它:

public class CharacterPhysic : MonoBehaviour {
  . . .
  protected virtual void Start ()
  {
     whatIsGround = LayerMask.GetMask("Ground");
     groundRadius = 0.01f;
  }
  protected bool IsGrounded()
  {
     Collider2D[] colliders = Physics2D.OverlapCircleAll(groundPoints.position, groundRadius, whatIsGround);
     return colliders.Length > 0;
  }
  . . .
}

public class ErrantMove : CharacterPhysic {

  protected override void Start()
  {
      base.Start();
  }

  private void FixedUpdate()
  {
     Debug.Log(IsGrounded());
  }

}

你可以去virtual/override方法,或使用new关键字“取消隐藏”儿童类的Start方法(我不知道new将如何表现在统一,所以最好与第一个一起)。

另一答案

您可以像使用普通的C#继承范例一样正确地继承Unity的回调函数,例如AwakeStartUpdate。这非常简单。

使基类的所有回调函数都为virtual

public class YourBaseClass : MonoBehaviour
{
    protected virtual void Awake()
    {
        Debug.Log("Awake Base");

    }

    protected virtual void Start()
    {
        Debug.Log("Start Base");
    }

    protected virtual void Update()
    {
        Debug.Log("Update Base");
    }

    protected virtual void FixedUpdate()
    {
        Debug.Log("FixedUpdate Base");
    }
}

对于将从基类派生的父类,也添加回调函数,但将它们标记为override。如果您需要调用基函数,请在父函数中执行任何其他操作之前使用base.FunctionName调用它:

public class Parent : YourBaseClass
{
    protected override void Awake()
    {
        base.Awake();
        Debug.Log("Awake Parent");
    }

    protected override void Start()
    {
        base.Start();
        Debug.Log("Start Parent");
    }

    protected override void Update()
    {
        base.Update();
        Debug.Log("Update Parent");
    }

    protected override void FixedUpdate()
    {
        base.FixedUpdate();
        Debug.Log("FixedUpdate Parent");
    }
}

以上是关于如何正确继承Unity的回调函数,如Awake(),Start()和Update和FixedUpdate()?的主要内容,如果未能解决你的问题,请参考以下文章

Tip8:Unity中诸如 Awake() Start() Update()等函数的 执行顺序

酷熊科技工作积累 ----------- Unity3d中的Awake()OnEnable()Start()等默认函数的执行顺序和生命周期

unity 中函数调用的顺序

Unity3D脚本中Start和Awake的区别

Unity - 脚本的 Awake() 是不是在其他脚本的 Start() 之前运行?

在 Unity 中,是在游戏开始之前还是在场景开始之前调用 Awake()?