看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不出來了。