在Unity3D中使用單個SendMessage送出多重參數

来源:互联网 发布:淘宝金酷娃玩具和谐号 编辑:程序博客网 时间:2024/06/06 07:18
不久前買了一套第三方的Unity Asset,當我專案中的遊戲物件要獲取第三方的數據時,遇到了困難。 因為該套件以C#開發,個人比較習慣使用JavaScript開發,兩個不同語言的程式之間要互通參數本身就有困難,最簡單的解決方案就是透過SendMessage傳遞參數。 但是當你要傳送的參數很多時,真的只能一行一行把每個參數Send出去嗎?

在Unity Answers爬的結果是否定的,當你仔細看SendMessage的程式屬性時,傳遞參數那欄是object屬性,這代表著這裡可以是任何東西,可以是字元、向量、浮點數、布林、單一數據類型的陣列或者是混和數據的物件等等… 因此我再繼續爬下去,最後我實作了JavaScript的接收方,與JavaScript和C#的發送方(因為我個人用JavaScript開發,因此目前還不打算做C#的接受方)。 

接收方 | Receiver
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
varunpkg1:String;
varunpkg2:boolean;
varunpkg3:Vector3;
varunpkg4:float;
vartestMod:boolean=true;
varsupportCS:boolean=false;
 
functionUpdate()
{
 if(testMod)
  gameObject.transform.position=unpkg3;
}
 
functionUnpackage(msgArr:Array)
{
 unpkg1=msgArr[0];
 unpkg2=msgArr[1];
 unpkg3=msgArr[2];
 unpkg4=msgArr[3];
 if(testMod)
 {
  Debug.Log(unpkg1);
  Debug.Log(unpkg2);
  Debug.Log(unpkg3);
  Debug.Log(unpkg4);
  Debug.Log(unpkg1+", and this's the "+unpkg2+". My address is "+unpkg3+", my phone number is "+unpkg4+". Remember to call me!!");
 }
}
 
functionUnpackageCS(msgArrCS:Object)
{
 unpkgCS1=msgArrCS[0];
 unpkgCS2=msgArrCS[1];
 unpkgCS3=msgArrCS[2];
 unpkgCS4=msgArrCS[3];
 if(supportCS && testMod)
 {
  Debug.Log(unpkgCS1);
  Debug.Log(unpkgCS2);
  Debug.Log(unpkgCS3);
  Debug.Log(unpkgCS4);
  Debug.Log(unpkgCS1+", and this's the "+unpkgCS2+". My address is "+unpkgCS3+", my phone number is "+unpkgCS4+". Don't call me!!");
 }
}
原理很簡單,我先宣告我預定要接收的變數與數據類型(本範例分別使用:字元、布林、浮點數、三維向量,來當作示範),然後設置兩個函數分別用來接收JavaScript或C#傳來的參數(不一定要分成兩個函數,其實也可以在同個函數內解決,但為了方便辨識,我分成了兩個函數處理),傳來的參數可以用讀取陣列的方式解開參數內容。

Notes:
a. 函數不需要特別宣告傳值的數據類型也可以處裡,例:msgArr:Array,只打msgArr也是可以使用的;但是切記請勿以無法紀錄傳值的數據類型去宣告,例:Vector2,因為傳值內還有字元和布林,會出現錯誤。
b. 別忘了陣列總是從0開始。
c. 接收函數內部(例:Unpackage)不需要特別宣告變數(例:unpkg1),但是如果這個變數要在別的函數內使用時(例:在Update內使用unpkg1去改變gameObject位置),就需要事先宣告,不然別的函數會認不得。

發送方(JavaScript) | Sender(JavaScript)
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
varmsgValue1:String="I'm a man";
varmsgValue2:boolean=true;
varmsgValue3:Vector3=newVector3(2,4,6);
varmsgValue4:float=1234.5678;
 
publicvarmsgArr=newArray();
 
msgArr.push(msgValue1);
msgArr.push(msgValue2);
msgArr.push(msgValue3);
msgArr.push(msgValue4);
 
varotherObj:boolean=false;
vartargetObj:GameObject;
 
functionStart()
{
 if(otherObj)
  targetObj.SendMessage("Unpackage",msgArr);
 else
  gameObject.SendMessage("Unpackage",msgArr);
}
在開頭宣告我要發送的變數,之後宣告一個新陣列(new Array()),在底下將變數加入到陣列內(Array.push),請記住變數在陣列中的順序依你加入的順序而定(上到下)。 然後SendMessage把此陣列給送出去就好了! JavaScript簡單多囉~

發送方(C#) | Sender(C#)
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using UnityEngine;
using System.Collections;
 
public class Sender : MonoBehaviour
{
 public int valueLength=4;
 public string msgValue1="I'm a man, from C#";
 public bool msgValue2=false;
 public Vector3 msgValue3=newVector3(1,3,5);
 public double msgValue4=8765.4321;
 public bool otherObj=false;
 public GameObject targetObj;
  
 void Start ()
 {
  object[] msgArrCS=newobject[valueLength];
  msgArrCS[0]=msgValue1;
  msgArrCS[1]=msgValue2;
  msgArrCS[2]=msgValue3;
  msgArrCS[3]=msgValue4;
   
  if(otherObj)
   targetObj.SendMessage("UnpackageCS",msgArrCS);
  else
   SendMessage("UnpackageCS",msgArrCS);
 }
}
大致原理同JavaScript,不過C#中同一陣列只能單一數據類型,因此沒辦法用陣列傳值(如果是混和數據類型的話),所以改用Object傳值。 然後C#的陣列一定要有數組大小或者初始值,也就是範例中的valueLength位置,一定要放數值或者動態數值,沒辦法像JavaScript那樣,可以空陣列然後塞變數進去。

Notes:
a. 如果不想用Object存值的話,其實C#還是有使用陣列的解決方案 - 使用「List」,不過太複雜、太麻煩了… 我沒有實作出來,但我還是會在教學最後附上相關連結。

教學在這裡結束,至於以上程式碼我會放到我的GitHub上,GitHub的版本還會附上註解,有興趣的人可以去下載。
原创粉丝点击