Unity3D中JavaScript與C#對比


 第一個也是最容易區分的一點就是聲明變量和方法。
JavaScript的腳本:

1.  private var cubeTransform; 

在C#中,同樣的代碼則會是:

1.  private Transform cubeTransform; 

這對方法同樣適用,在C#中,一個方法什么值也沒有返回,那么他的返回值為 void 類型,但是在JavaScript中則可以省略。

類的繼承也是不同的。在JavaScript和C#中,方法是隱型並且不可重載,除非方法聲明中添加虛擬關鍵字。不同的是C#只重載那些包含重載關鍵字的方法。而JavaScript不需要關鍵詞,只要重載類方法就可繼承他們。我們來看一個JavaScript類繼承的例子:

1.  class Weapon extends Item 

2.  { 

3.       //Class members and declarations 

4.  } 

在C#中,同樣的代碼則會是:

1.  public class Weapon : Item 

2.  { 

3.       //Class members and declarations 

4.  } 

這就是這兩種代碼的主要區別,實際上他需要定義全部的東西,像執行產出代碼,訪問GameObject和組件,激光投射等等。還有一些其他的不同點,比如導入函數庫的關鍵字(在JavaScript中用“Import”,在C#中使用“using”),但是這些聲明和關鍵字的不同就比較容易明白了。

1.  //do this: 

2.  private var score:int; 

3.  //instead of this: 

4.  private var score; 

======================================================

使用JavaScript來獲取GameObject很簡單,你只需要調用Find()靜態方法,並把想要的GameObject的名稱作為參數:

 

1.  private var pawnGO:GameObject; 

2.  function Awake() 

3.  { 

4.      pawnGO = GameObject.Find("Pawn"); 

5.  } 

 

用C#也很相似:

 

1.  using UnityEngine; 

2.  using System.Collections; 

3.   

4.  public class PawnGetter : MonoBehaviour 

5.  { 

6.      private GameObject pawnGO; 

7.   

8.      void Awake () 

9.      { 

10.         pawnGO = GameObject.Find("Pawn"); 

11.     } 

12. } 

在不考慮兩種語言的關鍵字和格式不同的情況下,代碼是完全一樣的(第一個代碼的第四行和第二個代碼的第八行是相同的)。不管代碼是強類型還是弱類型,GameObject.Find()方法總是會返回一個GameObject值。

 

 

現在,讓我們看看如何獲得一個GameObject上的組件。假設“PawnMover”組件賦給“Pawn”GameObject,讓我們來看看如何使用JavaScript獲得“PawnMover”組件:

1.  private var pawnGO:GameObject; 

2.  private var pmSC:PawnMover; 

3.  function Awake() 

4.  { 

5.      pawnGO = GameObject.Find("Pawn"); 

6.      pmSC = pawnGO.GetComponent("PawnMover"); 

7.  } 

基本上,要獲得“PawnMover”組件,我們所需要做的就是從“Pawn”GameObject調用GetComponent()方法,並把所需組件的名稱作為參數。除了名稱,我們也可以通過組件類型作為參數,但是像上面的例子我們用名字就行了。因為JavaScript是弱類型,返回值為組件,我們不需要把組件給PawnMover 類作為結果。在C#中也是一樣的:

1.  using UnityEngine; 

2.  using System.Collections; 

3.   

4.  public class PawnGetter : MonoBehaviour 

5.  { 

6.      private GameObject pawnGO; 

7.      private PawnMover pmSC; 

8.   

9.      void Awake() 

10.     { 

11.         pawnGO = GameObject.Find("Pawn"); 

12.         //returns a CS0266 error 

13.         pmSC = pawnGO.GetComponent("PawnMover");//<=returns a CS0266 error 

14.         //this is the right way to do it when using C# 

15.         pmSC = pawnGO.GetComponent< PawnMover >();  

16.     } 

17. } 

用C#就不可能只是調用GetComponent()方法並把該組件的名稱作為參數了,這樣他會導致錯誤CS0266,也就是說C#不能從一個類型隱型轉換為另一個格式。因為C#屬於強類型,我們不能把組件類型轉換為PawnMover類型。我們需要調用一個方法傳遞這個類型,強制GetComponent()方法返回“PawnMover”對象而不是組件。

======================================================

 

這系列第三節,解釋JavaScript和C#在Unity3d游戲引擎中編程時有什么不同。建議你最好先去閱讀第一和第二節,方便理解這節內容。

在第三節中,主要講解用JavaScript和C#讓一個GameObject向前移動有什么不同。現在我們來看一段使用JavaScript讓一個GameObject向前移動的代碼:

 

 

public var goTransform:Transform;

private var vel:int = 2;//how fast the game object is being moved 

 

 

function Awake() 

{

//get this GameObject's Transform

  goTransform = this.GetComponent(Transform);

}

 

 

// Update is called once per frame 

function Update() 

{

//moves the containing GameObject forward

goTransform.position.z = goTransform.position.z + vel;

}

把這個腳本的目的是在每一個更新周期使goTransform的z軸坐標增加來控制讓goTransform向前移動的,現在讓我們看看用C#編寫代碼會是什么樣的:

using UnityEngine; 

using System.Collections;   

public class PawnMover : MonoBehaviour 

{

public Transform goTransform; 

private int vel = 2;//how fast the game object is being moved  

 

void Awake() 

    { 

         //get this GameObject's Transform 

        goTransform = this.GetComponent<Transform>(); 

    }   

// Update is called once per frame 

     void Update() 

    { 

         //returns a CS1612 error 

        goTransform.position.z=goTransform.position.z + vel;//<=returns a CS1612 error 

         //this is the right way to do it when using C# 

goTransform.Translate(Vector3.forward * vel);//moves the containing GameObject forward 

 

    } 

這里我們可以看到,在C#中不能像JavaScript腳本中那樣直接改變goTransform的z軸坐標值來移動,這樣會產生CS1612error,因為我們是要改變一個值而不是引用該值。為了避免這個錯誤,在用C#編寫腳本時,我們用方法移動GameObejct,比如Translate()、 Rotate()、 RotateAround()等等。這些方法都是Transform類得公共成員變量。

=======================================================

 


         yielding pauses代碼對於游戲編程是相當有用的,你可以用它更好的控制你游戲中的事件。無論是用JavaScript或C#都不能簡單的中斷Update()方法。相信你已經猜到了,我們今天要議論的是這兩種語言對此的解決方案有什么不同。我們這節中會給出這種解決方案的常用實例。現在我們來看看JavaScript是如何yield的:

 

 

private var textS:String; 

private var counter:float = 0; 

function Update () 

    //call the function that waits three seconds to execute 

    WaitThreeSeconds(); 

//This function waits three seconds before executing 

function WaitThreeSeconds() 

    //Waits three seconds 

    yield WaitForSeconds(3); 

    //converts the counter to a String and stores its value in textS 

    textS = "Three seconds has passed, now I'm counting..."+counter.ToString(); 

    //add one to the counter 

    ++counter; 

 

function OnGUI() 

    //The next line displays the first line of text 

    GUI.Label(new Rect(20,20,250,20), "I will start counting in 3 seconds."); 

    //Displays the counter 

    GUI.Label(new Rect(20,40,500,20),textS); 

這個代碼在屏幕上輸出了兩個文本,第一行會在開始不久就被渲染出來,第二行只會在暫停3秒后出現,yield代碼只會執行一次,然后再正常執行Update()循環(也就是說不會再等三秒在去執行一次WaitThreeSeconds())。有一點要注意,我們知道能在函數內用yield,Update()方法是不能被暫停的。

現在來看看C#代碼:

using UnityEngine; 

using System.Collections; 

public class Yield : MonoBehaviour 

    private string textS; 

    private float counter = 0; 

    void Update () 

    { 

        //doesn't generate an error but doesn't work either. 

        WaitThreeSeconds();//<=does nothing 

        //start the coroutine named WaitThreeSeconds 

        StartCoroutine("WaitThreeSeconds");//<=right 

    } 

    //Waits three seconds before executing 

    IEnumerator WaitThreeSeconds() 

    { 

        //Waits three seconds 

        yield return new WaitForSeconds(3); 

        //converts the counter to a String and stores its value in textS 

        textS = "Three seconds has passed, now I'm counting..."+counter.ToString(); 

        //add one to the counter 

        ++counter; 

    } 

     

    void OnGUI() 

    { 

        //The next line displays the first line of text 

        GUI.Label(new Rect(20,20,250,20), "I will start counting in 3 seconds."); 

        //Displays the counter 

        GUI.Label(new Rect(20,40,500,20),textS); 

    } 

主要區別就是我們在C#中不能把yield放在函數中使用,需要使用IEnumerator接口,之所以這樣只是因為C#就是這么設計的(關於IEnumerator接口的更多信息可以在http://www.devarticles.com/c/a/C-Sharp/Interface-IEnumerable-and-IEnumerator-in-C-sharp/2/這里找到)我們不能像調用普通函數那樣調用WaitThreeSeconds(),即便那么做也不會有任何反應的。所以我們的解決辦法就是想調用協同那樣調用WaitThreeSeconds()。(例如14行)

另外一個區別就是在21行,我們要用yield return new WaitForSeconds(3)來替換 yield WaitForSeconds(3)代碼,因為我們用IEnumerator接口需要一個返回值。

====================================================

 


先來看點兒基礎知識:何為射線投射?顧名思義,就是用程序模擬了一個現實生活中被打出的一道射線(“Ray”,譯者:O(∩_∩)O哈哈~我的名字)。在游戲編程中相當有用,Raycast類可以返回源點到射線碰撞某物體的距離(有的時候被用作得到碰撞物體的名稱)。Unity3D沒有單獨的Raycast類,它是被Physics, RaycastHit 和 Ray 功能分散的類。

我來舉一個用JavaScript投射射線的例子:

 

//Creates a ray object 

private var ray : Ray; 

//creates a RaycastHit, to query informarion about the objects that are colliding with the ray 

private var hit : RaycastHit  =  new RaycastHit(); 

//Get this GameObject's transform 

private var capsTrans : Transform; 

 

function Awake() 

//get this Transform 

capsTrans = this.GetComponent(Transform); 

// Update is called once per frame 

function Update () 

//recreate the ray every frame 

ray = new Ray(capsTrans.position, Vector3.left); 

//Casts a ray to see if something have hit it 

if(Physics.Raycast(ray.origin,ray.direction, hit, 10))//cast the ray 10 units in distance 

//Collision has happened, print the distance and name of the object into the console 

Debug.Log(hit.collider.name); 

Debug.Log(hit.distance); 

else 

//the ray isn't colliding with anything 

Debug.Log("none") 

 

來看看它是如何工作的:

首先,我們需要創建一個射線對象(Ray object),並且每幀都要重新創建一次(例如第2和20行),該射線類具備如光線投射的方向和來源等屬性。

然后,我們需要一個RaycastHit類對象,獲取射線與其他GameObject的碰撞發生時的距離和一些其他的詳細信息。

接下來,我們需要從Physics類中調用Raycast()靜態方法(例如23行),這個方法將實際的投射出一道射線,記錄下射線源點、投射方向、RaycastHit 對象和距離這些參數,然后把距離和碰撞結果傳遞到RaycastHit對象。

乍一聽起來可能有些亂,但是多嘗試幾回就熟練了(更多信息請查看http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html),接下來看看C#代碼:

 

using UnityEngine; 

using System.Collections; 

  

public class Raycast : MonoBehaviour 

//Creates a ray object 

private Ray ray; 

//creates a RaycastHit, to query informarion about the objects that are colliding with the ray 

private RaycastHit hit = new RaycastHit(); 

//Get this GameObject's transform 

private Transform capsTrans; 

  

void Awake() 

//get this Transform 

capsTrans = this.GetComponent<Transform>(); 

// Update is called once per frame 

void Update () 

//recreate the ray every frame 

ray = new Ray(capsTrans.position, Vector3.left); 

//Casts a ray to see if something have hit it 

if(Physics.Raycast(ray.origin, ray.direction, out hit, 10))//cast the ray 10 units in distance 

//Collision has happened, print the distance and name of the object into the console 

Debug.Log(hit.collider.name); 

Debug.Log(hit.distance); 

else 

//the ray isn't colliding with anything 

Debug.Log("none") 

 

當投射射線時,這兩種編程語言之間唯一的區別在第28行代碼上。現在來看看我們怎么Out關鍵詞來傳遞hit對象呢?因為在C#中Raycast()方法需要RaycastHit參數做參考,這恰巧也是out關鍵詞做的事情。所以我們用傳遞一個Raycast()的參考來代替傳遞對象(就好像我們在JavaScript中做的那樣)。(更多信息請參考http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM