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

时间:2018-10-31 05:09:14

标签: c# function unity3d inheritance

我已经创建了一个父类,我希望它具有与测试GameObject是否接地,在水上,在空中等有关的所有功能...假定此功能将由玩家以及其他人使用游戏对象。但是,子类似乎无法正确继承功能。

父脚本如下:

do {
    print(String(data: data, encoding: .utf8))
    let response = try JSONDecoder().decode(TrackerResponse.self, from: data)
    print(response.data?.id)

} catch let jsonErr {
    print("Error Serializing JSON:", jsonErr)
}

子脚本只是:

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());
  }
}

将第一个脚本作为组件添加到游戏对象(定义了grounPoint之后)时,public class ErrantMove : CharacterPhysic { private void FixedUpdate() { Debug.Log(IsGrounded()); } } 返回 TRUE

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

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

2 个答案:

答案 0 :(得分:3)

您可以像使用普通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");
    }
}

答案 1 :(得分:1)

您的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的表现如何,所以最好选择第一个)。