Unity3D腳本編程--基本概念


1. 簡單介紹

    在Unity3D中,游戲對象(GameObject)的行為是由附加其上的腳本來控制的,游戲開發人員通過編寫腳本來控制游戲中的全部對象,如移動Camera等。

GameObject能夠被附加不同類型的組件。但每種類型的組件僅僅能有一個或沒有。

腳本本質上也是一種組件。

     在Unity3D中默認的腳本代碼例如以下所看到的:    

<span style="font-family:Arial;"><span style="font-family:Arial;">// ***** C# script *****
using UnityEngine;
using System.Collections;

public class ffc : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}

	/ Update is called once per frame
	void Update () {
	}
}

//***** Java script *****

#pragma strict

function Start () {
}

function Update () {

}
</span></span>

    由此可見,腳本代碼與大家熟悉的Java代碼類似,即都是由下面兩部分組成:

    • 變量

    • 函數

   • 其他代碼:在不論什么函數之外的代碼在物體被載入的時候執行。這個能夠用來初始化腳本狀態。

  MonoBehaviour是全部腳本的基類。每一個Javascript腳本自己主動繼承MonoBehaviour,使用C#或Boo時,須要顯式繼承MonoBehaviour.       

1.1 腳本成員變量

      腳本變量就是指類的成員變量(即在JavaScript或C#或Boo中定義的成員變量,而不是基類MonoBehaviour中定義的變量),在Unity3D中將成員變量設為公有的時候,當把它附加到游戲對象后。能夠在游戲對象的監視面板中的腳本組件那欄里面看到該“公有變量”。即能夠在編輯器中直接對該公有變量進行賦值,同一時候在Debug狀態下也能夠在面板中看到它的值。

1.2 基類可被繼承的成員變量(內置變量)

           變量名                                                                      描寫敘述                                                                               
transform The Transform attached to this GameObject (null if there is none attached).
rigidbody The Rigidbody attached to this GameObject (null if there is none attached).
camera The Camera attached to this GameObject (null if there is none attached).
light The Light attached to this GameObject (null if there is none attached).
animation The Animation attached to this GameObject (null if there is none attached).
constantForce The ConstantForce attached to this GameObject (null if there is none attached).
renderer The Renderer attached to this GameObject (null if there is none attached).
audio The AudioSource attached to this GameObject (null if there is none attached).
guiText The GUIText attached to this GameObject (null if there is none attached).
networkView The NetworkView attached to this GameObject (Read Only). (null if there is none attached)
guiTexture The GUITexture attached to this GameObject (Read Only). (null if there is none attached)
collider The Collider attached to this GameObject (null if there is none attached).
hingeJoint The HingeJoint attached to this GameObject (null if there is none attached).
particleEmitter The ParticleEmitter attached to this GameObject (null if there is none attached).
gameObject The game object this component is attached to. A component is always attached to a game object.
tag The tag of this game object.


1.3 基類可被繼承的類函數    

   類函數                                描寫敘述                                   
Destroy Removes a gameobject, component or asset.
DestroyImmediate Destroys the object obj immediately. It is strongly recommended to use Destroy instead.
DontDestroyOnLoad Makes the object target not be destroyed automatically when loading a new scene.
FindObjectOfType Returns the first active loaded object of Type type.
FindObjectsOfType Returns a list of all active loaded objects of Type type.
Instantiate Clones the object original and returns the clone.

1.4 基類可被繼承的函數

            類函數                                     描寫敘述                                
GetComponent Returns the component ofType type if the game object has one attached, null if it doesn't.
function GetComponent (type :Type) : Component
GetComponent Returns the component withnametype if the game object has one attached, null if it doesn't.
function 
GetComponent (type :string) : Component
GetComponentInChildren Returns the component of Type type in the GameObject or any of its children using depth first search.
GetComponentsInChildren Returns all components of Type type in the GameObject or any of its children.
GetComponents Returns all components of Type type in the GameObject.
CompareTag Is this game object tagged tag?
SendMessageUpwards Calls the method named methodName on every MonoBehaviour in this game object and on every ancestor of the behaviour
SendMessage Calls the method named methodName on every MonoBehaviour in this game object.
BroadcastMessage Calls the method named methodName on every MonoBehaviour in this game object or any of its children.
GetInstanceID Returns the instance id of the object.
ToString Returns the name of the game object.

1.5 基類可重寫函數

1.5.1  常規更新事件

     函數名                                                                        描寫敘述
Update Update is called every frame, if the MonoBehaviour is enabled.
LateUpdate LateUpdate is called every frame, if the Behaviour is enabled.
LateUpdate is called after all Update functions have been called.
This is useful to order script execution. For example a follow camera
should always be implemented in LateUpdate because it tracks
objects that might have moved inside Update.
FixedUpdate This function is called every fixed framerate frame, if the MonoBehaviour is enabled.

1.5.2 初始化事件

         函數名                                                            描寫敘述                                                                                     
Awake Awake is called when the script instance is being loaded.
Start Start is called just before any of the Update methods is called the first time.
Reset Reset to default values.

1.5.3 GUI元素或Collider碰撞體事件

      函數名                                                    描寫敘述                                                                         
OnMouseEnter nMouseEnter is called when the mouse entered the GUIElement or Collider.
OnMouseOver OnMouseOver is called every frame while the mouse is over the GUIElement or Collider.
OnMouseExit OnMouseExit is called when the mouse is not any longer over the GUIElement or Collider.
OnMouseDown OnMouseDown is called when the user has pressed the mouse button while over the GUIElement or Collider.
OnMouseUp OnMouseUp is called when the user has released the mouse button.
OnMouseUpAsButton OnMouseUpAsButton is only called when the mouse is released over the same GUIElement or Collider as it was pressed. 
OnMouseDrag OnMouseDrag is called when the user has clicked on a GUIElement or Collider and is still holding down the mouse.

1.5.4 Collider碰撞體事件

         函數名                                                              描寫敘述                          
OnTriggerEnter OnTriggerEnter is called when the Collider other enters the trigger.
OnTriggerExit OnTriggerExit is called when the Collider other has stopped touching the trigger.
OnTriggerStay OnTriggerStay is called once per frame for every Collider other that is touching the trigger.

1.5.5 Collider碰撞體或rigibody剛體事件

          函數名                                                       描寫敘述                                                                                                      
OnCollisionEnter OnCollisionEnter is called when this collider/rigidbody has begun touching another rigidbody/collider.
OnCollisionExit OnCollisionExit is called when this collider/rigidbody has stopped touching another rigidbody/collider.
OnCollisionStay OnCollisionStay is called once per frame for every collider/rigidbody that is touching rigidbody/collider.

2. 控制游戲對象(GameObject)

    在Unity3D中,能夠在監視器面板中改動物體的組件屬性,可是很多其它的時候,須要使用腳本來進行動態操作。

2.1 訪問組件

    最常見的一個情形是須要使用腳本訪問附加到同樣游戲對象(GameObject)上的還有一個組件(當前腳本就是一個組件,其它的組件也就是還有一個組件了)。

一個組件實質上是一個類的實例。因而首先須要做的是獲取想要操作的組件實例的引用。這個通過GetComponent函數來實現。典型的,可能會想要將一個組件賦值給一個變量,例如以下代碼所看到的:  

void Start () {
    Rigidbody rb = GetComponent<Rigidbody>();
}

     一旦獲取了組件實例的引用,就能夠對它的屬性進行想要的操作。同一時候也能夠調用它的一些功能函數。

     假設想要訪問還有一個腳本文件。也能夠使用GetComponent,僅僅需使用腳本的類名作為該函數的組件類型參數(由於腳本本來就也是一個組件)。

// You can access script components in the same way as other components.
function Start () {
	var someScript : ExampleScript;
	someScript = GetComponent (ExampleScript);
	someScript.DoSomething ();
}


    假設想要去獲取一個並沒有加入到當前游戲對象的組件。GetComponent函數會返回null。假設試圖去改變一個null對象上的不論什么值,將會發生null引用錯誤。

    因為一些組件類型常常使用。unity提供了一些內置的變量來訪問它們,參見1.2(內置變量)。其演示樣例代碼例如以下:

void Start () {
   transform.position = Vector3.zero;
}

2.2 訪問其它對象

     盡管游戲對象(GameObject)都有各自的組件(包含腳本)進行處理,使用代碼進行跟蹤其它物體是常有的事。

比如,一個追趕的敵人可能須要知道玩家的位置,Unity提供了一系列的方法來獲取其它對象,以適合不同的場合。

2.2.1 將對象【靜態】鏈接到公有成員變量

    最直接的辦法是將一個游戲對象加入到腳本的公有成員變量上。直接在編輯器中將須要訪問的游戲對象拖到相應腳本組件的那個公有成員變量上,Unity3D會自己主動依據變量的類型將加入的游戲對象中同樣的組件類型映射到該變量。

    比如將一個游戲對象拖給一個Transform的成員變量。就會自己主動的將游戲對象的Transform組件和該變量映射起來。
直接將對象和變量鏈接起來在處理須要有永久鏈接的對象的時候是最實用的方法。

同一時候也能夠使用一個數組變量和幾個同樣類型的對象鏈接起來,可是這樣的鏈接必須在Unity3D編輯器中完畢,而不能在執行時進行

2.2.2 【動態】定位其他對象

2.2.2.1 查找子物體

      假設一個游戲場景中有非常多同一類型的對象,比如敵人、路點(waypoints)和障礙物。這些對象在游戲中須要由一個特定的腳本來監視和響應。這個時候使用變量來鏈接這些對象太過麻煩。對於這樣的情況。通常更好的方法是將一系列的對象加入到一個父對象以下,這些子對象能夠通過使用父對象的Transfrom組件來獲得。


public class WaypointManager : MonoBehaviour {  
   public Transform waypoints;  
   void Start() {  
       waypoints = new Transform[transform.childCount];  

       int i = 0;  
       for (Transform t in transform) {  
          waypoints[i++] = t;  
       }  
   }  
}  

    同一時候也能夠使用Tranfrom.Find來查找某個詳細的子對象。使用Transform來進行對象查找操作是由於每個游戲對象都有Transfrom組件。

2.2.2.2 通過名稱或標簽訪問對象

   僅僅要有一些信息。在層級場景中的不論什么位置定位到該游戲對象是可能的。單個對象能夠通過GameObject.Find函數進行查找。例如以下:  

GameObject player;

void Start() {
   player = GameObject.Find("MainHeroCharacter");
}

   某個對象或者一系列的對象也能夠分別通過GameObject.FindWithTag和GameObject.FindObjectsWidthTag函數進行定位。

2.2.2.3 查找特定類型的對象

     static Object  FindObjectOfType(Type  type)
     返回指定類型對象中的第一個活動的載入對象, 須要注意的是這個函數非常慢(可能是因為要在整個場景中進行遍歷),不推薦每一幀都使用這個函數。在大多數情況下能夠使用單件模式。比如:
      Camera cam = FindObjectOfType(typeof(Camera)) as Camera;
      因為該函數返回的類型是Object,所以須要使用as進行一下強制轉換。


      static Object[ ] FindObjectsOfType(Type type);
      返回指定類型的載入活動對象的列表。速度也慢

       HingeJoint[ ]  hinges = FindObjectsOfType(typeof(HingeJoint))  as  HingeJoint[ ];

3. 創建和銷毀對象

     在執行時創建和銷毀對象是常有的事。

在Unity3D中。能夠使用Instantiate函數對現有的一個對象做一個拷貝來創建一個新的游戲對象。

     實例化很多其它通經常使用於實例投射物(如子彈、榴彈、破片、飛行的鐵球等)。AI敵人,粒子爆炸或破壞物體的替代品。

// Instantiates 10 copies of prefab each 2 units apart from each other
var prefab : Transform;
for (var i : int = 0;i < 10; i++) {
	Instantiate (prefab, Vector3(i * 2.0, 0, 0), Quaternion.identity);
}
    值得注意的是用於進行拷貝的對象並不一定須要放置在場景中。

更普遍的做法是將一個預設(Prefab)拖到腳本的相應公有成員變量上,實例化的時候直接對這個成員變量進行實例化就可以。

// Instantiate a rigidbody then set the velocity
var projectile : Rigidbody;
function Update () {
	// Ctrl was pressed, launch a projectile
	//按Ctrl發射炮彈
	if (Input.GetButtonDown("Fire1")) {
		// Instantiate the projectile at the position and rotation of this transform
		//在該變換位置和旋轉。實例化炮彈
		var clone : Rigidbody;
		clone = Instantiate(projectile, transform.position, transform.rotation);

		// Give the cloned object an initial velocity along the current object's Z axis
		//沿着當前物體的Z軸給克隆的物體一個初速度。

clone.velocity = transform.TransformDirection (Vector3.forward * 10); } }


    實例化也能直接克隆腳本實例,整個游戲物體層次將被克隆。而且返回被克隆腳本的實例。

   同一時候也有一個Destroy函數在幀更新函數完畢后或設定的一個延時時間后銷毀一個對象。

// Kills the game object
//銷毀游戲物體
Destroy (gameObject);

// Removes this script instance from the game object
//從游戲物體刪除該腳本實例
Destroy (this);

// Removes the rigidbody from the game object
//從游戲物體刪除剛體
Destroy (rigidbody);

// Kills the game object in 5 seconds after loading the object
//載入物體5秒后銷毀游戲物體
Destroy (gameObject, 5);

// When the user presses Ctrl, it will remove the script
// named FooScript from the game object
//當按下Ctrl將從游戲物體刪除名為FooScript的腳本
function Update () {
	if (Input.GetButton ("Fire1") && GetComponent (FooScript))
		Destroy (GetComponent (FooScript));
}

    注意到Destroy函數能夠銷毀單獨的組件而不正確游戲對象本身產生影響,一個通常易犯的錯誤是Destroy(this); 這句代碼只銷毀腳本組件,而不銷毀該腳本所附加在的對象。

4. 協程(Coroutines)

     一個coroutine就像一個能夠暫停運行並將控制權返回給Unity3D的函數,可是在下一幀的時候又能夠在它停止的位置繼續運行。在C#中,這樣聲明一個coroutine:

IEnumerator Fade() {  
   for (float f = 1f; f <= 0; f -= 0.1f) {  
      Color c = renderer.material.color;  
      c.alpha = f;  
      renderer.material.color = c;  
      yield return;  
   }  
}  

    實質上它是一個返回類型為IEnumerator的函數,同一時候在函數體中添加了yield return這句代碼。yield return這行就是會在運行的時候暫停、在下一幀的時候恢復運行的位置。要啟動coroutine,須要使用StartCorutine函數。

void Update() {  
   if (Input.GetKeyDown("f")) {  
      StartCoroutine("Fade");  
   }  
} 

    默認的情況下。一個coroutine在它暫停后的下一幀恢復,可是也能夠使用WaitFroSeconds來引入一個延時。


IEnumerator Fade() {  
	for (float f = 1f; f <= 0; f -= 0.1f) {  
		Color c = renderer.material.color;  
		c.alpha = f;  
		renderer.material.color = c;  
		yield return new WaitForSeconds(.1f);  
	}  
}  

    這個能夠用於產生一個隨時間變化的效果,同一時候也是一個用於進行優化的有效方法。游戲中的很多人物須要周期性的運行。最經常使用的做法是將它們包括在Update函數中。可是Update函數通常每秒會調用多次。

當有的任務並不須要這么頻繁的被調用的時候,能夠將它放在一個coroutine中按一定時間進行調用,而不是每一幀都調用。


參考:http://game.ceeger.com/Script/



免責聲明!

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



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