創作內容

4 GP

使用Unity讓你的行動裝置跟電腦連線(Wifi環境)

作者:愛錢的乾隆│2015-02-19 13:57:41│贊助:8│人氣:6905
大年初一不免俗的要來:

圖:偉大的背景姊 Mii
這是我們的畢業製作,變秘危機,
5.1號開始在新一代展出~

工商時間結束,好了拉回來XD,
今天要記錄的是如何用wifi將電腦跟手機連在一起,
之後還會寫GPS的使用,主要是因為實習需要做AR導航應用所以才稍有研究,
那麼我們就廢話不多說開始吧:

---

這邊不討論unity的手機平台怎麼輸出apk,有需求的請拿香拜一拜大神應該就有了(?),
首先就從unity怎麼連線開始說吧。
unity要連線的方法有很多種,我使用的方法是一種叫做masterServer的東西,
主要概念是一方用區網的ip架server(伺服器端),
並給一些資訊供client(客戶端)做辨識進而連線,
比起藍芽還需要手動配對來說,masterserver可以不到一秒的時間就連上線,
並可隨時中斷server端以及client端的程式,亦可隨時重新連接,
去掉必須要有wifi的限制,其實還挺方便的。

要連線的話雙方(客戶&伺服器端)都得加入一個Network View元件,
你可以開一個空的gameobject來放,放好NV元件後,
接著就可以將script放進來了,至於你是server還是client端就看你的程式怎麼寫,
我這邊會寫兩個,一個是server的script,一個是client的script,
使用JavaScript,C#的使用者不好意思,請自己轉換囉

先從server端的script開始吧:
function OnGUI() {
  if (GUILayout.Button ("Start Server")) {
    Network.InitializeServer(1, 25002, !Network.HavePublicAddress());
    MasterServer.RegisterHost("YourPCRoom", "PhantasyNan", "alpha 1.0");
  }
  GUI.Label(new Rect(Screen.width* 3 /4,10,100,25), "Connections: " +Network.connections.Length);
}

就這樣(好少!?),
來解釋一下吧,加了NV元件之後:
function OnGUI()
↑在遊戲畫面上(OnGUI是繪圖用的function)

