Как вызвать действие из абстрактного класса в производном классе (C#)? - PullRequest
0 голосов
/ 28 апреля 2020

Я пытаюсь вызвать Действия в производном классе, но ничего не происходит.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

[RequireComponent(typeof(PlayerInput))]
public abstract class CharacterInput : MonoBehaviour
{
    protected PlayerInput input;

    protected Action<InputAction.CallbackContext> OnMove;
    protected Action<InputAction.CallbackContext> OnAttack;
    protected Action<InputAction.CallbackContext> OnSpecial;
    protected Action<InputAction.CallbackContext> OnBlock;
    protected Action<InputAction.CallbackContext> OnGrab;
    protected Action<InputAction.CallbackContext> OnJump;

    // Start is called before the first frame update
    void Start()
    {
        input = GetComponent<PlayerInput>();
        InputActionMap fighterMap = input.actions.FindActionMap("Fighter");
        fighterMap.FindAction("Move").performed += OnMove;
        fighterMap.FindAction("Attack").performed += OnAttack;
        fighterMap.FindAction("Special").performed += OnSpecial;
        fighterMap.FindAction("Block").performed += OnBlock;
        fighterMap.FindAction("Grab").performed += OnGrab;
        fighterMap.FindAction("Jump").performed += OnJump;
    }

    // Update is called once per frame
    void Update()
    {

    }
}

Вот производный класс

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class ExampleInput : CharacterInput
{
    // Start is called before the first frame update
    void Start()
    {
        OnAttack = callbackContext => Debug.Log(callbackContext.performed);
    }
    // Update is called once per frame
    void Update()
    {

    }
}

"Атака" привязана к левому щелчку. Сначала я сделал CharacterInput не абстрактным и определил OnAttack, чтобы просто напечатать строку в окне отладки, затем, когда я добавил CharacterInput в качестве компонента вместо ExampleInput, все заработало нормально. Печатается каждый раз, когда я щелкаю левой кнопкой мыши Но я хочу иметь возможность добавлять дочерние элементы CharacterInput в качестве компонентов к игровому объекту и определять действия OnWh независимо от этого, но ничего не происходит.

1 Ответ

1 голос
/ 28 апреля 2020

Если вы хотите убедиться, что он работает правильно, измените текущий метод, скрывая его на переопределение. Добавьте ключевое слово «virtual» в базовый метод Start ().

virtual void Start()
{
    input = GetComponent<PlayerInput>();
    InputActionMap fighterMap = input.actions.FindActionMap("Fighter");
    fighterMap.FindAction("Move").performed += OnMove;
    fighterMap.FindAction("Attack").performed += OnAttack;
    fighterMap.FindAction("Special").performed += OnSpecial;
    fighterMap.FindAction("Block").performed += OnBlock;
    fighterMap.FindAction("Grab").performed += OnGrab;
    fighterMap.FindAction("Jump").performed += OnJump;
}

Затем добавьте ключевое слово override к производному методу и в конце вызовите base.Start ().

override void Start()
{
    OnAttack = callbackContext => Debug.Log(callbackContext.performed);
    base.Start();
}

В C# неабстрактные методы не переопределяются автоматически (как это работает в Java), и вы должны использовать виртуальное ключевое слово. В противном случае производный метод просто скрывает базовый метод, но можно случайно вызвать базовый метод, когда вы его не имеете в виду (например, путем приведения или просто объявив его как тип базового класса - как здесь: https://dotnetfiddle.net/FOeUL9). Вот почему это может вызвать различные проблемы, поэтому избегайте этого, если можете.

Есть еще немного информации о разнице между ними: https://www.geeksforgeeks.org/difference-between-method-overriding-and-method-hiding-in-c-sharp/

В вашем случае, скорее всего, вашей главной проблемой было то, что производный метод не его базовый метод вызывается base.Start(), поэтому оператор fighterMap.FindAction("Attack").performed += OnAttack; никогда не вызывался. Скрытие также может быть проблемой.

Редактировать: Мое плохое, base.Start(), вероятно, должно быть в конце производного метода, а не в начале, так как это базовый метод, который создает подписки на события - без перед инициализацией обработчика события OnAction он просто подписывается на событие null.

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