最近在看各别解析度对应的方法,发现unreal engine 4里面已经有DPI Scale来很好处理这一块了。但其实这个机制其实也并不完美,因为玩家能够乱拉视窗的大小,随便乱拉的结果则会有些UI会跑到看不见,尤其是当视窗大小被拉成不是预期的状态时,整个UI会变成很奇怪,这对于一个好的游戏体验是没办法接受的。
在我的预期上调整短边应该要能够scale位置,而调整长边去scale大小。但这个DPI Scale机制最终其实也只能选择直的或横的来做处理。虽然有一个custom可以实作自己的类别,看起来似乎有那么一点戏可以做到想做的效果,但实在有点麻烦,而且实作出来应该也只是对值的customize而已,而不是根据动作(上面说的位置、大小),所以我开始在寻找禁止玩家去乱拉window大小的方法,最终目标是只在游戏中提供几个按钮让玩家选择可用的解析度大小。这种做法也比较符合一般游戏使用的机制,不用去烦恼那几近无限的解析度适配的问题,只要我们提供的选项的aspect ratio是一致的,然后再根据我们的选项去把那个DPI Scale curve拉好,基本上就不会有什么大问题。
为了这个问题我研究了好几天,发现在void FWindowsWindow::Initialize这个function下面虽然有传入一个FGenericWindowDefinition definition来指定这个视窗的样式,但该参数并没有开放给引擎的使用者进行调整,因为它在更上一层的FSlateApplication::MakeWindow被宣告成local的变数再传进来的。那么到底该怎么去调整这视窗的样式呢?
看来引擎并没有一个generic的api来做这件事,因此我们能做的就是针对各个平台拿出NativeWindow再进行对应的实作,以下的程式码可以达成这件事:
# if PLATFORM_WINDOWS # include " windows/WindowsWindow.h " # include " SharedPointer.h " # endif // PLATFORM_WINDOWS # include " AllowWindowsPlatformTypes.h " void AHopePlayerController::AdjustWindow () { # if PLATFORM_WINDOWS TSharedPtr<FGenericWindow> NativeWindow = GEngine->GameViewport-> GetWindow ()-> GetNativeWindow (); auto Window = static_cast <FWindowsWindow*>(NativeWindow. Get ()); // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644898%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 // https://msdn.microsoft.com/en-us/library/windows/desktop/ff700543(v=vs.85).aspx // DWORD WindowStyle = WS_DLGFRAME; DWORD WindowExStyle = WS_EX_APPWINDOW; DWORD WindowStyle = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_VISIBLE; // | WS_THICKFRAME | WS_POPUP | WS_DLGFRAME | WS_VISIBLE; auto hWnd = Window-> GetHWnd (); SetWindowLongPtr (hWnd, GWL_EXSTYLE, (LONG_PTR)WindowExStyle); SetWindowLongPtr (hWnd, GWL_STYLE, (LONG_PTR)WindowStyle); # endif // #if PLATFORM_WINDOWS } # include " HideWindowsPlatformTypes.h "
在游戏跑起来之后呼叫一次这个方法之后,总算能让玩家不能去乱拉window的大小啦。
当然在其他平台,如mac或linux,则必须要再survey相关的实作才行(如果有需要的话)。