2017年11月9日 星期四

iPhoneX上的ARKit人臉識別

作者:Jimmy Alamparambil 原文
潤稿:Kelvin Lo


自從6月份在WWDC大會上首次發佈ARKit以來,它已經成為實現穩定商品等級AR的方法。最近在iPhone X發佈會上,Apple發表將會為ARKit加入一些只在iPhone X上可用的人臉辨識功能,這功能會用到iPhoneX上面的深度鏡頭的前置鏡頭組。

Unity一直與
Apple密切合作,在ARKit發佈的同時就提供了對應的Unity ARKit套件,確保Unity開發者可以在最短的時間內就可以開發出ARKit產品應用。我們與Apple公司緊密合作,把ARKit的人臉識別包入了Unity ARKit套件。

這些新功能的相關程式與範例已整合在Unity ARKit套件裡,你可以從BitBucketAsset Store找到它。

套件新增的API內容


如果你的產品會在iPhoneX執行,現在可以使用一個名為ARKitFaceTrackingConfiguration的設定資訊。新的RunWithConfig 和 RunWithConfigAndOptions方法可以使用ARKitFaceTrackingConfiguration設定資訊來啟動AR。

新增了用來增加、刪除或更新ARFaceAnchor的事件Callback。

人臉辨識功能

ARKit中的人臉辨識有四個主要功能。下面會一一介紹並展示範例。

臉部定位(Face Anchor)



人臉辨識的一個基本功能是當iPhoneX的前鏡頭偵測到人臉時提供一個定位錨點。這個定位錨點與ARKit通常回傳的平面錨點相似。當你移動頭部時,它會追蹤頭部中心的位置和方向。透過這種方式就可以使用臉部運動作為ARKit應用的輸入,同時也允許你使用這個錨點將物件附加到臉部或頭部,就能做到3D物件會隨著你頭部移動。
我們製作了一個展示場景FaceAnchorScene來展示這個功能。它裡面有一個附加了UnityARFaceAnchorManager元件的GameObject,這個元件會使用ARKitFaceTrackingConfiguration初始化ARKit。它還連接到FaceAnchor,建立、更新和移除事件,以便執行以下操作:

  1. 在建立臉部錨點時,它會啟用一個GameObject。在範例中是一個如上圖的三軸座標模型,會將這個模型移到由FaceAnchor給予的位置和方向上面。 
  2. 在臉部錨點更新時,它會更新GameObject的位置和方向。 
  3. 當移除臉部錨點時,它會關掉這個GameObject。 
這個場景還用了ARCameraTracker元件,這個元件透過FrameUpdateEvent更新Main Camera,和一般的ARKit應用程式一樣。

臉部網格Face Mesh Geometry



臉部辨識API還可以將檢測到的人臉形狀傳回一個網格。在Unity中使用這些網格點就可以建立一個臉部網格。然後與透明紋理一起使用就可以幫臉部做表面繪製。當我們這個網格放在上面提到臉部錨點時,賦予一個材質就能換臉。

展示場景FaceMeshScene展示了如何在你的臉上放一個用預設材質的臉部網格 。它有一個常見的ARCameraTracker物件,用在在場景中的鏡頭。還有一個ARFaceMeshManager物件,該物件有一個基本網格以及一個空的Mesh Filter元件。這個物件還有UnityARFaceMeshManager元件,用來執行以下操作:

  1. 設定臉部辨識 
  2. 根據錨點位置和旋轉,更新對應物件的transform資訊。
  3. 展出每幀錨點的網格資料,填充成一個網格,並將此網格賦予Mesh filter元件

變形 Blend Shapes





我們從臉部辨識得到的另一組資料是描述臉部表情的係數,將它們映射到一個虛擬面部,就可以模仿你的表情。

範例場景FaceBlendShapeScene展示了這個應用。在UI中它顯示了根據當下表情返回的不同混合形狀值的係數。看看它們在你改變表情時是如何變化的。

這個場景與FaceMeshScene擁有相同的物件,但是另外還有一個包含了BlendshapePrinter元件的BlendshapeOutput物件。該元件從臉部錨點中提取存在的Blend Shapes,並輸出到螢幕UI。

我們正在製作一個更詳細的例子,在這個例子中,這些值將被映射到虛擬頭部的臉部動畫中,以幫助你更好地瞭解它的用途。

定向光估計 Directional Light Estimate



使用臉部辨識還能獲取另一組有趣的資料,將你的臉當成場景裡的定向光偵測器,來產生場景的定向光推算 。產生的資料包含三個:

  1. 主光源方向 
  2. 主光源亮度 
  3. 預估的全向照明環境的球面調和係數 (Spherical harmonics coefficients)
最後一項在Unity中對我們來說很有意思,因為它剛好是我們標準渲染管線中用於動態全域照明的解決方法。瞭解這些資訊後,我們就可以在範例場景中使用。

FaceDirectionalLightEstimate場景有一個ARCameraTracker和一個ARFaceAnchorManager,它使一個灰色球體會隨你的臉四處移動。ARKitLightManager物件是新增的,它包含一個UnityARKitLightManager元件,用於從FrameUpdated事件獲取球面調和係數,並將它指到場景中所有的Unity光線探頭,包括環境光線探頭。這樣就能根據估計的環境光線,有效地為場景中的網格提供動態照明。

如果你希望使用自己的機制來提供場景照明,可以通過FrameUpdated事件,獲取以Unity坐標系統表示的原始球面調和係數,放到你的照明公式中。你也可能只是想使用主光源的方向和強度來照明,那麼同樣的方式也適用。

