簡體   English   中英

如何從派生的 class (C#) 中的抽象 class 調用動作?

[英]How do I invoke an Action from an abstract class in a derived class (C#)?

我正在嘗試調用派生的 class 中的操作,但沒有任何反應。

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()
    {

    }
}

這里是派生的 class

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 只是在調試 window 中打印一行,然后當我添加 CharacterInput 作為組件而不是 ExampleInput 時,它工作正常。 每次我左鍵單擊時都會打印。 但是我希望能夠將 CharacterInput 的子項作為組件添加到游戲 object 中,並在其中定義 OnWhatever 操作,但沒有任何反應。

如果您想確保它正常工作,請將您當前的方法隱藏更改為覆蓋。 將“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 中一樣),您必須使用 virtual 關鍵字。 否則,派生方法只會隱藏基本方法,但可能會在您無意中意外調用基本方法(例如 - 通過強制轉換或簡單地將其聲明為基本 class 類型 - 就像這里: 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 到事件.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM