Как правильно наследовать функции обратного вызова Unity, такие как Awake (), Start () и Update и FixedUpdate ()? - PullRequest
0 голосов
/ 31 октября 2018

Я создал родительский класс, который, как я ожидаю, будет иметь все функции, связанные с тестированием, если GameObject заземлен, в воде, на воздухе и т. Д., Учитывая, что эти функции будут использоваться игроком, а также другими GameObjects. Однако дочерний класс, похоже, не наследует должным образом функции.

Родительский скрипт выглядит следующим образом:

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 даже в тех же обстоятельствах.

Я ожидаю, что смогу добавить функции движения во второй скрипт, но это зависит от способности проверить, заземлен ли он.

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Вы можете должным образом наследовать функции обратного вызова Unity, такие как Awake, Start и Update, как если бы вы использовали обычную парадигму наследования C #. Это очень просто.

Сделать все функции обратного вызова для базового класса равными 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");
    }
}
0 голосов
/ 31 октября 2018

Ваш метод 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 будет вести себя в единстве, поэтому лучше перейти к первому) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...