請注意:本文中所提供的範例場景,只有在從Bitbucket下載的套件裡才有。 


小結

正如你所看到的,在iPhone X上有一些和臉部辨識有關的ARKit功能。Unity的ARKit套件可以幫助你輕鬆地在你的應用中實現這些功能。iPhone X目前已正式發售,所以如果你是AR的開發者,趕緊研究如何在你的應用加入臉部辨識吧。

2017年10月24日 星期二

We are Hiring


Field Engineer
at Unity Technologies
China (Shanghai / Beijing / Guangzhou)
Brief Description
Unity Technologies is currently seeking an experienced Field Engineer who will lead handle incoming technical issues from Unity users. This incumbent would have deep knowledge of Unity and how it is used in large projects.
Instrumental in helping key Unity users ship amazing games and applications.
Goals and responsibilities:
  1. Provide in-depth consultation and support to developers who are planning
    to use Unity for their games and simulations;
  2. Become a technical expert in the use of Unity product portfolio (Unity Pro,
    Source Code, etc) for game and simulation development;
  3. Build long-term relationships with technical decision makers and
    influencers within key accounts;
  4. Provide technical presentations and technology demos at trade shows and
    on customer site visits;
  5. Provide product development recommendations and technical data to
    Unity’s product development teams;
  6. Act as a strong internal advocate for our customers ensuring feedback is
    communicated between sales and product engineering;
7. Act as an ambassador for our customers offering regionalized feedback to our product development processes.
Requirements:
  1. 5+ years of experience in game programming, simulation programming or
    games middleware with knowledge of game development process and
    platforms;
  2. A bachelor’s degree (or equivalent) in computer science, math, or a related
    field;
  3. Practical understanding of 3D graphics algorithms and web technologies;
  1. Strong oral and written communication skills addressing various groups of customers: technical, business, and/or project management
  2. Demonstrated consultative customer management skills;
  3. Willing to travel;
  4. Self-starter, highly motivated individual;
  5. Experience in working as developer support engineer in related field;
9. Experience in working as part of a cross-functional team.
Who we are

We are product-driven, curious, and creative. We aggressively reinvest in
development to keep Unity moving and evolving - from expanding usability and
power, to platform reach. With over a billion installs per month, Unity touches
gamers and non-gamers alike. As well as video games, our software is used in
industries as diverse as medicine, visualization and shopping - democratizing
game development while solving hard problems and enabling success for a
huge range of developers worldwide.
Today, Unity has expanded to over 15 international offices and has employees
in 23 countries. Every person at Unity Technologies has an inherent passion and driven spirit and it isn’t enough to be able to do the job- we’re looking for people that color outside the lines, are looking to be freed from the process tangle, and can dream big!
Those interested in applying for this role please submit resumes to
emmali@unity3d.com

2017年9月5日 星期二

Unity說明文件範例正確性檢測 - 玩轉Unity編輯器測試工具

作者:Karl Jones 原文
發表於:2017/8/18

潤稿:Kelvin Lo

每當我遇到不熟悉的API,當下第一反應一定是去查查Unity文件,看看文件裡的範例來瞭解API的使用方式。但如果按照文件依樣畫葫蘆卻編譯失敗的話,是否可能是文件出錯了呢?

這是Unity Hackweek(註一)的一個專案,利用Unity 5.3以上的編輯器測試工具,來自動檢驗所有Unity腳本的範例程式是否編譯成功。

Unity腳本文件共有15000頁左右,其中並非所有文件都包含範例(這需要另外解決),但也已經不少了。手動檢查每個範例加上測試,在為期一周的Hackweek中很難辦到,也無法解決未來的API更新衍伸的文件更新問題。

然而去年發佈的Unity 5.3中包含一個新功能:Editor Test Runner,它是能在Unity中執行的單元測試框架(unit test framework)。這個功能發佈後就一直用於Unity內部測試,幫助我們追蹤問題。Unity所有腳本文件都保存為XML檔,可以在Unity內部專案中編輯。



專案已經包含解析XML檔的程式,所以只需在專案中加上編輯器測試即可使用這些功能。在編輯器測試框架中會用到TestCaseSource屬性,讓測試多次在不同的來源資料上執行。在本例中,來源資料就是程式範例文件:



這個方法會顯示所有執行在Test Runner上的測試。每個測試都能獨立執行,或通過Run ALL選項來同時執行。


本範例使用CodeDomProvider 編譯,這樣可以傳遞多個表示腳本的字串,並編譯和返回相關的錯誤及警告資訊。
首次測試反覆運算的縮減版(已刪除XML解析):




運作很正常! 編譯腳本的方式還需做些調整,因為有些腳本是組合在一起的方式形成一個範例。分別編譯所有範例以檢測是否有這種情況,如果出現錯誤再將其合併編譯,看看是否成功。

還有一些簡單範例就是一行程式,沒有封裝在函數內。可以在測試中進行封裝來處理這種問題,要遵循的規則就是這些例子必須能獨立執行(即開發者將它複製貼上到一個新的檔案中也可以被編譯和執行),否則就將這些範例視為測試失敗。

這個測試方法現在離正式作為文檔驗證工具還有一段距離。我還需要解決一個小問題:這個測試流程執行需花費30分鐘。由於我們每天需要執行約7000個版本,僅僅作為一個版本驗證測試來說這個執行時間太長了。

