Unity常用的函數和遇到的C#的知識整理

看Unity的視頻也有一段時間了,把視頻裏面遇到的東西稍微記錄一下,

這些東西也算是Unity常用的,整理方便日後要用的的時候來搜索查看,

有些東西要用到但是比較少一點,不容易想起,這裏記錄下。

好記性不如爛筆頭,以後會不定期更新。





Invoke("functionName",time)   

功能:在time時間之後執行函數functionName(),這裏這句話和functionName()在同一個腳本,至於調用其他腳本的函數好像不可行。

這裏引用一篇對比介紹Invoke的文章:點擊打開鏈接


InvokeRepeating("functionName",time,repeatTime)

功能:  在time時間之後執行函數functionName(),之後每repeatingTime時間再次執行functionName();

這裏再引用一篇介紹InvokeRepeating的文章:點擊打開鏈接




get和set

功能:get和set是屬性特有的兩個方法。屬性是對字段的封裝,是爲了程序數據的安全性考慮的。

總的來說,字段有兩種操作權限,就是獲取和修改,就分別對應的是get和set方法了,可以通過制定get和set方法來限定字段的訪問權限。

這裏遇見的是用在單例模式的時候,將腳本實例化物體賦值給私有變量,然後通過get、set來訪問該腳本類型的變量,

然後調用其中的方法和屬性,get、set保證數據安全性。

private int _age;//年齡 字段
public int Age
{
    get 
   {
      return _age;  
   }
   set
   {
       if(_age<0 || _age>150)  _age=null;
       
       else _age=value; 
    transform.Find("Label").GetComponent<UILabel>().text=""+age;
    }     
 }

調用的時候直接.Age就可以了,寫了set的函數可以直接賦值Age=?,只寫了get就不行。

這裏引用一篇易懂的文章:點擊打開鏈接




SendMessage("functionName",parameters)

功能:調用函數

這裏引用一篇簡單的文章:點擊打開鏈接



Params 

功能:用在函數聲明時候放在數組參數聲明前面,用以傳遞不確定個數的同一類參數。

例如,聲明時是method(params int i[]);則調用時候可以是mathod(1)、mathod(2,3)、mathod(1,2,3,4)等等。

這裏引用一篇言簡意賅的文章:點擊打開鏈接




[HideInInspector]

功能:當你希望有些屬性在別的類別的腳本里直接訪問到,你把它設置爲public屬性。

但是在腳本編譯好後,你又不希望它出現在unity的Inspector面板,可以在

public前面加上這段話。

這裏引用一篇相關術語介紹的文章:點擊打開鏈接



找到在Inspector面板中不啓用的物體

如圖


這樣的物體我們也可以直接在代碼中找到他。代碼如下:

 this.transform.parent.Find("Conatainer");

其中的this是和Container的父物體相同的物體。

比如這個是NGUI的物體,然後他的transform的父物體就是

UIRoot,這種方法可以找到Unity中沒有啓用的物體的transform,

如果要找GameObject,可以在後面加上後綴.gameobject。



三維世界裏物體旋轉的幾種方法

  • 當你的GameObject使用了RigidBody組件,可以調用RigidBody裏面的AngularSpeed屬性,來給角速度賦值。FixedUpda和Update幀長不同,FixedUpdate是在固定幀調用的,一般Rigidbody物理位移的操作可以放在FixedUpdate裏面。例如: 在Update函數中
       float h = Input.GetAxis("Horizontal");
       rigidbody.angularVelocity = transform.up * h * angularSpeed;
  • 當然RigidBody類還提供了 MoveRotation()方法,直接將物體移動至某個角度,所以當你需要移動的過程的時候要注意傳進去的參數了。比如:在Update()中
       float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");
            GetComponent<Rigidbody>().MoveRotation(Quaternion.Euler(transform.rotation.x + h * speed * Time.deltaTime, 0, transform.rotation.z + v * speed * Time.deltaTime));
  • 使用transform的Rotate()方法,這個很多人應該都知道了,這個方法有六個重載,具體內容可以查看聖典:點擊打開鏈接
  • 使用Vector3.Lerp函數,實現一個有過程的旋轉:
    <span style="white-space:pre">	</span>targetVector=targetTransform.position-transform.position;
    
            transform.forward = Vector3.Lerp(transform.forward,targetVector,rotateSpeed*Time.deltaTime);
    	



三維世界裏物體移動的幾種方法
  • 當你的GameObject使用了RigidBody組件,裏面有個方法叫做MovePosition,和MoveRotation一樣,直接將物體移動至某一位置,所以傳參要注意一下。例如,在Update()中:

float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
GetComponent<Rigidbody>().MovePosition(transform.position + new Vector3(h, 0, v) * speed * Time.deltaTime);

  • Transform.Translate()函數,這個不多說了,最直接常用的函數,將物體向目標點移動
  • 當你的GameObject使用了CharacterController組件,可以調用CharacterController的SimpleMove和Move方法實現移動。下面引用一篇文章可以瞭解下SimpleMove方法:點擊打開鏈接

