1)Text Mesh Pro圖文混排如何對任何圖片都能實現
2)PlayerSettings.WebGL.emscriptenArgs設置無效的問題
3)Prefab對DLL中腳本的引用丟失
4)如何在第三人稱藍圖模板中獲得當前相機SpringArm的Target Arm Length
這是第386篇UWA技術知識分享的推送,精選了UWA社區的熱門話題,涵蓋了UWA問答、社區帖子等技術知識點,助力大家更全面地掌握和學習。
UWA社區主頁:community.uwa4d.com
UWA QQ羣:793972859
UI
Q:目前Text Mesh Pro圖文混排需要把圖片打入圖集並放入TMP的Resources文件夾中。項目中想在任務UI面板展示很多裝備或物品的icon,這些icon都是打好了的圖集,很多別的系統也要用,不可能都放入TMP的這個資源文件夾裏,但這樣就無法進行圖文混排,請問有什麼解決辦法嗎?
A1:把TMP裏面所有的Resources.Load接口,都替換成項目自身的Bundle加載接口,應該就可以解決了。
感謝王燦光@UWA問答社區提供了回答
A2:可以註冊以下回調:TextMeshProUGUI.OnFontAssetRequest,這樣就可以自定義一個加載方法。
如果加載成功了,TMP就不會Resources.Load。
感謝程一峯@UWA問答社區提供了回答
WebGL
Q:遊戲裏用了C++的第三方庫集成到xLua裏面,端版是用CMake構建,可以配置宏、Include路徑等,很方便。
我現在用Unity 2021.3發佈的WebGL版本,xLua是把所有Lua代碼放在了“工程目錄/WebGLPlugins”下面,在引擎裏去#include這裏的C代碼,也沒問題。
但是自己的C/C++代碼比較多,也不能全部扔在同一個目錄下,如果加了目錄,就有跨目錄Include的問題(主要是lua.h,lauxlib.h)。從實際表現來看,include .c或.cpp時,用到的.h文件如果是在同目錄就沒問題,如果跨目錄了就會找不到。
我用PlayerSettings.WebGL.emscriptenArgs = "-Imy_file_folder_path";這樣設置搜索路徑,但是沒用;然後定義宏-Dxx也沒用,不知道為什麼。(參數中沒有自己定義的路徑和宏,都是Unity自己的,雖然ProjectSettings.asset已經生效了。)
請問有解決方案嗎?
A:在Unity 2021.2之後更新Emscripten,emscriptenArgs屬性失效了,可以把Lua代碼和C/C++代碼都放到一個層級,然後改引用。
還有一個方式:找到你Unity安裝目錄\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emcc2.py,如果沒有emcc2.py就找emcc.py,在裏面找到get_clang_command方法,這個方法就是拼接執行編譯C/C++代碼語句的,在[src_file]後面增加+ ['-IAssets/XXX/XXX'],注意-I和Assets之間沒空格,大概這樣子:
def get_clang_command(src_file): return get_compiler(use_cxx(src_file)) + get_cflags(options, state.orig_args) + compile_args + [src_file] + ['-IAssets/XXX/XXX']注意py文件縮進問題,多個文件夾就添加多個“-I”,我猜因為它自己有“-I.”參數,所以可以使用相對目錄(對clang++編譯不太熟,我在Windows的Unity 2021.3.38f1上使用可行。)
compile_args變量是記錄傳進來的參數的,有精力也可以找找調用emcc2.py的地方傳進來更合適,我這邊沒找到。
其它需要改C/C++編譯參數的地方我也在這裏改了,如果有其它更簡便有效的方法,歡迎分享。
感謝高鬆@UWA問答社區提供了回答
Script
Q:開發時,不希望策劃看到源碼,於是將源碼替換成DLL,但是這樣掛在Prefab上的腳本引用會丟失,請問怎麼解決?
A1:是原有的預製掛了CS,後面想打成DLL重新掛?如果是這樣,遍歷預製,去批量修改GUID和FileID。可參考文章《Unity將C#腳本轉換為DLL,Prefab等文件不丟失引用的方法(轉)》,文章裏面用了DLLSwitcher插件,也可以自己理解Prefab GUID fileID和DLL,CS文件對應的關係就行了。
感謝c8K2SVRRcz1P@UWA問答社區提供了回答
A2:代碼要分成底層和邏輯層。底層用DLL+Obfuscator,邏輯層就不能了,因為如果也加密,開發驗收查bug都會費勁。
如果要防止策劃帶走代碼,按照我説的底層DLL就行,即使他帶出去,只有邏輯層的開發,後面也會一大堆問題,除非自己寫底層,就要調試,時間還不如自己重新寫,這樣的博弈論一旦開始,這個代碼庫重要性就不高了。
同時也要防止策劃帶走服務端代碼,做到服務端拿不到客户端,客户端拿不到服務端,這樣即使有一方代碼,也是無用代碼。
感謝夏霖鋭@UWA問答社區提供了回答
Rendering
Q:使用SpringArm組件會讓相機在發生碰撞時拉近,但是為什麼獲得到的Target Arm Length值卻一直不變?
A:在代碼中,Target Arm Length永遠是不變的,但是它下面有RelativeSocket,在藍圖中可以使用GetSocketTransform來獲取,並且使用RTS_Component參數,取Location然後用VectorLength來計算:
FTransform USpringArmComponent::GetSocketTransform(FName InSocketName, ERelativeTransformSpace TransformSpace) const { FTransform RelativeTransform(RelativeSocketRotation, RelativeSocketLocation); switch(TransformSpace) { case RTS_World: { return RelativeTransform * ComponentToWorld; break; } case RTS_Actor: { if( const AActor* Actor = GetOwner() ) { FTransform SocketTransform = RelativeTransform * ComponentToWorld; return SocketTransform.GetRelativeTransform(Actor->GetTransform()); } break; } case RTS_Component: { return RelativeTransform; } } return RelativeTransform; }
https://www.youku.com/video/XNjM5ODYyMjMwMA==
還可以用SpringArm與Camera的位置相減來計算,分別GetWorldLocation再Sub和VectorLength:
https://www.youku.com/video/XNjM5ODYyMzg1Ng==
可以發現兩種方式得到的數據似乎有些小區別,這是因為該案例中還有一個相機跟隨鼠標位置移動的功能,它會對Camera進行SetRelativeLocation,偏移其Y和Z值。方式一是從SpringArm中取,與Camera無關,所以不受偏移量影響;方式二用到了Camera的RelativeLocation,因此將偏移量也算了進去。
另外還有一種方式,無法計算距離,而是直接檢測相機是否與世界發生了碰撞,發生碰撞時就會進行縮放。
歡迎有經驗的朋友轉至社區交流:
https://answer.uwa4d.com/question/66417ac15ce8a46b00fc4d2b
封面圖來源於網絡
今天的分享就到這裏。生有涯而知無涯,在漫漫的開發週期中,我們遇到的問題只是冰山一角,UWA社區願伴你同行,一起探索分享。歡迎更多的開發者加入UWA社區。
UWA官網:www.uwa4d.com
UWA社區:community.uwa4d.com
UWA學堂:edu.uwa4d.com
官方技術QQ羣:793972859