UE4 FAQ Summary

UE4 VS system cannot find the file specified

You can right-click the solution to set the startup item Set as Startup Project

UE4 outputs Chinese garbled characters

VS uninstalls the Chinese language pack and installs the English language pack

UE4C++ project packaging pop-up web page

Because VS2022 is installed, you need to uninstall and reinstall VS2019

UE4 compile too card

You can install UE4 and VS on solid state drives, as well as projects. This can be several times faster

UE4 cannot find Interfaces/IPluginManager.h

Need to add "Projects" below

PublicDependencyModuleNames.AddRange(
    new string[]
    {
        "Core",
        // ... add other public dependencies that you statically link with here ...
        "Projects"
    }
);

UE4C++ multithreading

1. The new UChessAIAsyncNode class inherits from UBlueprintAsyncActionBase

Note: Blueprint nodes with a clock icon are called asynchronous nodes, which need to be inherited from the above class

2. Declare dynamic multicast delegation

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FChessAIMuitDynamicDele, FBestMove, chessBest);

Description: Declared outside the class, this macro has three parameters (delegate to be bound, return value type, return value name)

For details, see: UE4 commission

3. Create a delegate that needs to be bound

public:
	UPROPERTY(BlueprintAssignable)
	FChessAIMuitDynamicDele Complete;

Explanation: This thing needs to be made public, otherwise it cannot be called elsewhere after it is private by default

Explanation 2: BlueprintAssignable means a dedicated entrusted node

Note 3: FChessAIMuitDynamicDele can be customized but it should be the same as step 2 above

Explanation 4: The name of Complete can be chosen casually, but it is actually the output parameter of the node

4. Declare asynchronous nodes

UFUNCTION(BlueprintCallable, Category = "ChessAI")
static UChessAIAsyncNode* ChessAIAlphaBeta(AChessAIBase *chess, const int max_depth);

Explanation: Similar to ordinary nodes, in fact, there is no need to return a value, just void, the main thing is to pay attention to the parameters that need to be used

5. Implement asynchronous nodes

UChessAIAsyncNode* UChessAIAsyncNode::ChessAIAlphaBeta(AChessAIBase *chess, const int max_depth)
{
	UChessAIAsyncNode* BlueprintNode = NewObject<UChessAIAsyncNode>();
	(new FAutoDeleteAsyncTask<MyAsyncTask>(BlueprintNode, chess, max_depth))->StartBackgroundTask();
	return BlueprintNode;
}

Explanation: BlueprintNode is the class instance just now, which is mainly used to call the binding delegate Complete in the future, so it needs to be passed to the multi-thread

Explanation 2: new FAutoDeleteAsyncTask<MyAsyncTask> means to create a multi-thread, in which MyAsyncTask is defined by ourselves, which will be discussed later. The parameters in it are all needed, and you can also not pass them.

Note 3: The StartBackgroundTask function means to start the thread running

Note 4: FAutoDeleteAsyncTask is an available thread that can be automatically destroyed, it will be automatically allocated from the thread pool, and other reference videos can also be used

6. Create a thread class

First introduce the relevant header files in the header file

#include "Async/AsyncWork.h"

Then write a class as shown below

 Description: 1 declare a friend class, do not know what it means

Note 2: The following variables can be customized, if necessary, add

Note 3: MyAsyncTask constructor, and initialize values ​​for member variables, see step 5 above will pass in some parameters

Explanation 4: 2 needs to overload this DoWork function, which means calling when the thread is running

Explanation 5:3 is just written like this, I don’t know what it means, pay attention to replace MyAsyncTask with your own

7. Realize the thread running function DoWork

Explanation: The first two lines are calculations, which take a long time, so multi-threading is required

Explanation 2: ENamedThreads::GameThread means that the statements inside are called in the game thread

Explanation 3: Node is the UChessAIAsyncNode instance above, which was passed in through the constructor before

Note 4: Complete is the commission that needs to be bound just now, which is the output part of the blueprint node

Note 5: The Broadcast function should just call the delegate, and the blueprint node will output the calculation result at this time