三維世界裏物體跳躍的幾種方法

使用CharacterController的時候,可以在Update或者FixedUpdate中使用其move方法,在必要的時候(比如按下空格鍵)添加向上的速度,實現跳躍:

  upSpeed = transform.up * jumpSpeed;
 upSpeed.y -= gravity * Time.deltaTime;
 myController.Move((upSpeed + transform.forward)*Time.deltaTime);


transform.TransformDirection

雖然一直搞不清楚這個函數的具體意思,但是我試用過好多次發現他能把世界座標的z軸轉化爲自身的z軸。即如果角色想沿着自身的z軸前進而不是世界的z軸,可以使用這個函數。例如:

transform.TransformDirection(new Vector3(0, 0, 1))

這在有時transform.forward不起效果的時候很有用。


如果在腳本里寫有Invoke()來調用方法,然後禁用了該腳本,但是該腳本的某些效果並沒有停止,請記得在停用腳本的時候調用CancelInvoke,有參無參

就自己判斷了。記得自己在這裏找bug找了好久...



Unity更改腳本的執行順序

單擊腳本,然後在Inspector面板可以看到有一個Excution Order按鈕


點擊之後界面如圖:


在這裏旋轉,格子裏的數字越小越在上面,代表越先執行。





繼承了UIDragDropItem的類的Start()方法如果要重寫記得要在重寫的Start()方法裏面寫上base.Start(),否則會調用出錯,以後繼承了其他功能類如果遇到錯誤可以嘗試此思路。





獲得鼠標位置的方法:

在普通世界座標中,我們獲取物體鼠標位置的方法通常是使用

Camera.main.ScreenToWorldPoint(Input.mousePosition);

這個方法,這裏獲得的三維座標的z和攝像機相同,而不是0,所以有必要的話要改z座標。

然後在NGUI中獲得鼠標位置的方法,則是通過

 UICamera.currentCamera.ScreenToWorldPoint(Input.mousePosition);
這個方法來獲得的



Unity舊版Animation播放結束的判斷

在舊版動畫中,有時我們需要在前一個動畫播放完成後再播放別的動畫。

if (!myAnim.isPlaying)
        {
            myAnim.CrossFade(aniName);
        }

可以使用animation.isPalying變量來判斷,這裏要注意的是該animationClip的WrapMode是Once,如果是Loop

則isPlaying變量不會變化。至於animation的詳解可以參看我轉載的博客:點擊打開鏈接



查找判斷的物體爲null,而不能判斷子物體或者組件是否爲null

我有時需要某物體的transform,我們查找的時候是應該這樣:

GameObject gObj=GameObject.FindGameObjectWithTag(GameTags.swordMan) as GameObject;
        if ( gObj!= null)
        {
            player = gObj.transform;
        }
        else
        {
            player = GameObject.FindGameObjectWithTag(GameTags.magician).transform;
        }
而不是這樣:

player = GameObject.Find("Swordman").transform;
        if (player == null)
        {
            player = GameObject.Find("Magician").transform;
        }


獲取NGUI的鼠標點擊及相應信息

NGUI提供了一個方便的方法

void OnPress(bool isPress)
    {
        this.isPress = isPress;
    }
這個方法的isPress代表鼠標是否按下,可以通過這個標誌位來在Update

裏面做一些操作。

UICamera.LastTouchPosition表示鼠標在UI界面的點擊位置,

以NGUI設計界面的Root的左下角爲原點。



動態給NGUI按鈕添加點擊響應事件

EventDelegate NormalAttackEvent = new EventDelegate(this, "OnNormalAttackClick");
GameObject.Find("NormalAttack").GetComponent<UIButton>().onClick.Add(NormalAttackEvent);
給名字叫NormalAttack的遊戲物體的按鈕組件添加這個腳本的OnNormalAttackClick的函數。


CharacterController的isGrounded屬性

CharacterController提供了屬性isGrounded以供檢測,但是在使用中發現isGrounded總是返回false,個人認爲CharacterController的SkinWidth要設置合理,皮膚厚度決定了兩個碰撞器可以互相滲入的深度。較大的皮膚厚值度會導致顫抖。小的皮膚厚度值會導致角色被卡住。一個合理的設定是使該值等於半徑(Radius)的10%,再小點檢測會更準確點,但是不能太小


當在FixedUpdate裏面使用CharacterController.Move或者SimpleMove出現卡頓的時候,不妨把相關代碼放在Update裏面,卡頓現象可能就會得到解決。


在Unity中一些你想要new出來的類一定不要繼承monobehaviour,如果忘記了這一點,你會使勁排查你的程序邏輯卻排查不出錯誤,過了猴年馬月後才發現一切正常,只是你要new的類繼承了monobehaviour,就new不出來了。


發佈了25 篇原創文章 · 獲贊 13 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章