1. 程式人生 > >Unity3D伺服器端使用PhysX計算物理

Unity3D伺服器端使用PhysX計算物理

本文的最終目的

當設計師在Unity3D中製作好遊戲場景後(為Gameobject拖好Collider),通過我們寫的工具匯出這份場景的Collider配置,在伺服器端能夠生成一份一模一樣的物理世界,從而由權威伺服器去計算物理,諸如子彈有沒有擊中玩家等等。

PhysX最初是AGEIA公司開發的物理運算引擎,跟Havok,Bullet這兩款旗鼓相當,後來2008年AGEIA被NVIDIA收購,NVIDIA將PhysX保密,作為NVIDIA顯示卡的專利,這逐漸導致了其沒落,在封閉了相當長一段時間後,NVIDIA最終將其開源,目前原始碼已經託管在了Github上。

PhysX支援平臺和引擎如下:

硬體平臺:Windows, OSX, Linux, XBOX, PlayStation, Andriod, IOS

遊戲引擎:Unreal 3, Unreal 4, Unity

1. 安裝PhysX

1.1 獲取GitHub上PhysX原始碼的許可權

PhysX原始碼並不對所有人開放,需要向Repo的holder申請,操作步驟參考如下:詳細步驟

總的來說就是4步:

  • 申請許可權,在最下面填上自己的GitHub Username就可以了。
  • 1個小時後檢視github繫結的郵箱,就可以看到通過申請的回覆郵件了
  • 訪問Github上PhysX的Repo, 就可以fork,clone下來了

1.2. PhysX安裝

  • 原始碼clone下來之後, 按照根目錄下的README.md很容的找到 /PhysX-3.3/PhysXSDK/Source/compile/目錄下所需要的平臺,編譯出對應平臺下的靜態和動態連結庫。
  • 整合/PhysX-3.3/Include 和 /PhysX-3.3/Lib 和 /PhysX-3.3/Bin到自己的程式使用。

備註:

在根目錄下,我們會看到另外一個APEXSDK, 這個是一套讀取設計師通過PhysX Lab等工具匯出的設計的資源的API(資源有自己定義的格式如 “.apb”).

例如:場景中物體的摧毀效果,布料,粒子等效果,比方說其中有一個模組: Destruction Module, 有興趣的可以看一下

這套視訊,半個小時左右,就瞭解了,這個不是這篇文章的重點。

2. Unity Editor中匯出物理場景的配置

Unity中基本的Collider分為:Box Collider, Sphere Collider, Capsule Collider,以及針對精度要求較高的Mesh Collider,還有其它的一些特定應用場景下會用到的諸如Wheel Collider,Terrain Collider等等。

我們今天主要目的搭建好整個流程,只用基本型別的Collider作為例子。

我們前後臺都統一使用Google Proto buffers定義場景匯出的格式,以二進位制格式序列化和反序列化場景。

2.1 定義Scene.proto

整個proto程式碼貼在了下方,我們簡單說明一下,很容易就明白了。

每一個戰鬥場景匯出一個檔案,格式如下:

  1. message U3DPhysxScene
  2. {
  3. optional int32 id                                              = 1;
  4. optional string scene_name                            = 2;
  5. repeated U3DPhysxBox box_collider              = 3;
  6. repeated U3DPhysxSphere sphere_collider    = 4;
  7. repeated U3DPhysxCapsule capsule_collider = 5;
  8. repeated U3DPhysxMesh mesh_collider         = 6;
  9. }

一個場景由若干個U3DPhysxBox,U3DPhysxSphere,U3DPhysxCapsule,U3DPhysxMesh組成.

每個collider的定義很容易理解, 其中Capsule Collider在PhysX的定義如下:

package killer.proto;

enum ColliderType
{
BOX        = 1;
SPHERE  = 2;
CAPSULE = 3;
MESH      = 4;
}

message Position
{
optional double x = 1 [default = 0];
optional double y = 2 [default = 0];
optional double z = 3 [default = 0];
}

message U3DPhysxScene
{
optional int32 id                                          = 1;
optional string scene_name                         = 2;
repeated U3DPhysxBox box_collider            = 3;
repeated U3DPhysxSphere sphere_collider   = 4;
repeated U3DPhysxCapsule capsule_collider = 5;
repeated U3DPhysxMesh mesh_collider        = 6;
}

message U3DPhysxSphere
{
optional int32 id                = 1;
optional ColliderType type = 2;
optional Position pos         = 3;
optional double radius       = 4;
}

message U3DPhysxBox
{
optional int32 id                 = 1;
optional ColliderType type  = 2;
optional Position pos          = 3;
optional double x_extents  = 4;
optional double y_extents  = 5;
optional double z_extents  = 6;
}

message U3DPhysxCapsule
{
optional int32 id                = 1;
optional ColliderType type = 2;
optional Position pos         = 3;
optional double raduis       = 4;
optional double height      = 5;
}