目前這個測試方法是依序執行的,一次一個腳本。由於測試彼此獨立,且無需呼叫Unity API,因為只測試編譯是否成功,所以完全可以並行執行這些測試。下面引入用於並存執行任務的.NET API-執行緒池。將測試作為單個任務放入執行緒池中,當執行緒可用時立即執行。這需要從單個函數執行,即不能用單獨的NUnit測試用範例來測試文件的單一範例。儘管不能單獨測試,但我們大大提高了整體執行的速度。



這將測試時間從30分鐘縮短至2分鐘,作為版本驗證來說已滿足需求。由於無法測試單個範例,所以在腳本文件編輯器中加入按鈕,以便文件編寫人員日後更新。執行測試時出錯腳本會顯示為紅色,並在下方顯示錯誤資訊。

首次執行測試時有326個錯誤,將這些加入白名單以便日後更新。畫面現在只剩32個,大多錯誤都是由於無法存取特定的程式集導致。整合該測試並未引入新的問題,所以可以確定如果棄用部分API導致測試失敗,則需要更新文件來使用新的API。

結語

本文只是Editor Test Runner工具一個非常有趣的使用案例,當然還有待改進,例如只能抓取C#範例,無法處理.js的編譯。但在不久的將來,這也將不再是問題。(註二)

感謝各位,可以從這裡下載完整程式碼

<註一> Unity Hackweek是一個Unity內部活動,每年研發人員會集合並討論Unity有哪些需要改進的地方,並在為期一周的時間,動手做個初始原型,有點像是企業內部的黑客松。
<註二> Unity已經對外發佈未來即將不支援 Unity Java Script。會專心維護C#。

2017年9月4日 星期一

Unity遊戲開發中的AI - 基於Q-Learning的強化學習

作者:Arthur Juliani 原文
潤稿:Kelvin Lo


歡迎來到Unity AI系列文章第二篇,我們上次已經為大家介紹了遊戲開發中的AI - 入門,今天這篇文章將延續上次的內容繼續探討如何將它擴展到一個
完整能強化學習問題的吃角子老虎機。在這個過程裡,我們會展示如何利用一個Agent透過Q函數學習,來預估長期在特定條件下採取特定行為的值。本例僅使用一個簡單的網格空間(gridworld)以及一個Q-Representation列表。這原理可以應用於任何遊戲上。

Q-Learning演算法

情境老虎機回顧
強化學習(Reinforcement Learning)的目的是在特定環境下訓練一個Agent代理,通過學習來實現特定環境的最大化預期利益。在"遊戲開發中的AI -入門"一文中,環境是相對靜態的,環境狀態也很單純,就是代理躲在3個箱子其中之一,而行為就是選擇打開哪個寶箱。我們的演算法為每一對狀態行為學習Q函數,Q函數則對應在該狀態下隨著時間前進採取某種行為而獲得的預期利益。這樣的問題通常被稱為“情境老虎機”(Contextual Bandit)。

強化學習問題

要將前面的情境老虎機問題轉換為強化學習問題,還缺少兩個關鍵因素:稀有獎勵與狀態轉換。稀有獎勵是指代理並非每次採取行為都可以獲得獎勵。有時獎勵會“延遲”,因為有些行為可能不是必須的,也可能要在一系列非必須行為之後才能獲得獎勵。更具體的展示是,代理可能跟隨正確路徑,但只有到達終點才能獲得獎勵,而非走過的每一步都有獎。儘管中途沒有獎勵,但走過的每一步對到達終點來說都至關重要。我們需要一種方式來執行“信用分配”,即讓代理知道早期的行為是有價值的,儘管只是間接價值。

第二個缺失的因素是強化學習中狀態之間的轉換。有了狀態轉換之後,我們的行為不再是只根據獎勵函數R(s, a) ⇨ r來獲得獎勵,還會根據狀態轉換函數P(s, a) ⇨ s’來產生新的狀態。具體範例是,沿著路徑走過的每一步都會使代理到達路徑的新位置,也就是新的狀態。因此我們希望代理不僅要學習採取行動優化目前可能的獎勵,還要採取行動向可能提供更多獎勵的狀態移動。

貝爾曼更新

雖然新增的兩個複雜元素初看起來並不相關,但確是直接相關聯的。兩個元素都隱含了影響代理的未來最終狀態及其可能獲得的獎勵。通過這種質樸的理解,我們可以利用這種關係來學習在這些情形下應採取的最優行為。即在一個“真正”最優的Q-函數(只存在於理論)中,目當狀態的估值和行為可以被分解為直接獎勵r加上在下一狀態中代理採取行動的最大預期獎勵乘以一個折扣係數:

 

 這就是貝爾曼方程(Bellman Equation)也被稱作動態規劃方程式(Dynamic Programming Equation),由理查·貝爾曼(Richard Bellman)發現,可以按如下形式表述:




此處的𝛄 (gamma)是一個折扣因數,決定了代理對未來可能獲得獎勵的關注程度。如果值為1.0,則代理對未來所有的獎勵一視同仁,在永無止境的訓練中,估值可能會增加到無窮大。為此,𝛄應在0到1之間取值,典型取值範圍是0.7-0.99。

貝爾曼方程有效的原因在於:它提供了一種自動更新Q-函數的方法。Q*(s, a)是一個優化Q-函數。但即使當前的下一狀態的次優Q-value估值也有助於讓當前狀態的估值更加精確。由於每一步都主要依賴於真正的獎勵,所以可以相信Q-value估值自身會緩慢改進,並不斷趨近真實值。我們可以使用貝爾曼方程進行新的Q-Learning更新:



這個方程和之前情境老虎機中使用的更新演算法類似,不同點是Q-target現在包含下一步中未來期望獎勵的折扣值。


探索

為了讓代理更充分地探索狀態空間,我們使用了一種名為epsilon-greedy的探索更新形式。使用時將epsilon-greedy中ϵ初值設置為1.0,每次代理採取行動將該值減少一部分,而當代理選擇行動時,可選最貪婪的行動argmax(Q(s, a)),或者採用概率為ϵ的隨機行動(在搜索初期增加隨機性,提高搜索範圍空間,隨著代理積累經驗,逐步降低隨機影響)。直覺就是訓練開始時,代理的Q-value 估值與真實值相差較大,但通過對整個世界的學習後,ϵ值減少,Q-函數就慢慢與真實環境的Q-函數更一致,而使用Q函數採取行動的精確性也不斷提高。

Unity GridWorld


藍色的方塊是代理,紅色是障礙物,綠色是目標位置,綠色和紅色的球體代表GridWorld中每種狀態的估值。


為了演示Q-Learning代理,我們使用Unity建立了一個簡單的GridWorld環境。其中包含:
  1. 一個在世界中隨機位置出現的代理;
  2. 一個隨機的目標位置,我們希望代理通過學習向目標移動;
  3. 隨機放置的障礙物,我們希望代理學會躲避;

環境狀態(s)是一個整數,代表網格位置,四個行為(a)包括上、下、左、右,獎勵(r)規則為:移動到帶有目標的狀態時+1,移動到帶有障礙物的狀態時-1,為了鼓勵代理快速移動到目標,每次移動時-0.05。每個階段會在移動100次後,或者在代理到達既非目標又非障礙物的狀態時(碰到障礙時)結束。代理的Q-value存儲在表中,行代表狀態,列代表可採取的行為。

你可以點擊這裡直接從網頁看結果,也可以點擊這裡下載這個Unity專案,然後自己修改並應用於自己的遊戲。隨著代理不斷探索環境,不同顏色的球將會出現在網格世界的每個狀態中,這對應當前狀態下代理的平均Q-value估值,一旦代理完成優化策略的學習,這些球就會形成從開始到目標位置的直接值漸變。

後續計畫

此處的代理和環境代表了Q-Learning問題的經典表格,如果不符合你的需求也不用太擔心,Q-Learning演算法從90年代被提出至今,它已經歷了一系列重大的改進,Q學習可被應用於更加多變的動態場景中。Deepmind的Deep Q網路的一個主要示例,就是用於學習直接從圖元中進行幾十種不同的ATARI遊戲,像這裡僅用一個查閱資料表根本不可能實現的壯舉。為了實現這個目標,他們用到了一個由Deep Neural Network(DNN)網路控制的代理。通過神經網路,它可以學習將廣義Q-函數應用于完全不可見的狀態,例如顯示器上少見的圖元組合。

在後面的幾周中,我們會公佈一系列演算法的介面和展示專案,可以在Unity遊戲和模擬應用中訓練類似的深度強化學習代理。您可以查看影片,先簡要瞭解這些工具的功能。初次發佈版本將有些限制,主要用於研究、工業以及遊戲的QA測試。我們非常樂於看到在Unity中利用現代深度學習方法來學習遊戲行為,希望當此項技術成熟時,可以引爆機器學習技術在遊戲開發中的潛力,例如控制遊戲中複雜的NPC行為與遊戲動態等等。我們尚處於探索深度學習技術應用于遊戲開發的初期階段,也希望大家陪伴我們一起踏入後續的旅程。


2017年9月1日 星期五

遊戲開發中的AI - 入門

作者:Arthur Juliani 原文
潤稿:Kelvin Lo


Unity正朝著AI的方向潛心探索著。本文是Unity發佈的首篇AI相關文章,為大家介紹AI的一些概念及術語,詳細介紹機器學習相關理論與方法,並講解在使用Unity開發遊戲的過程中如何應用AI。未來我們還將為大家分享更多AI的內容。在過去幾年,Machine Learning(機器學習,ML)的進步,在檢查物件、翻譯、辨識語言,甚至玩遊戲等等都有突破性發展。值得一提的是,ML和玩遊戲之間的關係在Unity上很像是我們人類的心態。我們相信繼續鑽研能在製作遊戲這塊有突破性的發展,從改變貼圖和3D建模、動畫、人物動作或場景照明的製作方式,到自動產生NPC(非玩家角色)的程式碼。


這篇文章適合的讀者

我們想和Unity的開發者們一起探討關於AI和ML在遊戲開發過程中能發揮的力量,同時也想討論AI用在美術製程的可能性。藉由這次機會剛好可以對ML研究者展現以Unity作為AI研究/開發平台的潛力。像是機器人和自動駕駛等等的模擬平台,讓有興趣的人或研究學生透入研究Unity和ML。


何謂ML(機器學習)

首先來介紹下Machine Learning(機器學習,下文簡稱ML)和遊戲Artificial Intelligence(人工智慧,下文簡稱AI)間的關係。現在大部分遊戲裡的AI都是手動硬寫的,由大量判斷式組成,有時會包含多達數千條規則。而且必須由人工維護和測試。而ML所依賴的演算法可以自動從原始資料尋找規律,無需專業人員預先定義資料的解讀邏輯。