8. Summary

Proxy-agent, multi-threaded, asynchronous nodes

 h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "ChessAIBase.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "Async/AsyncWork.h"
#include "ChessAIAsyncNode.generated.h"


//声明动态多播委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FChessAIMuitDynamicDele, FBestMove, chessBest);

/**
 * 
 */
UCLASS()
class CHESSAI_API UChessAIAsyncNode : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()

public:
	UPROPERTY(BlueprintAssignable)
	FChessAIMuitDynamicDele Complete;

	UFUNCTION(BlueprintCallable, Category = "ChessAI")
	static UChessAIAsyncNode* ChessAIAlphaBeta(AChessAIBase *chess, const int max_depth);
	
};

class MyAsyncTask : public  FNonAbandonableTask
{
	// 1
	friend class FAutoDeleteAsyncTask<MyAsyncTask>;
	UChessAIAsyncNode *Node;
	AChessAIBase *chess;
	const int max_depth;
	MyAsyncTask(UChessAIAsyncNode *WaitNode,AChessAIBase *WaitChess,const int Waitmax_depth)
	: Node(WaitNode), chess(WaitChess), max_depth(Waitmax_depth){}

	// 2
	void DoWork();
	// 3
	FORCEINLINE TStatId GetStatId() const
	{
		RETURN_QUICK_DECLARE_CYCLE_STAT(MyAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
	}
};

cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "ChessAIAsyncNode.h"

UChessAIAsyncNode* UChessAIAsyncNode::ChessAIAlphaBeta(AChessAIBase *chess, const int max_depth)
{
	UChessAIAsyncNode* BlueprintNode = NewObject<UChessAIAsyncNode>();
	(new FAutoDeleteAsyncTask<MyAsyncTask>(BlueprintNode, chess, max_depth))->StartBackgroundTask();
	return BlueprintNode;
}

void MyAsyncTask::DoWork()
{
	FBestMove chessBest;
	chessBest = chess->AlphaBeta(max_depth);
	AsyncTask(ENamedThreads::GameThread, [=]()
	{
		Node->Complete.Broadcast(chessBest);
	});
}

UE4C++ crashes after multi-threaded packaging

The editor runs normally, but it crashes after packaging

A follow-up to the above multi-threaded approach (just to solve the problem and not the best way):

1. Do not use dynamic multicast in multithreading, whether with parameters or without parameters

 2. Do not use it in the DoWork function

// AsyncTask(ENamedThreads::GameThread, [=]()
// {
// 	Node->Complete.Broadcast();
// });

I don't know the details, but it will crash after adding it

So the question is, how to return the value? I use a blueprint timer to wait for the calculation to end, and use a boolean member variable of a class to determine whether it is over.

Replenish:

It has nothing to do with multicast, mainly because it cannot be written like this

Indicates that it runs on the game thread, so that it will not crash after packaging 

After UE4C++ is packaged, the DLL cannot be called and the path cannot be found

The FPlatformProcess::PushDllDirectory() function can tell the program the path of the required dll
FPlatformProcess::PushDllDirectory(*(FPaths::ProjectDir() / TEXT("Plugins/ChessAI/Source/ThirdParty/ChessAIDLL/x64/Release/")));
FPlatformProcess::PushDllDirectory(*(FPaths::ProjectDir() / TEXT("Plugins/ChessAI/Binaries/ThirdParty/ChessAIDLL/Win64/")));

Pay attention to these two lines, the paths are different, the second path is the plug-in directory after packaging, the first path will be invalid after packaging

for example

 These three paths are all output in the first line above, 1 is the editor state, 2 is the editor build and running state, and 3 is the state after packaging

If there is no second line of code on both sides, you need to manually copy the relevant dll to the directory at the same level as the exe, which is troublesome. There is also a code that automatically copies the dll to the specified path on the Internet, which will not be discussed here.

If it crashes pay attention to the dependencies of the dll.

Guess you like

Origin blog.csdn.net/u012863565/article/details/125057580