message U3DPhysxMesh
{
optional int32 id                   = 1;
optional ColliderType type    = 2;
optional int32 vertex_count = 3;
repeated Position vertices    = 4;

}

2.2 修改Scene.proto

  • 進入Editor/BuildProtocol/Protocal
  • 修改Scene.proto, 然後執行 Editor/BuildProtocol/build.bat,這樣protobuf會在 Editor/ProtoGeneratedScrips 目錄下生成新的Scene.cs。
  • 然後重新整理Unity,修改 Editor/SceneExtractor.cs 指令碼使用新的Scene.proto的欄位。

2.3 程式碼下載並執行

整個Unity Editor的程式碼(c#) 和 依賴的第三方庫(proto-net),都已經打包好了.

下載下來直接放到Unity的Assets目錄下,重新整理unity.

在選單欄中: Tools->SceneExtractor->ExtractColliders

即可匯出當前開啟的場景為一份物理配置給後臺使用。

程式碼託管在了Github上:

3. 伺服器端匯入場景的配置檔案,生成物理場景

因為後臺在跑的伺服器沒有顯示卡,所以我們伺服器端的工作,分為如下兩步

3.1 在windows平臺上,反序列化出場景,用OpenGL渲染測試正確性

1. 這部分工程程式碼也封裝好了,可以下載下來直接跑

程式碼託管在了Github上:

平臺:windows7 x64 + Visual Studio 2013 + OpenGL

語言: C++

具體每個資料夾的含義以及如何導proto,請看工程根目錄下的README.md檔案。

在跑工程的時候,有可能會遇到一些問題,比方說:OpenGL沒有安裝等,請移步 /external 目錄,裡面有兩張png是解決沒有安裝OpenGL問題的。

  • 如果沒有安裝OpenGL,請將 /external/GL 目錄拷貝到 **/Program Files(x86)/Microsoft Visual Studio 12.0/VC/include/GL。對於Visual Studio的其它版本,放到對應的目錄下去就好了。
  • 同樣如果在連結階段報lib檔案找不到的話,將external/*.lib 這3個lib放到 **/Program Files(x86)/Microsoft Visual Studio 12.0/VC/lib/amd64 這個目錄下去。

2. 程式碼結構說明

  • PhysicsSceneManager是核心的類,管理了初始化PhysX,匯入場景等核心功能
  • PhysicsSceneRender和ServerCooperationRender負責渲染
  • PhysicsSceneCamera是控制相機鏡頭的類
  • Main.cpp是工程入口,通過RENDERFORTEST巨集去控制是否開啟OpenGL渲染

我們開啟PhysicsSceneManager.cpp

看到最重要的兩個函式: InitiPhysics()和InitiSceneFromFile().

需要注意的是m_foundation, m_physics是在程式一啟動的時候就必須初始化的。

其它的程式碼配合PhysX的Documentation看,很容易就看明白了。

3.2 關閉OpenGL渲染,將Simulation部分的程式碼放到Linux上去

程式碼託管在了Github上: 

最後關閉 RENDERFORTEST 巨集, 並刪除PhysicsSceneRender.h, PhysicsSceneRender.cpp和SeverCooperationRender.cpp,並將對程式碼進行簡單的封裝,就可以放到伺服器上運行了。

這一部分的程式碼部分可以在這裡下載,但是linux下的physx環境配置需要自行安裝,安裝過程也很簡單, 不能直接make。

目錄下有一個可執行的二進位制檔案 PhysXTestBinary,是我們編譯出來測試的。

4.執行測試

  1. Unity製作測試場景

  2. 在Windows下伺服器端渲染的場景

  3. 在Linux伺服器上,利用PhysX的Raycast的API, 可以正確檢測其中一對點可以到達, 另外一對點由於中間Box collider的阻擋無法達到。

相關推薦

Unity3D伺服器使用PhysX計算物理

本文的最終目的: 當設計師在Unity3D中製作好遊戲場景後(為Gameobject拖好Collider),通過我們寫的工具匯出這份場景的Collider配置,在伺服器端能夠生成一份一模一樣的物理世界,從而由權威伺服器去計算物理,諸如子彈有沒有擊中玩家等等。 Phy

Unity3D移動HTTP無法訪問伺服器

原因: 近期在開發Unity移動端的專案時,發現通過HTTP無法請求伺服器(前期在編輯器中訪問正常,釋出到Android端就 涼涼了) using System.Collections; using

Unity3D 通過Get與Post方式與伺服器進行互動

<p style="padding-top: 10px; padding-bottom: 10px; margin-top: 0px; margin-bottom: 0px; line-height: 25px; color: rgb(51, 51, 51); fon

Unity3D開發之網路遊戲中伺服器的架構設計

    最近在研究網路遊戲開發,感覺結構很好玩,所以就將自己學到了解到的記錄下來。部落格前幾篇的Socket通訊講的就是網路遊戲部分Socket的基本結構。上一篇的對MySql使用就是伺服器對資料庫的連線使用。今天要介紹的就是遊戲伺服器的設計架構以及一些核心程式碼。    通

無法向會話狀態伺服器發出會話狀態請求。請確保 ASP.NET State Service (ASP.NET 狀態服務)已啟動,並且客戶埠與伺服器埠相同。如果伺服器位於遠端計算機上,請檢查。。。

無法向會話狀態伺服器發出會話狀態請求。請確保 ASP.NET State Service (ASP.NET 狀態服務)已啟動,並且客戶端埠與伺服器埠相同。如果伺服器位於遠端計算機上,請檢查HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspn

(轉)Unity3D 之插值計算

離開 http 分享 player oid 動畫 and stat etc 在unity3D中經常用線性插值函數Lerp()來在兩者之間插值,兩者之間可以是兩個材質之間、兩個向量之間、兩個浮點數之間、兩個顏色之間,其函數原型如下: Material.Lerp 插值 func

Unity3D移動電量與wifi信號的獲取

ios 位置 wol file arp zhang logs code cit 移動端遊戲中無法看到電量與wifi信號對於玩家來說是很困擾的事。 關於這個問題安卓與iOS有不同的方法 電量 安卓 安卓獲取電量有兩種方法,一種是讀取安卓手機裏的一個文件,一種是利用安卓

netty伺服器啟動

package com.imooc.netty.ch3; import com.imooc.netty.ch6.AuthHandler; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.ne

基於windows的簡單伺服器和客戶

伺服器端套接字建立步驟:1.呼叫socket函式建立套接字。2.呼叫bind函式分配IP地址和埠號。3.呼叫listen函式轉為可接收請求狀態。4.呼叫該accept函式受理連線請求。 客戶端套接字建立步驟:1.呼叫socket函式建立套接字。2.呼叫connect函式向伺服器端傳送連線請求。  

Ajax傳遞複雜引數到伺服器的方法

我們大概都知道,使用Ajax傳遞簡單引數到伺服器端(SpringMVC)的方法,如下: $.ajax({ type : "POST", url : CONFIG.mec_otm.order + "/cancel", data : { "resu

DataTables的伺服器(SpringMVC)分頁模式

Datatables是一款jquery表格外掛。它是一個高度靈活的工具,可以將任何HTML表格新增高階的互動功能。 分頁,即時搜尋和排序 幾乎支援任何資料來源:DOM, javascript, Ajax 和 伺服器處理 支援不同主題 DataTables, jQuery UI, Bo

Django-伺服器物件-跨域請求

Django-伺服器端物件-跨域請求 在介面函式中配置 from django.http import HttpResponse,response,JsonResponse def login(request): todo_list = [ {"

Django-伺服器物件

Django-伺服器端物件 request 通過request.method可以檢視提交方式 request 解析資料 get request.environ request.GET #如果提交資料方式為: http://localh

伺服器解決跨域問題的三種方法

跨域是指html檔案所在的伺服器與ajax請求的伺服器是不同的ip+port,例如:  - ‘192.168.1.1:8080’ 與 ‘192.168.1.2:8080’是不同的域。  - ‘192.168.1.1:8080’ 與 ‘192.168.1.1:8081’是不同的域。

PG客戶連線伺服器報Connection refused (0x0000274D/10061) 的問題分析

C:\Users\Administrator>psql -h 192.168.80.189 -U highgo -p 5899 psql: 無法聯接到伺服器: Connection refused (0x0000274D/10061)       

基於windows的tcp伺服器/客戶

一個計算器的例子: 客戶端連線到伺服器端後以1位元組整數形式傳遞待算數字個數; 客戶端向伺服器端傳遞的每個整數型資料佔用4位元組; 傳遞整數型資料後接著傳遞運算子,運算子佔1個位元組; 伺服器端以4位元組整數型向客戶端傳回計算結果。   伺服器端:   #includ

Socket-tcp協議客戶伺服器互聯

客戶端 using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.T

Linux 檢視伺服器開啟情況及開啟或關閉一個埠(永開啟久關閉)

Linux 檢視伺服器端開啟情況及開啟或關閉一個埠(永久關閉等) 1.Linux CentOS7防火牆的基本操作,對firewalld-cmd操作和檢視 2.Linux CentOS7怎麼開啟外網訪問一個埠 1.Linux

基於windows的使用select的I/O複用回顯伺服器

使用過select函式可以將多個檔案描述符集中到一起監視,集中時也要按照監視項(接收、傳輸、異常)區分。   伺服器端: #include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #de

Jersey 2.x 伺服器應用支援的容器

基於 JAX-RS Servlet-based 部署的一部分標準,能執行在任何支援 Servlet 2.5 和更高標準的的容器上。Jersey 提供支援程式化部署在下面的容器中:Grizzly 2 (HTTP 和 Servlet), JDK Http server,Simple Http server 和 J