以圖片內容分類這個電腦視覺問題為例。直到幾年前,科學家們仍採用人工編寫篩檢程式,辨識圖像上的特徵,用來分辨某個圖像中包含的是貓還是狗。而ML,特別是最新的深度學習方法,只需圖像和類型標籤,就可以自動學習有用特徵。我們相信這種自動化學習不僅可以拓展Unity平台的應用範圍,例如用於ML場景模擬,還可以幫助所有開發者簡化和加速遊戲的開發過程。

這種自動化學習尤其可以應用在非玩家角色(NPC)的行為。我們可以使用Reinforcement Learning(增強學習,簡稱RL ) 來訓練NPC,預估某一環境中施行特定行為的價值。一旦訓練完成,NPC即可以最佳行為模式做出反應,不用程式對它們的行為進行篩選。後面的文章我們會介紹RL的應用,所有的範例專案也都會公開放在Github上面,你也可以透過WebGL看看整個專案展示。

用RL演算法學習的吃角子老虎

RL背後的一個核心概念是價值估計,並依照此進行對應動作。在繼續深入之前,最好先瞭解一些術語。

在RL裡執行動作的個體稱為agent(代理),它使用policy(策略)進行動作決策。一個代理通常嵌於一個environment(環境)中,並在任意給定的時刻都處於某個特定的state(狀態)。從那個狀態,它可以進行一系列actions(動作)。某個給定狀態的value(值)指的是處於該狀態的最終回報價值。在某個狀態執行一個動作可以讓代理進入另一個新的狀態,獲得一個reward(回報),或者同時擁有兩者。所有RL代理都在盡可能最大化累計回報。



這個RL 範例專案有個問題,技術上稱為multi-armed bandit(或稱為N-armed bandit problem)。這名字源自於為了平衡多台老虎機的回報產生最優化的結果而生,也稱作"Single-arm bandits",設計用來一點一滴的從玩家身上回收錢。在這樣的設定下,環境只包含一種狀態,代理能採取n個動作中的一個。每個動作都會立即為代理提供一個回報。而代理的目地是找出能提供最多回報的動作。

為了更好理解,可以想成一個迷宮遊戲。代理進入一個房間,發現牆邊放著一排寶箱。每個寶箱都有一定的機率開到一顆鑽石(回報+1)或一個敵人惡魂(回報-1)。

代理的目標就是學習思考哪個寶箱最有可能出鑽石。(比如判斷結果為從右屬過來第三個箱子)。要找出回報最高的寶箱最簡單的方法就是逐一嘗試。在代理獲得足夠的資訊並採取最佳行動之前,大部分RL的工作就是簡單的不斷嘗試錯誤。上面這個例子用RL的術語來描述就是,"嘗試"對應的是採取一系列動作(多次打開每個寶箱),學習對應的是更新每個動作的估計值。一旦有了足夠的樣本,就可以讓代理總是選擇那個具有最高估計值的寶箱。

三個寶箱,每個都有機率開出鑽石或敵人



這些估計值可以透過一個反覆運算過程獲得。這個過程從最初的一系列估計V(a)開始,並根據每次動作的結果進行調整。運算式如下:


α對應我們的學習率,V(a)是給定動作的價值估計,r是採取動作後馬上可以獲得的回報。


上面的算式很直覺,它表示出我們將當下的價值估計向獲得回報的方向做了一些微調。這樣就能確保變化的估計值能更好的反應環境中的真實動態。如此一來,還能確保估計不會變得過大,如果我們只計算正向結果就可能會發生這種情況。要完成相應程式,我們可以使用一組值估計向量,並透過代理動作對應的索引來引用它們。



三個寶箱上方顯示的是代理的估計值(綠色球體),以及真實的概率值(中間的半透明球體)。在這個例子中,三個寶箱的潛在正向回報概率分別是 10%(左),20%(中),80%(右)。隨著訓練進行,代理的估計值會變得越來越精確。



情境吃角子老虎(Contextual Bandits)

上述所描述的情況缺少了真實環境中有的一個要素,它只有一個狀態。在現實或遊戲世界裡,一個環境可能會處於幾十(房子裡的房間)到數十億(一個螢幕上的圖元)種可能狀態中的一種。每個狀態都有它們自己獨特的動態特性,即動作如何提供新的回報或者允許狀態間的轉移。

因此,我們需要對動作與估計值以及狀態設定條件。用符號表示,現在將用Q(s,a)取代V(a)。它的抽象意思是,現在期望獲得的回報,是我們所採取的動作以及採取該動作時所處狀態的一個函數。

在迷宮遊戲中,狀態的概念使我們可以在不同的房間中擁有不同的寶箱組。每個房間可以有不同的最理想寶箱,因此,代理需要學習在不同房間中採取不同的動作。用程式來實現的話就是使用一個價值估計的matrix來取代一個簡單的array。這個matrix可以用[state, action]來索引。



探索(Exploring)和利用(Exploiting)

