私はいくつかのブループリントロジックを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);
}
}
}
}
コンパイル時に、InvocationListが無効であるためにクラッシュすることがありますが、その問題に関する情報はあまりわかりません。結論としては、OnNextBladeButtonPressedが呼び出されるべきときに呼び出されません。
質問のコードに問題はありません。一見すると、問題は別の場所にある可能性があります。放送の瞬間にAWeaponMakerが削除されていたのではないかと思います。