一.Unity常用事件執行順序測試
上圖解釋
1.Reset():只會在editor模式下觸發
2.Awake():即在腳本初始化的時候執行一次
3.OnEnable():腳本依附在GameObject上後,場景被啟動時,只有在.SetActive(true)情況才會執行
4.Start():腳本開始運作執行一次
5.FixedUpdate():不受幀率的影響,按固定時間執行,常用於運動
6.Update():每一秒執行相應的次數,這裡的次數即幀數,是根據硬件設備以及內部函數複雜度決定的,可能上一秒60幀,這一秒就是80幀,不唯一
7.LateUpdate():和Update()在同一幀執行
接著註冊一個腳本,編寫如下代碼
在Unity中運行如下:
所以執行順序:Awake>Start>FixedUpdate>Update>LateUpdate
二.C# const 關鍵字
const是一個C#語言的關鍵字,它限定一個變量不允許被改變
const 一般修飾的變量為只讀變量
const 的值是固定的
const是在編譯時可被完全計算的,所以 const int a = b+1;,b是一個變量,顯然不能被編譯
const可以聲明多個常數 public const int x = 1,y =2;
const不允許使用static修飾符
三.Unity場景跳轉的另一種方式
之前我學習到的跳轉場景是建立兩個Scene,通過庫SceneManagement調用函數
今天我學到了一種新的跳轉場景的方式,利用SetActive方法來隱藏或顯示所用的場景。
首先新建兩個Panels,在其中一個Panels中添加一個Button
註冊一個腳本,起名為Scene Manager,將腳本掛載到Canvas上(也可以掛到空物體上)打開腳本,編寫如下代碼
將Panels1和Panels掛載到GameObject類型數組中
接著,在Panel1中的Button中添加一個Onclick,將Canvas拖拽進去之後,選擇SceneManager.panel1;之後運行就可以了
SetActive
在 Unity 中,要激活遊戲對象的方法就是使用SetActive(),就是說通過此方法讓遊戲對象顯示或者隱藏。
格式:
GameObject.SetActive(value);
說明:
(1)GameObject 是定義 GameObject 遊戲對象的變量名
(2)value 是讓物體顯示或者隱藏,類型是bool
四.Unity 切割圖片
首先選擇一張導入的圖片,在Inspector面板中,將圖片格式改為Sprite2D and UI ,然後在Sprite Mode中選擇multiple,然後選擇Sprite Editor。
點擊Slice,選擇Automatic,然後Slice一下,最後點擊右上角的Aplay,一張圖片就會被自動切割好了
五.unity攝像機中clear flags屬性介紹
Clear Flags 清除標記
每個相機在渲染時會存儲顏色和深度信息。屏幕的未繪製部分是空的,默認情況下會顯示天空盒。當你使用多個相機時,每一個都將自己的顏色和深度信息存儲在緩衝區中,還將積累大量的每個相機的渲染數據。當場景中的任何特定相機進行渲染時,你可以設定清除標記以清除緩衝區信息的不同集合。可以通過下面四個選項之一來完成Skybox 天空盒
這是默認設置。在屏幕上空的部分將顯示當前相機的天空盒。如果當前相機沒有設置天空盒,它會默認使用渲染設置(在Edit->Render Settings裡)中選擇的天空盒。然後它將退回使用背景顏色。
Solid Color 純色
屏幕上的任何空的部分將顯示當前相機的背景顏色。
Depth Only 僅深度
如果你想繪製一個玩家的槍而不讓它在環境內部得到裁剪,你要設置一個深度為0的相機來繪製環境,還要另一個深度為1的相機單獨繪製武器。該武器相機的清除標記應設置為僅深度。這將保持環境的圖形顯示在屏幕上,但會丟棄所有關於每個對象在三維空間中的位置的信息。當槍被繪製出來,不透明的部分將完全覆蓋任何已繪製的事物,而不管槍到牆之間如何接近。
Don’t Clear 不清除
該模式不清除任何顏色或深度緩存。其結果是,每幀繪製在下一幀之上,造成圖片效果。這不是用於遊戲的典型方式,最好是與自定義著色器一起使用。
主要學習一下Depth Only:
個人理解為,假設一款FPS射擊遊戲,如果為武器單獨添加一個Camera,並且調整Depth值,使其大於原來的Camera的Depth,這樣這把武器便會永遠顯示在場景中,而不會因為距離太近或者太遠導致武器被裁剪掉。
六.Unity中List數據類型的使用
List類是 ArrayList 類的泛型等效類。該類使用大小可按需動態增加的數組實現 IList 泛型接口。
泛型的好處:它為使用 c#語言編寫面向對象程序增加了極大的效力和靈活性。不會強行對值類型進行裝箱和拆箱,或對引用類型進行向下強制類型轉換,所以性能得到提高。
一.List的基礎用法
a.T為列表中元素類型,現在以string類型作為例子
如:List mList = new List();
b.增加元素:List. Add(T item) 添加一個元素
如:mList.Add("aa");
c.插入元素:Insert(int index, T item); 在index位置添加一個元素
如:mList.Insert(1, "aa");
d.刪除元素: List. Remove(T item) 刪除一個值
如:mList.Remove("aa");
List. RemoveAt(int index); 刪除下標為index的元素
如.:mList.RemoveAt(0);
List. RemoveRange(int index, int count); 從下標index開始,刪除count個元素
如.:mList.RemoveRange(3, 2); //超出刪除的範圍會出錯
注:刪除某元素後,其後面的元素下標自動跟進
七,static關鍵字
一.靜態類
靜態類與非靜態類的重要區別在於靜態類不能實例化,也就是說,不能使用new關鍵字創建靜態類類型的變量。在聲明一個類時使用static關鍵字,意義是:
防止用代碼來實例化該靜態類
防止在類的內部聲明任何實例字段或方法。
特性:
1.僅包含靜態成員
2.無法實例化
3.靜態類的本質,是一個抽象的密封類,所以不能被繼承,也不能被實例化
4.不能包含實例構造函數。
5.如果一個類下面的所有成員,都需要被共享,那麼可以被這個類定義為靜態類
靜態類與私有構造函數區別
1.私有構造器方式仍然可以從類的內部對類進行實例化,而靜態類禁止從任何地方實例化類,其中包括從類自身內部。
2.使用私有構造器的類中,是允許有實例成員的,編譯器不允許靜態類有任何實例成員。
3.使用靜態類的優點在於,編譯器能夠執行檢查以確保不致偶然地添加實例成員,編譯器將保證不會創建此類的實例。
4.C#編譯器會自動把它標記為sealed。這個關鍵字將類指定為不可擴展;換言之,不能從它派生出其他類。
二.靜態成員
1、通過static關鍵字修飾,是屬於類,實例成員屬於對象,在這個類第一次加載的時候,這個類下面的所有靜態成員會被加載。
2、靜態成員只被創建一次,所以靜態成員只有一份,實例成員有多少個對象,就有多少份。
3、類加載的時候,所有的靜態成員就會被創建在“靜態存儲區”裡面,一旦創建直到程序退出,才會被回收。
4、成員需要被共享的時候,方法需要被反覆調用的時候,就可以把這些成員定義為靜態成員。
5、在靜態方法中,不能直接調用實例成員,因為靜態方法被調用的時候,對象還有可能不存在。
6、this/base 關鍵字在靜態方法中不能使用,因為有可能對象還不存在。
7、可以創建這個類的對象,指定對象的成員在靜態方法中操作。
8、在實例方法中,可以調用靜態成員,因為這個時候靜態成員肯定存在。
9、非靜態類可以包含靜態的方法、字段、屬性或事件;
10、無論對一個類創建多少個實例,它的靜態成員都只有一個副本;
11、靜態方法和屬性不能訪問其包含類型中的非靜態字段和事件,並且不能訪問任何對象的實例成員;
12、靜態方法只能被重載,而不能被重寫,因為靜態方法不屬於類的實例成員;
13、雖然字段不能聲明為 static const,但 const 字段的行為在本質上是靜態的。這樣的字段屬於類,不屬於類的實例。
三.什麼時候適合用靜態變量
靜態變量適合存儲一些全局都用得到的公共數據,由於靜態的變量不會隨對象的回收而釋放內存,若是大量濫用則會使內存空間被擠佔,代碼結構混亂複雜,難於維護等問題。
四.為什麼單例模式中要使用靜態變量
類的靜態成員變量就是指的類共享的對象,而單例模式的對象設成靜態就是為了讓該類所有成員共享同一個對象,所以從語義上是合適的;
從語法考慮,常見的單例模式都是通過一個靜態方法(如getInstance)返回其單例,因為靜態方法的內部不能直接使用非靜態變量,所以返回的這個實例就是靜態的。
八,Unity設計模式之單例模式
單例模式是一個基本的設計模式。使用類來實現單例模式可以確保在任何時間只有一個實例對象。當對象不需要在遊戲中多次複製時,推薦使用這種方法。這樣就可以像控制GameManager、AudioController一樣來控制類。
一、單例模式優點
單例模式核心在於對於某個單例類,在系統中同時只存在唯一一個實例,並且該實例容易被外界所訪問;
意味著在內存中,只存在一個實例,減少了內存開銷;
二、單例模式特點
只存在唯一一個實例;
提供統一對外訪問接口,使得全局可對該單例的唯一實例進行訪問;
自行實例化(私有構造函數,不允許外界對其進行實例化)。
三、單例模式使用
資源管理器,資源對象數據的加載和卸載(無狀態不需要實例化的對象);
單一客戶端連接服務器等;
生命週期在遊戲中永不消毀的對象。
四、最簡單的單例程序
每當食物被蛇吃掉之後,用單例生成食物。
九,position與localPosition
position是根據世界原點為中心
localPosition是根據父節點為中心,如果沒有父節點,localPosition和position是沒有區別的
在Unity中無法對transform.position直接賦值
transform.position.x=1;//錯誤
編譯器顯示,無法修改其返回值,因為它不是變量
解釋:
Vector3是一個結構體,而position是一個自動實現的屬性
在C#中,結構體是值類型的,值類型在通過方法傳遞的時候,所傳遞的只是值的副本。
C#的屬性可以說是兩個分別名為get 和set的方法
而當我們寫出形如transform.position.x = 1;這樣的代碼時,是在通過get方法得到position,然後修改position的x字段的值。但是,由於position是結構體類型的,get得到的也只是position的一個副本,而對這個副本所作出的任何修改,都對原positon沒有任何影響,因此這樣的修改是毫無意義的。編譯器會禁止這樣的修改操作。
正確的寫法應該是
transform.localPosition = new Vector3(x, y ,z);
十.Transform.Setparent()
Setparent()函數有兩個重載:
(重載,簡單說,就是函數或者方法有相同的名稱,但是參數列表不相同的情形,這樣的同名不同參數的函數或者方法之間,互相稱之為重載函數或者方法。)
public void SetParent(Transform parent);
public void SetParent(Transform parent, bool worldPositionStays);
第一個是我們常用的只有一個參數的函數,第二個是加了一個是否保持世界座標系的布爾型變量;
如果為true,就保持之前的位置、旋轉量、縮放值。而為false,保持局部座標的位置、旋轉、縮放。
意思是將foodHolder設為food的父物體。
十一,理解GameObject與Transform的區別與關聯
GameObject是一個類型,所有的遊戲物件都是這個類型的對象
gameobject是一個對象,指的是這個腳本所附著的遊戲物件
Transform是一個類,用來描述物體的位置,大小,旋轉等信息
transform是Transform類的對象,依附於每一個物體,也是當前遊戲對象的組件
transform與gameObject
含義:
transform:當前遊戲對象的transform組件
gameObject:當前遊戲對象的實例
區別:
在unity中每個遊戲對象都是一個gameobject. 每個gameobject都包含各種各樣的組件,但從這點可以看出transform是gameobject的一個組件,控制著gameobject的位置,縮放,和旋轉,而且每個gameobject都有而且必有一個transform組件
gameobject.find用來獲取場景中那個我們需要查找的對象(object). 而transform.find方法則是獲取當前對象的子對象下我們需要獲取的目標對象位置信息。
gameobject.transform與transform.gameobject
gameobject.transform,是獲取當前遊戲對象的transform組件.
所以在start函數中 gameobject.transform 和this.transform,指向的都是同一個對象。即:gameobject.transform == this.transform == transform
transform.gameobject:可以這麼理解為:獲取當前transform組件所在的gameobect
所以在start()函數中transform.gameobject == this.gameobject == gameobect
所以他們可以無限的引用下去
意思就是:
gameobject.transform == this.transform == gameobject.transform.gameobject.tranform ==
tranform.gameobect.transform
十二,鼠標點擊Cube控制按鈕旋轉移動
SwitchModeEnum枚舉類型定義了旋轉和移動
SwitchMoveAxis枚舉類型定義了座標x,y,z
[SerializeField] 強制unity去序列化一個私有域
這是一個內部的unity序列化功能,有時候我們需要Serialize一個private或者protect的屬性 ,會在Inspector面板顯示出來
OnMouseDown()方法必須在cube上添加一個碰撞器,否則代碼無效
十三.Random.Range()方法
整數類型:Random.Range(min,max); 返回一個隨機整數,在min(包含)和max(不包含)之間
小數類型:Random.Range(minf,maxf)時,返回一個隨機浮點數,在minf(包含)和maxf(包含)之間,此時包括臨界值。
eg:
public Sprite[] foodSprites; //定義一個數組
int index = Random.Range(0, foodSprites.Length); //隨機生成數組中的值。
十四.Invoke和InvokeRepeating方法
Invoke 和 InvokeRepeating 是 MonoBehaviour 中的兩個內置的延時方法
示例:
在場景中創建一個遊戲對象 , 命名為Invoker
創建一個Create Empty,用來存放腳本InvokerSp
在Start方法中,調用Invoke方法,Invoke方法有兩個參數,一個是我們要調用的方法名稱字符串,一個是以秒為單位的延遲時間。這行代碼的作用是經過2秒後調用SpawnObject方法。(只有無參數並且類型為void的方法,才可以使用Invoke調用)
經過2秒後,Invoker會被實例化在指定的位置。
InvokeRepeating
InvokeRepeating方法可以用來反覆的調用一個方法
InvokeRepeating中的三個參數分別是:要調用的方法名稱的字符串,調用方法之前的延遲時間,每次後續調用時間的延遲時間。
該代碼的意思是,在場景中實例化一個tar物體,兩秒後tar物體開始沿著Z軸運動,運動距離為1.0f,每一秒重複運動一次(因為每隔一秒都會調用一次SpawnObject方法)
CancelInvoke
用來停止InvokeRepeating方法的調用
用Invoke方法在10秒後調用stop方法中的CancelInvoke方法,CancelInvoke方法即停止調用SpawnObject方法。