Unreal Engine 4: C ++ делегат не вызывается - PullRequest
5 голосов
/ 30 июня 2019

Я работал над преобразованием некоторой логики проекта в C ++.У меня есть кнопка.Кнопка может быть нажата в VR и имеет делегата, который вызывается для уведомления любых зарегистрированных функций о том, что произошло нажатие кнопки.Вот как делегат объявляется в классе AButtonItem.h.

#pragma once
#include "BaseItem.h"
#include "ButtonItem.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FButtonItemPressedSignatrue);

UCLASS()
class AButtonItem : public ABaseItem
{
    GENERATED_BODY()

protected:
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Touch)
    float myMaxButtonPress;

public:

    UPROPERTY(EditAnywhere, Category = Callback)
    FButtonItemPressedSignatrue ButtonItem_OnPressed;
};

Функция широковещания делегата затем вызывается при нажатии кнопки следующим образом:

ButtonItem_OnPressed.Broadcast();

(ЭтоФункция должна вызываться вызывающе, потому что у меня есть оператор отладки, который печатает прямо перед вызовом. Также важно отметить, что все это работало, когда было логикой светокопии.)

Здесь я пытаюсь зарегистрироваться в делегате.и как я объявил функцию, которая будет вызываться:

WeaponMaker.h:

UFUNCTION()
void OnNextBladeButtonPressed();

WeaponMaker.cpp:

void AWeaponMaker::BeginPlay()
{
    Super::BeginPlay();

    TArray<USceneComponent*> weaponMakerComponents;
    this->GetRootComponent()->GetChildrenComponents(true, weaponMakerComponents);

    for (int componentIndex = 0; componentIndex < weaponMakerComponents.Num(); componentIndex++)
    {
        if (weaponMakerComponents[componentIndex]->GetName().Equals("NextBladeButton") == true)
        {
            myNextBladeButton = (AButtonItem*)weaponMakerComponents[componentIndex];
            break;
        }
    }

    if (myNextBladeButton != NULL)
    {
        myNextBladeButton->ButtonItem_OnPressed.AddDynamic(this, &AWeaponMaker::OnNextBladeButtonPressed);
    }

}

Я поставил точку останова и печатьоператор в функции OnNextBladeButtonPressed, поэтому я должен сразу знать, когда он работает, но его никогда не происходит.Я также заново создал сам проект с нуля, но все же не повезло.Иногда при компиляции происходит сбой из-за недействительности InvocationList, но я также не нашел много информации по этому вопросу.Суть в том, что OnNextBladeButtonPressed не вызывается, когда это должно быть.

Редактировать: Здесь я вызываю функцию широковещания в моем коде AButtonItem.Кажется, его вызывают, так как я вижу вывод UE_LOG в консоли:

void AButtonItem::Tick(float deltaTime)
{
    FTransform buttonWorldTransform;
    FVector buttonLocalSpacePos;
    FVector ownerLocalSpacePos;
    FVector localDiff;
    float buttonPressAmount;

    if (myHasStarted == true)
    {
        Super::Tick(deltaTime);

        if (myButtonComponent != NULL)
        {
            if (myPrimaryHand != NULL)
            {
                //Get the world space location of the button.
                buttonWorldTransform = myButtonComponent->GetComponentTransform();

                //Convert the location of the button and the location of the hand to local space.
                buttonLocalSpacePos = buttonWorldTransform.InverseTransformPosition(myInitialOverlapPosition);
                ownerLocalSpacePos = buttonWorldTransform.InverseTransformPosition(myPrimaryHand->GetControllerLocation() + (myPrimaryHand->GetControllerRotation().Vector() * myPrimaryHand->GetReachDistance()));

                //Vector distance between button and hand in local space.
                localDiff = ownerLocalSpacePos - buttonLocalSpacePos;

                //Only interested in the z value difference.
                buttonPressAmount = FMath::Clamp(FMath::Abs(localDiff.Z), 0.0f, myMaxButtonPress);
                localDiff.Set(0.0f, 0.0f, buttonPressAmount);

                //Set the new relative position of button based on the hand and the start button position.
                myButtonComponent->SetRelativeLocation(myButtonInitialPosition - localDiff);

                //UE_LOG(LogTemp, Error, TEXT("buttonPressAmount:%f"), buttonPressAmount);
                if (buttonPressAmount >= myMaxButtonPress)
                {
                    if (myHasBeenTouchedOnce == false)
                    {
                        //Fire button pressed delegate
                        if (ButtonItem_OnPressed.IsBound() == true)
                        {
                            ButtonItem_OnPressed.Broadcast();
                            AsyncTask(ENamedThreads::GameThread, [=]()
                            {
                                ButtonItem_OnPressed.Broadcast();
                            });
                        }

                        myHasBeenTouchedOnce = true;
                        myButtonComponent->SetScalarParameterValueOnMaterials("State", 1.0f);
                        Super::VibrateTouchingHands(EVibrationType::VE_TOUCH);
                    }
                }
            }
            else
            {
                //Slowly reset the button position back to the initial position when not being touched.
                FVector newPosition = FMath::VInterpTo(myButtonComponent->GetRelativeTransform().GetLocation(), myButtonInitialPosition, deltaTime, 10.0f);
                myButtonComponent->SetRelativeLocation(newPosition);
            }
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 16 июля 2019

Прежде всего:

UPROPERTY(EditAnywhere, Category = Callback)
FButtonItemPressedSignatrue ButtonItem_OnPressed;

Это должно быть:

UPROPERTY(BlueprintAssignable, Category = Callback)
FButtonItemPressedSignatrue ButtonItem_OnPressed;

Для удобства.

Во-вторых, функция тика может быть вызвана до начала воспроизведения по ряду причин. Вы даже не будете транслироваться, если игра еще не началась. Поэтому, чтобы избежать, просто добавьте проверку в вашей функции галочки.

if(bHasBegunPlay)
{
  // .. your logics ...
}
1 голос
/ 05 июля 2019

Иногда при компиляции происходит сбой из-за недействительности InvocationList, но я также не нашел много информации по этому вопросу. Суть в том, что OnNextBladeButtonPressed не вызывается, когда это должно быть.

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

...