[英]Unreal Engine 4: C++ Delegate not being called
I've been working on converting some blueprint logic over to C++. 我一直在努力将一些蓝图逻辑转换为C ++。 One of the things I have is a button. 我有一件事就是一个按钮。 The button can be pressed in VR and has a delegate that is called to notify any registered functions that the button press occurred. 可以在VR中按下该按钮,并且具有一个代理,该代理被调用以通知任何已注册的功能按钮按下发生。 Here is how the delegate is declared in the AButtonItem.h class. 以下是在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;
};
The delegate's broadcast function is then being called when the button is pressed like so: 然后在按下按钮时调用委托的广播功能,如下所示:
ButtonItem_OnPressed.Broadcast();
(This function should defiantly be called because I have a debug statement that prints right before the call. Its also important to note this was all working when it was blueprint logic.) (这个函数应该被调用,因为我有一个在调用之前打印的调试语句。同样重要的是要注意这是蓝图逻辑时的全部工作。)
Here is where I try to register with the delegate and how I declared the function that will be called: 这是我尝试向委托注册的地方,以及我如何声明将被调用的函数:
WeaponMaker.h: WeaponMaker.h:
UFUNCTION()
void OnNextBladeButtonPressed();
WeaponMaker.cpp: 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);
}
}
I put a breakpoint and a print statement in the function OnNextBladeButtonPressed so I should immediately know when it works but its never happening. 我在函数OnNextBladeButtonPressed中放了一个断点和一个print语句,所以我应该立即知道它何时起作用但它永远不会发生。 I also re-created the blueprint itself from scratch but still no luck. 我也从零开始重新创建了蓝图,但仍然没有运气。 Sometimes on compile I get a crash due to the InvocationList being invalid but I haven't found much info on that issue either. 有时在编译时我会因为InvocationList无效而崩溃,但我也没有找到关于该问题的更多信息。 Bottom line is, OnNextBladeButtonPressed is not getting called when it should be. 最重要的是,OnNextBladeButtonPressed未应该被调用。
Edit: Here is where I call the broadcast function in my AButtonItem code. 编辑:这是我在AButtonItem代码中调用广播函数的地方。 It seems to be getting called since i see the UE_LOG output in the console: 它似乎被调用,因为我在控制台中看到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);
}
}
}
}
First of all: 首先:
UPROPERTY(EditAnywhere, Category = Callback)
FButtonItemPressedSignatrue ButtonItem_OnPressed;
This should be: 这应该是:
UPROPERTY(BlueprintAssignable, Category = Callback)
FButtonItemPressedSignatrue ButtonItem_OnPressed;
For convenience. 为了方便。
Secondly the tick function may be called before begin play is executed for a number of reasons. 其次,可以在执行开始播放之前调用tick函数,原因有很多。 Your even't won't be broadcasted if the game hasn't begin play yet. 如果游戏还没有开始游戏,你甚至不会被广播。 So to avoid just add a check in your tick function. 所以,为了避免只在勾选函数中添加一个检查。
if(bHasBegunPlay)
{
// .. your logics ...
}
Sometimes on compile I get a crash due to the InvocationList being invalid but I haven't found much info on that issue either. 有时在编译时我会因为InvocationList无效而崩溃,但我也没有找到关于该问题的更多信息。 Bottom line is, OnNextBladeButtonPressed is not getting called when it should be. 最重要的是,OnNextBladeButtonPressed未应该被调用。
I don't see any issue in the code from the question. 我在问题的代码中没有看到任何问题。 At my glance, the issue could be in different location. 在我看来,问题可能出在不同的位置。 I would suspect that AWeaponMaker had been deleted at moment of broadcasting. 我怀疑AWeaponMaker在广播时已被删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.