UE4自身提供了一个FDateTime::ToUnixTimestamp函数可以将系统时间转换位时间戳,但是FDateTime::ToUnixTimestamp只能提供10位的时间错,翻阅了FDateTime中并没有提供13位的时间戳,且查看FDateTime::ToUnixTimestamp的源码,确实只精确到秒。
| FString UBPFunctionLibrary::GetTimestamp() { FString Timestamp; FDateTime Time = FDateTime::UtcNow(); int64 unixTimestamp = Time.ToUnixTimestamp(); Timestamp = FString::Printf(TEXT("%lld"), unixTimestamp); UE_LOG(LogTemp, Log, TEXT("Timestamp:%s"), *Timestamp); return Timestamp }
|
输出:
| LogTemp: Timestamp:1651734043
|
当我们需要使用13位的时间戳时UE似乎就提供不了,所以只能通过C++的手段来获取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <windows.h>
FString UBPFunctionLibrary::GetTimestamp() { string nowTimeUnix; string cs_uninxtime; string cs_milliseconds; SYSTEMTIME sysTime; GetLocalTime(&sysTime); time_t unixTime; time(&unixTime); char buf[30], bufms[30]; sprintf_s(buf, sizeof(buf), "%I64d", (INT64)unixTime); sprintf_s(bufms, sizeof(bufms), "%03I64d", (INT64)sysTime.wMilliseconds); nowTimeUnix = string(buf) + string(bufms); FString Timestamp = FString(nowTimeUnix.c_str()); UE_LOG(LogTemp, Log, TEXT("Timestamp:%s"), *Timestamp); return Timestamp; }
|
输出:
| LogTemp: Timestamp:1751734043331
|
上面这种方法只能在Windows上使用,如果需要在Andriod上使用,则可以直接封装java的库函数。然后通过UE4的JNI框架去调用java函数,以达到在Android上获取13位的时间戳的效果。
UE4调用java的函数通过一个中间XML文件来实现,我们将需要调用的函数在XML中用java函数进行一层封装,然后再在UE4中调用这个封装函数来实现间接调用。
首先创建一个XML文件,这里命名为:JavaTest.xml:
| <?xml version="1.0" encoding="utf-8"?> <root xmlns:android="http://schemas.android.com/apk/res/android"> <gameActivityClassAdditions> <insert> <![CDATA[ public String getSystemTimestamp() { long now = System.currentTimeMillis(); return String.valueOf(now); } ]]> </insert> </gameActivityClassAdditions> </root>
|
将我们的封装函数写在gameActivityClassAdditions标签里,这里直接调用Android的库函数获取当前时间戳。
然后我们需要在.Build.cs文件里注明这个XML文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| using UnrealBuildTool; using System.IO;
public class JavaTest423 : ModuleRules { public JavaTest423(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string[] { });
if (Target.Platform == UnrealTargetPlatform.Android) { PrivateDependencyModuleNames.Add("Launch"); AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(ModuleDirectory, "JavaTest.xml")); } } }
|
由于只需要运行在Android上,所以这里做了平台判断。
然后创建一个Actor—JavaTest,在Actor中调用这个java函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include "JavaTest.h" #include "Kismet/KismetSystemLibrary.h"
#if PLATFORM_ANDROID #include "Android/AndroidApplication.h" #include "Android/AndroidJavaEnv.h" #include "../Source/Runtime/Launch/Public/Android/AndroidJNI.h" #endif AJavaTest::AJavaTest() { PrimaryActorTick.bCanEverTick = true; } void AJavaTest::BeginPlay() { Super::BeginPlay(); Timestamp(); } void AJavaTest::Tick(float DeltaTime) { Super::Tick(DeltaTime); } FString AJavaTest::Timestamp() { FString Timestamp; #if PLATFORM_ANDROID jstring JavaString = NULL; if (JNIEnv* Env = FAndroidApplication::GetJavaEnv(true)) { static jmethodID MethonId = FJavaWrapper::FindMethod(Env, FJavaWrapper::GameActivityClassID, "getSystemTimestamp", "()Ljava/lang/String;", false); JavaString = (jstring)FJavaWrapper::CallObjectMethod(Env, FJavaWrapper::GameActivityThis, MethonId); if (JavaString != NULL) { const char* JavaChars = Env->GetStringUTFChars(JavaString, JNI_FALSE); Timestamp = FString(UTF8_TO_TCHAR(JavaChars)); Env->ReleaseStringUTFChars(JavaString, JavaChars); Env->DeleteLocalRef(JavaString); } } #endif UE_LOG(LogTemp, Log, TEXT("Timestamp:%s"), *Timestamp); return Timestamp; }
|
然后打一个Android包,安装到手机上运行,查看一下打印的日志:
| 830: 05-06 20:38:28.134 5103 5159 D UE4 : [2022.05.06-20.38.28:134][ 0]LogTemp: Timestamp:1651840708134
|