if (GUILayout.Button ("Start Server")) {
↑畫了一個按鈕叫做Start Server,若這個按鈕被點擊

Network.InitializeServer(1, 25002, !Network.HavePublicAddress());
↑就架server,InitializeServer底下三個參數分別代表:
【可多少人連,連線的通道,是否用NAT連線】
人數你可以自己訂,port也可以自己打(應該),
第三個是防範用,若沒有公用IP (ex:沒wifi的時候),則轉NAT。

MasterServer.RegisterHost("YourPCRoom", "PhantasyNan", "alpha 1.0");
↑給定一個專有名稱供Client辨識用,RegisterHost底下三個參數分別代表:
【通關密語(?),遊戲名稱,註解】
這邊的通關密語官方文件稱呼為遊戲類型,只是我都叫他通關密語XD,
因為這個參數到時候是要給client辨識的,必須是個獨特的名稱,
可別因為你做的遊戲是動作遊戲,結果都打act啊啊...!
第二個跟第三個則是會顯示在client上的資訊,要打什麼皆可自訂。

GUI.Label(new Rect(Screen.width* 3 /4,10,100,25), "Connections: " +Network.connections.Length);
↑Network底下的connections底下的Length這個參數,會回傳有多少人連到你的server端,
故這一行是將多少人連進來的資訊顯示在螢幕上。

這樣Server端就做好前置作業了,只要執行,按下按鈕,
就會架好一個server了~ (記得開啟wifi)
不得不說前陣子我用flash做行動裝置跟電腦連,
比這個困難多了... ...
unity在後面幫你寫了很多東西,因此可以很輕鬆就製作連線的功能。
---

接著要談client端的script:

var showDetail:boolean;

function Update(){
  MasterServer.RequestHostList("YourPCRoom");
}
function OnGUI() {
  if (GUILayout.Button("Connect to your Computer")){
    showDetail = !showDetail;
  }
  var data : HostData[] = MasterServer.PollHostList();
  for (var element in data)
  {
    if(showDetail)
    {
      GUILayout.BeginHorizontal();
      var name = element.gameName + " " + element.connectedPlayers + " / " + element.playerLimit;
      GUILayout.Label(name);
      GUILayout.Space(5);
      var hostInfo;
      hostInfo = "[";
      for (var host in element.ip)
        hostInfo = hostInfo + host + ":" + element.port + " ";
      hostInfo = hostInfo + "]";
      GUILayout.Space(5);
      GUILayout.Label(element.comment);
      GUILayout.Space(5);
      GUILayout.FlexibleSpace();
      if (GUILayout.Button("Connect"))
      {
        Network.Connect(element);
      }
      GUILayout.EndHorizontal();
    }
  }
}

好了,就這樣(不對),
怎麼比起之前的長了不少?其實不多,裡面有一大串都在做排版XD,
就像網路遊戲的房間那樣,將可以連的裝置分行排好,做成清單而已。
來解釋一下吧,加了NV元件之後:
var showDetail:boolean;
↑新增一個布林參數,當作詳細資訊的開關鈕。

function Update(){
↑每個frame更新一次的function

MasterServer.RequestHostList("YourPCRoom");
↑拿著通關密語的IC卡在網域中跑啊跑,看哪個電子門可以被開(?)
RequestHostList裡面的參數就是剛剛server端打的通關密語,
在client端得預先寫好你有的通關密語。

function OnGUI() {
↑在遊戲畫面上(OnGUI是繪圖用的function)

if (GUILayout.Button("Connect to your Computer")){
↑畫了一個按鈕叫做Connect to your Computer,若這個按鈕被點擊

showDetail = !showDetail;
↑將showDetail這個開關切換(開>關,關>開)。

var data : HostData[] = MasterServer.PollHostList();
↑每個frame檢查一次有幾個server端可連線,並將這些資訊放入data這個參數中。
(OnGUI是每個frame更新一次,因為要繪圖)

for (var element in data)
↑使用迴圈,將data用element替代。

if(showDetail)
↑若這個按鈕被打開,顯示以下資訊。

GUILayout.BeginHorizontal();
↑開始繪圖,這可以將繪製的東西都放在同個群組下。

var name = element.gameName + " " + element.connectedPlayers + " / " + element.playerLimit;
GUILayout.Label(name);
GUILayout.Space(5);
var hostInfo;
hostInfo = "[";
for (var host in element.ip)
hostInfo = hostInfo + host + ":" + element.port + " ";
hostInfo = hostInfo + "]";
GUILayout.Space(5);
GUILayout.Label(element.comment);
GUILayout.Space(5);
GUILayout.FlexibleSpace();
↑這邊都在排版(欸),並將可連線的server排好。

if (GUILayout.Button("Connect"))
↑畫了一個按鈕叫做Connect,若這個按鈕被點擊

Network.Connect(element);
↑連到那個server

GUILayout.EndHorizontal();
↑關閉繪圖。

這樣client端也做好前置作業了~
希望打了這麼多客官們不要頭昏腦脹才好,
總之先放個影片壓壓驚:
依舊是工商時間,
這是我們的畢業製作,變秘危機,
5.1號開始在新一代展出~ 來捧個場嘛
---
回來正題,從剛剛到現在,我們完成了:
「Server架設,Client連接」
雙方的橋梁已經做好了,那再來要做的就是將要互相傳送的資料送出去,
橋做好了就是給人過的嘛(?),因此接著要寫該怎麼將資料互通有無。

傳輸資料的方法似乎也有不少,
雖然都是橋,但作法材料跟樣貌都有不同,
而我這邊使用的作法是RPC,
希望這樣講會比較好理解。
RPC不僅限於Client到Server,Server到Client也是可以同步處理的,
關於RPC的使用我使用範例來講會比較清楚。

*假設我要將某些資料從Client端送到Server端
我想要每個frame就更新一次,所以我放在update,基本上要何時呼叫是隨意的,
以下紅字為client增加的script:

var cWeapon:int;
var sWeapon:int;
var create:boolean;

function Update(){
  MasterServer.RequestHostList("YourPCRoom");

  if(create)GetComponent.<NetworkView>().RPC("Attack", RPCMode.All, cWeapon);
}
function OnGUI() {
  if (GUILayout.Button("Connect to your Computer")){
    showDetail = !showDetail;
  }
  var data : HostData[] = MasterServer.PollHostList();
  for (var element in data)
  {
    if(showDetail)
    {
      GUILayout.BeginHorizontal();
      var name = element.gameName + " " + element.connectedPlayers + " / " + element.playerLimit;
      GUILayout.Label(name);
      GUILayout.Space(5);
      var hostInfo;
      hostInfo = "[";
      for (var host in element.ip)
        hostInfo = hostInfo + host + ":" + element.port + " ";
      hostInfo = hostInfo + "]";
      GUILayout.Space(5);
      GUILayout.Label(element.comment);
      GUILayout.Space(5);
      GUILayout.FlexibleSpace();
      if (GUILayout.Button("Connect"))
      {
        Network.Connect(element);
        create = true;
      }
      GUILayout.EndHorizontal();
    }
  }
}

@RPC
function Attack(W:int){
sWeapon = W;
}

@script RequireComponent(NetworkView)

只有增加不到十行,有沒有很少XD
假設我client端為手機,server端是電腦,
我希望在手機上選擇武器時,電腦可以隨時更換我選到的武器,
於是我在client的script創建了兩個參數,一個是sWeapon,一個是cWeapon,
分別代表server跟client的武器值,
也許0代表空手,1代表手槍,2代表小刀... ...之類的。
那麼來解釋一下剛剛新增的代表什麼意思:

var cWeapon:int;
var sWeapon:int;
var create:boolean;
↑新增兩個整數,一個布林。

if(create)GetComponent.<NetworkView>().RPC("Attack", RPCMode.All, cWeapon);
↑獲取一開始新增的NetworkView元件底下的RPC,
底下三個參數分別代表:
【呼叫的function,要送到那些地方,給function的其他參數】
第一個就好像步驟,第二個是送給誰,第三個則是我會丟入步驟的材料
所以這串的白話意思就是:
---
「我將【材料】丟到【步驟】裡,一起打包送到指定的地方。」
---
【步驟】我寫在script的最下方,等等就會講到;
送的對象(RPCMode)可單獨送給Server,或是All(包括自己),或是Others(除了自己),
剛剛不是有建立橋樑麼?如果沒有橋梁當然就只能送給自己囉...;
而【材料】可以很多個,你寫越多,該套【步驟】就會有越多個【材料】可以拿來運算。

create = true;
↑當前面說的橋梁建好之後才能開始送貨,如果你沒有做這個開關的話,
程式一執行就會不停地送貨,不停地墜河,不停地報錯,
這點要注意一下XD。

@RPC
↑在寫【步驟】之前會先有RPC的標記,這樣程式才看得懂那串是送貨用的function。

function Attack(W:int){
↑這是我的【步驟】,叫做Attack,W則是會存放呼叫時丟入的【材料】,
若丟入的【材料】越多,括弧裡面的參數也要隨之增多才行。

sWeapon = W;
↑我的【步驟】是將sWeapon的數值換成W這個【材料】。

@script RequireComponent(NetworkView)
↑告知這裡是RPC尾端,並跟unity說我這包需要用到Network View才可以讀取。

呼,
寫到這裡,總算是將貨物跑過流程送出去了,
最後的問題就是server端該怎麼收貨了。
---

server端的script(紅字為增加的script):
var sWeapon:int;

function OnGUI() {
  if (GUILayout.Button ("Start Server")) {
    Network.InitializeServer(1, 25002, !Network.HavePublicAddress());
    MasterServer.RegisterHost("YourPCRoom", "PhantasyNan", "alpha 1.0");
  }
  GUI.Label(new Rect(Screen.width* 3 /4,10,100,25), "Connections: " +Network.connections.Length);
}

@RPC
function Attack(W:int){
sWeapon = W;
}

@script RequireComponent(NetworkView)

Server端輕鬆很多,只要記得創建自己需要的以及【步驟】內有的參數(不然會報錯),
以及複寫一次【步驟】以供核對,
當貨通過橋送來的時候,
收件的那方就會拿對方的【步驟】單跟自己的【步驟】單核對一下,
然後將附上的【材料】套入【步驟】跑一次就算收件完成。
依照慣例,
解釋一下剛剛新增的分別代表什麼意思:

var sWeapon:int;
↑新增一個整數。

@RPC
↑宣告我這邊之下是RPC用的function喔~

function Attack(W:int){
↑這是我的【步驟】,叫做Attack,W則是會存放貨送過來時附上的【材料】,
若寄件者丟入的【材料】越多,收貨時得到的【材料】越多。

sWeapon = W;
↑我的【步驟】是將sWeapon的數值換成W這個【材料】,
因此Server端就會將自己的sWeapon換成送來的【材料】W,
而Client那邊也是有一個sWeapon,那其實沒什麼用,只是因為沒假設的話就會報錯。

@script RequireComponent(NetworkView)
↑告知這裡是RPC尾端,並跟unity說我這包需要用到Network View才可以讀取。

額外要提的注意事項是,
用電腦當server的時候,輸出PC執行檔打開,會跳出防火牆的允許訊息,
允許之後雖然client可以連上,但是關掉之後再開就不能使用了,
因為再次打開時就不會跳允許的視窗了,會被自動擋掉,
關於這點我還不確定有什麼好方法,
不過暫時關掉防火牆可以立即解決這個窘境X"D,
有空試試有沒有別的比較安全的作法,找到會在更新這篇文。
---
好了,打了一個早上終於結束了!!
基本上這份教學就到這裡為止,
以下是使用這樣的方法製作的遊戲 - 的遊玩影片,
完成度不高,只有兩關,
基本上這只是我自己做著玩的而已:

【音樂節奏遊戲】
試玩影片 第一關(沒有行動跟電腦遙控)
試玩影片 第二關(有遙控)

再來是當時做好這個功能時的測試影片:
【功能測試】

最後覆蓋一張圖當結尾:
啊!我是小草!很榮幸參與這個動畫!
有這樣壯烈的出場機會真是非常感謝!!
圖:霸氣的 S 動畫大大
這是我們的畢業製作,變秘危機,
5.1號開始在新一代展出~ 來嘛來嘛
---
下台一鞠躬。
有哪裡有問題或是錯誤的請提出,歡迎討論,謝謝。
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=2753711
All rights reserved. 版權所有,保留一切權利

相關創作

留言共 1 篇留言

哈囉你好嗎
你好! 我是學unity的新手 你這篇文章打得有點快我有點看不太懂 請問有推薦學習手機與電腦連線的網頁或書本嗎

09-02 20:37

愛錢的乾隆
不知道是不是隔太久沒上線所以沒有提醒... 當初我是看官方給的api,不懂的屬性就google,有幾篇國外文章也有做範例出來,若你還需要我再找找,有找到再說。11-30 20:32
我要留言提醒:您尚未登入,請先登入再留言

4喜歡★joe923692000 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:雜圖 - 男角一枚(遊戲... 後一篇:銘傳大學畢業製作動畫作品...

追蹤私訊切換新版閱覽

作品資料夾

blacktor讀者
【奇幻中篇】《殼中宇宙》:其二 https://home.gamer.com.tw/artwork.php?sn=5081810看更多我要大聲說16小時前


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】