讓RL能運作還需要一個重要的因素。在代理學得採用最佳回報動作的策略之前,需要有另一個策略使它可以充分瞭解世界,以確保它知道什麼是最佳策略。這會引出了一個經典問題,如何平衡探索(exploration)(通過不斷試錯學習環境的價值結構)和利用(exploitation )(基於環境習得的價值結構採取動作)。雖然有時這兩個目標會一致,但大多數狀況它們都會相左。有一系列策略可以平衡這兩個目標。下面列出了其中一部分:

  • 一個簡單卻強大的策略是遵循“optimism in the face of uncertainty”的原則。它的做法是,代理每個動作都從高值估計V(a)開始,這樣它就會貪婪地(利用最大值)採取動作,使它將每個動作都至少執行一次。
  • 如果動作沒有獲得好的回報,就降低對應的價值估計,反之則保持高價值估計,因為該操作可以作為後續好操作的候選。但是僅靠這種自身啟發式演算法通常仍然不夠,因為我們可能需要持續探索某個特定狀態以找到一個低頻率,卻有巨大的回報。
  • 另一個策略是為每個動作的價值估計添加隨機亂數,隨後根據新的亂數估計進行貪婪行為(act greedily)。使用這種方式,只要亂數值小於真實最優動作與其他動作間的差異值,就能收斂至最優的價值估計。
  • 也可以進一步利用估計值本身的特性,將它們進行歸一化(Normalize),依據概率採取動作。這種情況下,如果每個動作的價值估計大致相等,將會以相同概率採取動作。反之,如果一個動作的價值估計要大得多,我們將會更多的選擇這個動作。這樣就能通過遞減選擇無回報動作,慢慢將它們淘汰。這也是在範例專案中所採用的策略。



結語

有了這篇文章以及相關程式碼,你現在也可以嘗試在Unity中使用文章描述的演算法了。但這僅僅是入門而已,在後面的文章我們將通過Q-Learning來講解一個完整的RL問題,並以此為基礎,開始探討深度神經網路,解決視覺豐富遊戲環境中,愈趨複雜的代理行為的學習策略問題。使用這些進階的方法來訓練代理成為我們遊戲中的同伴或對手,適用的遊戲類型可以是格鬥遊戲、賽車、第一人稱射擊,或甚至即時策略遊戲等等。不需要編寫任何規則,只需專注於你希望代理達成的狀態,而非它如何達成的過程。

後續我們還會提供一些工具的早期版本,讓對使用Unity進行深度RL研究感興趣的開發者,可以將諸如Tensorflow或PyTorch等框架編寫的模型連接到Unity製作的環境中。一起探索未來可能是新的遊戲製作方式領域!

2017年8月20日 星期日

Unity告別UnityScript,未來將只支援C#

作者:Richard Fine 原文
潤稿:Kelvin Lo


UnityScript(Unity中客製的JavaScript),從Unity 1.0開始一直伴隨著我們至今。正所謂天下無不散之宴席,終於要向它告別。我們已經開始逐步棄用UnityScript,未來只會保留C#作為Unity程式語言。

目前只有3.6%的Unity專案使用UnityScript進行開發,代表維護UnityScript將會影響Unity對新程式語言功能的支援進度,所以我們決定將棄用UnityScript。


棄用UnityScript的原因

每次Unity決定放棄支援一些功能,都會先瞭解這些決定可能會為開發者帶來的不便。所以我們必須確保這些決定有其進行的理由,這對我們很重要。Unity腳本程式設計正在經歷重大升級,其中一些重要功能包括:
  • 核心執行版本升級,支援使用.NET 4.6與C# 6
  • JobSystem,支援編寫多執行緒程式,且避免互相競爭與鎖死
  • NativeArray類型,支援建立及使用大型陣列,它們擁有原生程式控制的存儲區域,以便於對記憶體分配擁有更多控制權,不必再擔心GC回收機制
  • 支援控制腳本編譯,以便自訂將哪些腳本整合進程式集

這些只是一小部分,我們還將繼續支援一些新功能,並計畫開啟一些腳本專案。除了這些專案之外,我們也正利用最為合適的語言結構,來開放更多引擎底層API。

目前UnityScript與C#在功能與效能不相上下,當然C#可以實現的內容UnityScript也能達到同樣的效果。但說到開發生態,顯然C#是贏家,不僅僅是因為C#教學與範例網路上到處都是,C#語言也有豐富的工具,例如Visual Studio提供的代碼重構與智慧提示。或許你會質疑Unity Script可以用就好了,也不需要那麼多花俏的工具。

技術永遠是不斷發展的,隨著我們升級執行核心支援最新的C#版本時,就會出現一些C#簡單實現但UnityScript無法輕易實現或者不支援的功能。比如說目前UnityScript就不支援為方法參數(method parameters)提供預設值,並且C#語言支援的功能越來越多,例如ref return等都會造成同樣問題。目前我們暫未在API中使用這些功能,但出於效能與API結構設計考慮,我們也希望趕快讓這些新功能上線。

或者我們也可以選擇花時間來彌補UnityScript所欠缺的功能,但時間成本昂貴,把時間花在維護UnityScript就代表無法進行其它工作,好比加新功能或修Bug等。這還不包括在執行核心中支援UnityScript需要的工作,以及文件製作更新工作等等。

所以我們換了個方向思考,如果棄用UnityScript,會有多少開發者被影響呢?我們統計結果如下:

  • 截止目前使用Unity 5.6的專案中,包含至少一個.js檔的專案占14.6%。這個比例看起來相當高,但進一步分析資料,看看各專案中.js檔案與總檔案數(.js檔案 + .cs檔案)占比,會有新發現。
  • 也就是說,85.4%的Unity專案完全使用C#語言,根本不包含任何UnityScript腳本。
  • 9.5%的Unity專案大量使用C#語言,其中也包含一些UnityScript腳本,但腳本數量占腳本總數不足10%。還有1.5%的Unity專案所包含的UnityScript腳本占專案腳本總數在10~20%之間。
  • 3.6%的Unity專案使用UnityScript語言的腳本占腳本總數20%以上。
  • 僅有0.8%的Unity專案完全使用UnityScript。

