code
This commit is contained in:
15
Source/TerracottaWarriors.Target.cs
Normal file
15
Source/TerracottaWarriors.Target.cs
Normal file
@ -0,0 +1,15 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class TerracottaWarriorsTarget : TargetRules
|
||||
{
|
||||
public TerracottaWarriorsTarget(TargetInfo Target) : base(Target)
|
||||
{
|
||||
Type = TargetType.Game;
|
||||
DefaultBuildSettings = BuildSettingsVersion.V4;
|
||||
|
||||
ExtraModuleNames.AddRange( new string[] { "TerracottaWarriors" } );
|
||||
}
|
||||
}
|
28
Source/TerracottaWarriors/Private/BPTools.cpp
Normal file
28
Source/TerracottaWarriors/Private/BPTools.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "BPTools.h"
|
||||
|
||||
FString UBPTools::ReadConfigString(const FString& FilePath)
|
||||
{
|
||||
|
||||
if (!FPaths::FileExists(FilePath))
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("file no exist: %s"), *FilePath);
|
||||
return "";
|
||||
}
|
||||
|
||||
FString FileContent;
|
||||
bool bSuccess = FFileHelper::LoadFileToString(FileContent, *FilePath);
|
||||
if (bSuccess)
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("file content : %s"), *FileContent);
|
||||
return FileContent;
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("file read failed: %s"), *FilePath);
|
||||
return "";
|
||||
}
|
||||
return FileContent;
|
||||
}
|
12
Source/TerracottaWarriors/Private/Tools.cpp
Normal file
12
Source/TerracottaWarriors/Private/Tools.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Tools.h"
|
||||
|
||||
Tools::Tools()
|
||||
{
|
||||
}
|
||||
|
||||
Tools::~Tools()
|
||||
{
|
||||
}
|
270
Source/TerracottaWarriors/Private/UDPInstanceSubsystem.cpp
Normal file
270
Source/TerracottaWarriors/Private/UDPInstanceSubsystem.cpp
Normal file
@ -0,0 +1,270 @@
|
||||
#include "UDPInstanceSubsystem.h"
|
||||
#include "Serialization/JsonReader.h"
|
||||
#include "Serialization/JsonWriter.h"
|
||||
#include "Sockets.h"
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "Common/UdpSocketBuilder.h"
|
||||
#include "Common/UdpSocketReceiver.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
||||
TSharedPtr<FJsonObject> FDeviceData::ToJsonObject() const
|
||||
{
|
||||
TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
|
||||
JsonObject->SetStringField("id", ID);
|
||||
JsonObject->SetNumberField("x", X);
|
||||
JsonObject->SetNumberField("y", Y);
|
||||
JsonObject->SetNumberField("z", Z);
|
||||
JsonObject->SetNumberField("yaw", Yaw);
|
||||
JsonObject->SetNumberField("roll", Roll);
|
||||
JsonObject->SetNumberField("pitch", Pitch);
|
||||
return JsonObject;
|
||||
}
|
||||
|
||||
bool FDeviceData::FromJsonObject(const TSharedPtr<FJsonObject>& JsonObject, FDeviceData& OutDeviceData)
|
||||
{
|
||||
if (!JsonObject.IsValid())
|
||||
return false;
|
||||
|
||||
if (!JsonObject->TryGetStringField("id", OutDeviceData.ID))
|
||||
return false;
|
||||
|
||||
if (!JsonObject->TryGetNumberField("x", OutDeviceData.X))
|
||||
return false;
|
||||
|
||||
if (!JsonObject->TryGetNumberField("y", OutDeviceData.Y))
|
||||
return false;
|
||||
|
||||
if (!JsonObject->TryGetNumberField("z", OutDeviceData.Z))
|
||||
return false;
|
||||
|
||||
if (!JsonObject->TryGetNumberField("yaw", OutDeviceData.Yaw))
|
||||
return false;
|
||||
|
||||
if (!JsonObject->TryGetNumberField("roll", OutDeviceData.Roll))
|
||||
return false;
|
||||
|
||||
if (!JsonObject->TryGetNumberField("pitch", OutDeviceData.Pitch))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
InitNetwork();
|
||||
UUID = FGuid::NewGuid().ToString();
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::Deinitialize()
|
||||
{
|
||||
CleanupNetwork();
|
||||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::InitNetwork()
|
||||
{
|
||||
// 初始化发送socket
|
||||
SenderSocket = FUdpSocketBuilder(TEXT("UDPSenderSocket"))
|
||||
.AsReusable()
|
||||
.WithBroadcast();
|
||||
|
||||
// 设置远程端点 (192.168.1.28:1234)
|
||||
FIPv4Address::Parse(TEXT("192.168.30.254"), RemoteEndpoint.Address);
|
||||
RemoteEndpoint.Port = 1234;
|
||||
|
||||
// 初始化接收socket
|
||||
ReceiverSocket = FUdpSocketBuilder(TEXT("UDPReceiverSocket"))
|
||||
.AsReusable()
|
||||
.WithBroadcast()
|
||||
.BoundToEndpoint(FIPv4Endpoint(FIPv4Address::Any, 9999)) // 监听相同端口
|
||||
.WithReceiveBufferSize(65535);
|
||||
|
||||
// 启动接收线程
|
||||
SocketReceiver = new FUdpSocketReceiver(ReceiverSocket, FTimespan::FromMilliseconds(100), TEXT("UDPReceiver"));
|
||||
SocketReceiver->OnDataReceived().BindUObject(this, &UUDPInstanceSubsystem::OnDataReceived);
|
||||
SocketReceiver->Start();
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::CleanupNetwork()
|
||||
{
|
||||
// 停止接收线程
|
||||
if (SocketReceiver)
|
||||
{
|
||||
SocketReceiver->Stop();
|
||||
delete SocketReceiver;
|
||||
SocketReceiver = nullptr;
|
||||
}
|
||||
|
||||
// 关闭接收socket
|
||||
if (ReceiverSocket)
|
||||
{
|
||||
ReceiverSocket->Close();
|
||||
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ReceiverSocket);
|
||||
ReceiverSocket = nullptr;
|
||||
}
|
||||
|
||||
// 关闭发送socket
|
||||
if (SenderSocket)
|
||||
{
|
||||
SenderSocket->Close();
|
||||
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket);
|
||||
SenderSocket = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::SetTrackedPawn(APawn* NewPawn)
|
||||
{
|
||||
TrackedPawn = NewPawn;
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::SendDeviceData(const FDeviceData& DeviceData)
|
||||
{
|
||||
if (!SenderSocket)
|
||||
return;
|
||||
|
||||
// 将结构体转换为JSON
|
||||
TSharedPtr<FJsonObject> JsonObject = DeviceData.ToJsonObject();
|
||||
FString JsonString;
|
||||
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonString);
|
||||
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
|
||||
|
||||
// 发送数据
|
||||
TArray<uint8> Data;
|
||||
FTCHARToUTF8 Converter(*JsonString);
|
||||
Data.Append((uint8*)Converter.Get(), Converter.Length());
|
||||
|
||||
int32 BytesSent = 0;
|
||||
SenderSocket->SendTo(Data.GetData(), Data.Num(), BytesSent, RemoteEndpoint.ToInternetAddr().Get());
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::SendCurrentPawnData()
|
||||
{
|
||||
if (!TrackedPawn)
|
||||
return;
|
||||
|
||||
FDeviceData DeviceData;
|
||||
/*DeviceData.ID = "PlayerPawn";*/
|
||||
DeviceData.ID = UUID;
|
||||
UCameraComponent* TargetCamera = TrackedPawn->FindComponentByClass<UCameraComponent>();
|
||||
|
||||
FVector Location = TargetCamera->GetComponentLocation();
|
||||
DeviceData.X = Location.X;
|
||||
DeviceData.Y = Location.Y;
|
||||
DeviceData.Z = 0;
|
||||
|
||||
FRotator Rotation = TargetCamera->GetComponentRotation();
|
||||
DeviceData.Yaw = Rotation.Yaw;
|
||||
DeviceData.Roll = Rotation.Roll;
|
||||
DeviceData.Pitch = Rotation.Pitch;
|
||||
|
||||
/*FVector Location = TrackedPawn->GetActorLocation();
|
||||
DeviceData.X = Location.X;
|
||||
DeviceData.Y = Location.Y;
|
||||
DeviceData.Z = Location.Z;
|
||||
|
||||
FRotator Rotation = TrackedPawn->GetActorRotation();
|
||||
DeviceData.Yaw = Rotation.Yaw;
|
||||
DeviceData.Roll = Rotation.Roll;
|
||||
DeviceData.Pitch = Rotation.Pitch;*/
|
||||
|
||||
SendDeviceData(DeviceData);
|
||||
}
|
||||
|
||||
|
||||
void UUDPInstanceSubsystem::SpawnActorInGameThread(TSubclassOf<AActor> Actor, const FVector& Location, const FRotator& Rotation, const FString& ID, FOnActorSpawned OnActorSpawned)
|
||||
{
|
||||
// 强制要求在 GameThread 调用
|
||||
if (IsInGameThread())
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("In main thread"));
|
||||
return;
|
||||
}
|
||||
// 记录开始创建
|
||||
UE_LOG(LogTemp, Log, TEXT("Actor1111 "));
|
||||
|
||||
// 使用智能指针或委托机制才能安全地处理异步结果
|
||||
AsyncTask(ENamedThreads::GameThread, [this, Location, Rotation, ID, Actor, OnActorSpawned]()
|
||||
{
|
||||
if (!GetWorld())
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("Cannot spawn actor: invalid world"));
|
||||
OnActorSpawned.ExecuteIfBound(nullptr, ID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Actor)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("Cannot spawn actor: invalid actor class"));
|
||||
OnActorSpawned.ExecuteIfBound(nullptr, ID);
|
||||
return;
|
||||
}
|
||||
|
||||
AActor* NewActor = GetWorld()->SpawnActor<AActor>(Actor, Location, Rotation);
|
||||
if (NewActor)
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("Actor %s spawned at %s"), ID.Len() ? *ID : TEXT("Unknown"), *Location.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("Failed to spawn actor %s"), *ID);
|
||||
}
|
||||
|
||||
OnActorSpawned.ExecuteIfBound(NewActor, ID);
|
||||
});
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::OnDataReceived(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt)
|
||||
{
|
||||
// 将接收到的二进制数据转换为字符串
|
||||
uint8* Data = (uint8*)ArrayReaderPtr->GetData();
|
||||
int32 DataSize = ArrayReaderPtr->Num();
|
||||
|
||||
// 添加字符串结束符
|
||||
TArray<uint8> DataWithNull;
|
||||
DataWithNull.Append(Data, DataSize);
|
||||
DataWithNull.Add(0); // 添加null终止符
|
||||
|
||||
// 转换为FString
|
||||
FString DataString = UTF8_TO_TCHAR(DataWithNull.GetData());
|
||||
|
||||
ParseReceivedData(DataString);
|
||||
|
||||
// 在游戏线程中处理数据
|
||||
// AsyncTask(ENamedThreads::GameThread, [this, DataString]() {
|
||||
//
|
||||
// });
|
||||
}
|
||||
|
||||
void UUDPInstanceSubsystem::ParseReceivedData(const FString& DataString)
|
||||
{
|
||||
//UE_LOG(LogTemp, Warning, TEXT("Received Data: %s"), *DataString);
|
||||
|
||||
TMap<FString, FDeviceData> DeviceDataMap;
|
||||
|
||||
TSharedPtr<FJsonObject> JsonObject;
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(DataString);
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
|
||||
{
|
||||
for (const auto& Pair : JsonObject->Values)
|
||||
{
|
||||
if (Pair.Value.IsValid() && Pair.Value->Type == EJson::Object)
|
||||
{
|
||||
FDeviceData DeviceData;
|
||||
if (FDeviceData::FromJsonObject(Pair.Value->AsObject(), DeviceData))
|
||||
{
|
||||
DeviceData.ID = Pair.Key; // Set ID from map key
|
||||
DeviceDataMap.Add(Pair.Key, DeviceData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FDeviceDataMap DeviceDataMapStruct;
|
||||
DeviceDataMapStruct.ReceivedDataMap = DeviceDataMap;
|
||||
AsyncTask(ENamedThreads::GameThread, [&,this, DeviceDataMapStruct]()
|
||||
{
|
||||
OnDeviceDataReceived.Broadcast(DeviceDataMapStruct);
|
||||
});
|
||||
}
|
27
Source/TerracottaWarriors/Public/BPTools.h
Normal file
27
Source/TerracottaWarriors/Public/BPTools.h
Normal file
@ -0,0 +1,27 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "BPTools.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class TERRACOTTAWARRIORS_API UBPTools : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Reads the content of a file and returns it as a string.
|
||||
* @param FilePath The path to the file to read.
|
||||
* @return The content of the file as a string, or an empty string if the file does not exist or cannot be read.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable)
|
||||
static FString ReadConfigString(const FString& FilePath);
|
||||
|
||||
};
|
15
Source/TerracottaWarriors/Public/Tools.h
Normal file
15
Source/TerracottaWarriors/Public/Tools.h
Normal file
@ -0,0 +1,15 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class TERRACOTTAWARRIORS_API Tools
|
||||
{
|
||||
public:
|
||||
Tools();
|
||||
~Tools();
|
||||
};
|
116
Source/TerracottaWarriors/Public/UDPInstanceSubsystem.h
Normal file
116
Source/TerracottaWarriors/Public/UDPInstanceSubsystem.h
Normal file
@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "Networking.h"
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
#include "UDPInstanceSubsystem.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FDeviceData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
FString ID;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float X;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float Y;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float Z;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float Yaw;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float Roll;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float Pitch;
|
||||
|
||||
// JSON 序列化
|
||||
TSharedPtr<FJsonObject> ToJsonObject() const;
|
||||
static bool FromJsonObject(const TSharedPtr<FJsonObject>& JsonObject, FDeviceData& OutDeviceData);
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FDeviceDataMap
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Device Data")
|
||||
TMap<FString, FDeviceData> ReceivedDataMap;
|
||||
};
|
||||
|
||||
// 声明代理类型
|
||||
// C++
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDeviceDataReceived, const FDeviceDataMap&, ReceivedDataMap);
|
||||
|
||||
UCLASS()
|
||||
class TERRACOTTAWARRIORS_API UUDPInstanceSubsystem : public UGameInstanceSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
|
||||
// 设置要跟踪的Pawn
|
||||
UFUNCTION(BlueprintCallable, Category = "UDP")
|
||||
void SetTrackedPawn(APawn* NewPawn);
|
||||
|
||||
// 发送设备数据
|
||||
UFUNCTION(BlueprintCallable, Category = "UDP")
|
||||
void SendDeviceData(const FDeviceData& DeviceData);
|
||||
|
||||
// 发送当前Pawn的位置数据
|
||||
UFUNCTION(BlueprintCallable, Category = "UDP")
|
||||
void SendCurrentPawnData();
|
||||
|
||||
// 设备数据接收代理
|
||||
UPROPERTY(BlueprintAssignable, Category = "UDP")
|
||||
FOnDeviceDataReceived OnDeviceDataReceived;
|
||||
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
FString UUID;
|
||||
|
||||
// UDPInstanceSubsystem.h 中合适的位置(如类前向声明或public部分)
|
||||
DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnActorSpawned, AActor*, SpawnedActor, const FString&, ID);
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SpawnActorInGameThread(TSubclassOf<AActor> Actor, const FVector& Location, const FRotator& Rotation, const FString& ID, FOnActorSpawned OnActorSpawned);
|
||||
|
||||
private:
|
||||
// UDP 发送相关
|
||||
FSocket* SenderSocket;
|
||||
FIPv4Endpoint RemoteEndpoint;
|
||||
|
||||
|
||||
|
||||
// UDP 接收相关
|
||||
FSocket* ReceiverSocket;
|
||||
FUdpSocketReceiver* SocketReceiver;
|
||||
TArray<FDeviceData> ReceivedDeviceData;
|
||||
FCriticalSection ReceivedDataCriticalSection;
|
||||
|
||||
// 要跟踪的Pawn
|
||||
UPROPERTY(Transient)
|
||||
APawn* TrackedPawn;
|
||||
|
||||
// 初始化网络
|
||||
void InitNetwork();
|
||||
|
||||
// 清理网络
|
||||
void CleanupNetwork();
|
||||
|
||||
// UDP 接收回调
|
||||
void OnDataReceived(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt);
|
||||
|
||||
// 解析接收到的数据
|
||||
void ParseReceivedData(const FString& DataString);
|
||||
};
|
33
Source/TerracottaWarriors/TerracottaWarriors.Build.cs
Normal file
33
Source/TerracottaWarriors/TerracottaWarriors.Build.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class TerracottaWarriors : ModuleRules
|
||||
{
|
||||
public TerracottaWarriors(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[]
|
||||
{
|
||||
"Core", "CoreUObject", "Engine", "InputCore",
|
||||
"Networking",
|
||||
"Sockets",
|
||||
"Json",
|
||||
"JsonUtilities"
|
||||
});
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { "Networking",
|
||||
"Sockets",
|
||||
"Json",
|
||||
"JsonUtilities" });
|
||||
|
||||
// Uncomment if you are using Slate UI
|
||||
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
|
||||
|
||||
// Uncomment if you are using online features
|
||||
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
|
||||
|
||||
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
|
||||
}
|
||||
}
|
6
Source/TerracottaWarriors/TerracottaWarriors.cpp
Normal file
6
Source/TerracottaWarriors/TerracottaWarriors.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "TerracottaWarriors.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, TerracottaWarriors, "TerracottaWarriors" );
|
6
Source/TerracottaWarriors/TerracottaWarriors.h
Normal file
6
Source/TerracottaWarriors/TerracottaWarriors.h
Normal file
@ -0,0 +1,6 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
15
Source/TerracottaWarriorsEditor.Target.cs
Normal file
15
Source/TerracottaWarriorsEditor.Target.cs
Normal file
@ -0,0 +1,15 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class TerracottaWarriorsEditorTarget : TargetRules
|
||||
{
|
||||
public TerracottaWarriorsEditorTarget(TargetInfo Target) : base(Target)
|
||||
{
|
||||
Type = TargetType.Editor;
|
||||
DefaultBuildSettings = BuildSettingsVersion.V4;
|
||||
|
||||
ExtraModuleNames.AddRange( new string[] { "TerracottaWarriors" } );
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user