這些資料顯示,大多數的Unity開發者都不是UnityScript的重度使用者。甚至專案所包含的UnityScript也並非實際使用的腳本,可能只是Asset Store某個套件的範例程式,對實際專案並無影響。所以我們棄用UnityScript計畫的第一步,就是從Asset Store開發者著手,先移除所有發佈套件裡的UnityScript腳本。

對於那3.6%使用較多UnityScript的Unity專案,以及那0.8%完全使用UnityScript的專案,我們表達深切的歉意。我們明白這樣的決定會對你產生影響,我們正製作一些轉換措施來嘗試讓整個轉換過程更加流暢,也希望大家能夠理解並支持我們所做出的決定。

棄用計畫

當然我們會一步一步捨棄UnityScript,而不是一刀切斷。主要計畫步驟如下:

首先,從6月開始我們已經修訂了Asset Store的套件審核條款,拒絕接受程式有包含UnityScript代碼的套件。所有新送審的套件都必須使用C#程式(在執行此項規定前我們已與開發者有過許多討論與溝通)。很快我們將會對Asset Store現有的套件進行檢查,如果有UnityScript則會通知發行商將程式碼轉為C#。如果一段時間後程式沒轉換為C#,套件將會從Asset Store下架。

再來,可能你已經注意到了,Unity 2017.2測試版的Create Assets選單下已經找不到Javascript(即UnityScript)。目前我們只移除了功能表上的建立功能,Unity編輯器仍然支援UnityScript,您仍然可以從編輯器之外創建UnityScript檔(例如MonoDevelop)。這麼做的原因是想確保新手開發者不會選用UnityScript,以免浪費學習成本。

另外,我們正在開發UnityScript自動轉換為C#的工具。目前該工具已有些成果,但還沒到我們滿意的地步。我們也還沒決定是否將工具整合到Unity編輯器或單獨開源提供。無論以何種方式,這個工具都會在今年年底Unity 2017.2正式發佈時提供大家使用。後續也會單獨介紹這個工具,請大家保持關注。

最後,我們也會繼續分析資料,我們希望能看到Unity專案都可以儘快切換至C#,尤其是那些UnityScript腳本數量少於10%的那些專案,因為需要移植的程式相對較少。但如果分析結果轉換未達預期,我們會暫停計畫並調查原因。在徹底棄用UnityScript之前,我們將確保不遺漏任何重要資訊。

一旦確認UnityScript使用率到一個低點之後,我們就會剝離UnityScript編譯器,不再將.js檔識別為腳本。也會從文檔中移除UnityScript程式範例,腳本更新器也將不再支援UnityScript。

如果有單獨需求,開發者仍可從Unity的GitHub中下載UnityScript編譯器,我們不會接受任何推送請求,但您可以建立自己的分支實現你的需求。


關於Boo

在歷史紀錄上Unity曾在2014年宣佈放棄支援Boo語言。但Boo編譯器仍存在現在的編輯器中,只因為UnityScript會用到了Boo的執行庫,並且UnityScript編譯器本身就是用Boo語言編寫的。所以雖然我們沒提但你仍可在Unity專案中使用.boo文件。

但是剝離UnityScript支援之後,就代表Boo編譯器也會被移除。目前所有使用Unity 5.6的專案中僅有0.2%的專案包含了.boo檔,僅有0.006%的專案擁有3個以上.boo檔案。


結論

希望本篇文章有清楚解釋了棄用UnityScript將會為大家帶來的影響,我們會依照流程:通知大家我們的計畫->推動Asset Store套件與編輯器UI更新,最後依照實際使用率的分析資料來決定是否執行。

放棄某個功能看起來像是退步,但這也是提高Unity開發效率的必經之路。我們希望集中精力為大家儘快修復現有的問題並製作新功能,也希望大家能夠理解並支持我們的決定。

2017年8月7日 星期一

最佳實踐 - Unity碰撞效能優化

作者:William Armstrong 原文
潤稿:Kelvin Lo

Unity有一個名為Spotlight的團隊,有一群優秀的Unity開發人員一起研究並試著不斷的打破Unity的極限。針對各種複雜圖形效能和設計問題,我們不斷嘗試各種新的解決方案。

這個系列的文章會探討我們在和客戶合作時遇到的一些常見的問題。這些都是我們的合作團隊辛苦得出的經驗和教訓,我們很榮幸能夠和大家分享這些智慧。

這些問題很多只會出現在發佈到主機遊戲、手機遊戲、或者處理大量遊戲內容時才會出現。如果能在開發早期就將這些問題考慮進去,那麼開發過程就會更輕鬆,而遊戲也會做得更好。

較大的問題

有時候我們追蹤某個物理效能問題時,會歸咎到某一個問題的物件資源或設定上。常常查看Profiler並和前次執行結果比對,是發現這些問題的最佳方式。如果能儘早發現效能的減退,就可以透過查看最近所做的變更找到問題所在。

雖然運算單一簡單的物理
節(physics joint)速度很快,但背後的運算卻很複雜。本質上一個關節就是一套由剛體的位置、速度、加速度、旋轉等資訊組成的方程式。如果建立了一個帶有許多不同剛體的物件,而這些剛體又各自包含了許多會互相碰撞的關節。為了不讓這些關節不會互相穿透,要滿足這些關節的碰撞運算代價會非常大。

所以設計這種複雜關節時,要慎重考慮所需關節數量,碰撞類型以及必要的剛體數量。你可以用圖層(Layer)來過濾不必要的碰撞,也要謹慎評估哪些關節要打開"Allow Collision"來計算碰撞。透過限制關節的活動範圍可以減少碰撞檢測的量。或調整關節使它和其他關節不會發生碰撞。透過將關節和剛體作為插值方法的控制點來減少它們的使用數量。

使用Profiler可以看到某個特定時間啟動的剛體總數。觀察Rigidbody count的值
,尤其是當剛體互相接近時,會對效能產生很大的影響。在執行時放置或產生物件時,這個數字很容易會膨脹到超出預期。這就好比一罐汽水罐的碰撞很容易做,但如果罐子做成Prefab疊成超市裡的飲料塔,碰撞計算就很容易出大問題。


採用MeshCollider要非常小心,通常為了方便,開發者很容易會拿模型網格直接作為碰撞網格,但這可能會引起嚴重的效能下降,而且還不易察覺。PhsyX你給他甚麼他就算甚麼,所以如果一個小物體身上有高模或不合身的碰撞體,這時可能還好,但是如果將MeshCollider放大到容易被RayCast偵測運算的環境中,你會發現效能會驟然下降。如果非要用MeshCollider,建議是對於所有可能會有碰撞運算的物體,另外製作一組低模的碰撞網格。如果網格有問題又沒時間製作自訂網格,可以將MeshCollider設定裡的Convex打勾,並調整SkinWidth來取得一個比較適合的低面碰撞網格。

擁有多個重疊碰撞器的影子戰術NPC

較小的問題

通常開發者都會明智的避開不做大或慢的事情。但很多常見的情況是,專案所做的一系列理性決策,每個都一點一滴無形的影響了PhysX的效能。尤其是製作大規模遊戲時很容易出現這種狀況。例如你用5個方塊做關卡AI測試時表現很OK。但相同的AI放到實際的關卡時,大量的Physics.Update運算造成效能不好,而你卻不知道問題在哪? 


"明明測試都很OK的,為甚麼上正式版就壞了?" -- by 工程師


你有做足夠的測試了嗎?
可以從ProjectSettings->Physics裡找到碰撞圖層過濾(Layer Collision Matrix)來檢查是否存在不必要的碰撞規劃。透過打勾/取消打勾那些方塊,可以控制碰撞體之間的碰撞行為。這個功能會在碰撞發生前先進行計算,進而避開不必要的碰撞計算。許多遊戲使用”Is Trigger”為true的大型碰撞器來檢測角色或其他物件,這通常被稱為觸發器。通常這些觸發器會設定和預設圖層或所有物件發生碰撞計算。透過將角色放到特定層,並將這些觸發器放到某個只會與角色層發生碰撞計算的層,可以避免大體積碰撞器與複雜的世界網格或地形網格發生碰撞計算。

觸發器(Trigger)是否是使所有物件慢下來的原因?
當碰撞器屬性的“Is Trigger”設為true,它依然是一個需要進行碰撞計算的碰撞器。因此移動一個觸發器和移動一個碰撞器所產生的消耗都是一樣的,會需要做很多工作來發送碰撞和重疊事件。如果要在每幀都移動觸發器,確保它只對必須的物件進行碰撞計算。盡可能將觸發器做小,並將相似或重疊的觸發器分組。

我們常見到專案在NPC上使用多個大型觸發器用來檢查是否有互動。NPC的每種類型的遊戲物件都會有自己的碰撞器,以及一堆放在OnCollision中的程式,用來找到正確的互動物件。通常將多個觸發器合併一起會比較快,然後在OnCollision函式中用Tag或Layer或距離來進行過濾。很多情況下可以透過完全繞過碰撞計算來獲得更好的效能。而不必每幀都對球體與世界的碰撞進行計算,而是將所有希望存取的物件註冊到一個共用管理器,然後讓NPC對所有已註冊物件做簡單的距離計算。如果有一小堆需要檢測的潛在目標。這種方法要比對世界中所有的碰撞做檢測效能要高的多。

物件在Hierarchy裡的結構會導致PhysX做了額外的工作嗎?
在《ReCore》這個遊戲裡,我們發現場景中圓形旋轉平臺上的每一個平台都擁有自己的剛體。這導致了每個平台都會與其他平台發生碰撞檢測。將所有的平臺歸於同一父物件之下,將剛體賦予父物件,讓父物件進行旋轉,在Physics.Update中節省了大量的時間。
注意:將一個共用剛體下的碰撞器合併會增加Raycast對它或形狀投射檢測的開銷。

從另一個方面來說,如果一個共用的剛體父物件下已經有幾個碰撞器,你需要非常小心,不要讓它們做相對於父物件的移動。因為任何時候剛體改變形狀,會造成中心的質量和慣性張量(Inertial Tensor)
都必須重新計算,這需要大量的時間。當多個剛體連接到動畫角色的四肢時,常常會出現這種問題。可以通過設定自己的質心來關閉它。只要遊戲物件的形狀不要變化太大就沒問題。

這堆小小的系統問題累積起來是很可怕的,所以在開發中要時刻牢記,並在一開始就做好計畫規避這些問題。如果突然發現Physics時間出現一個巨大峰值,那就分析下當下的修改有哪些並思考對應方式。

最後感謝Mimimi Productions和Armature Studio 讓我們用他們的遊戲作為例子。我們還會為大家分享更多最佳實踐系列文章。

關於我自己

我的相片
Unity台灣官方部落格 請上Facebook搜尋Unity Taiwan取得Unity中文的最新資訊