转载unity
Unity基礎知識匯總
2018-05-12 17:02:37 levosam 閱讀數 3870更多 分類專欄: 編程 版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。 本文鏈接:https://blog.csdn.net/levosam/article/details/802929892.Unity相關知識
2.1 Unity介紹
Unity成為一款可以輕松創建游戲和三維互動的開發工具,是一個專業跨平臺游戲引擎
Unity操作快捷鍵
?
Ctrl | ? | N | New Scene 新建場景 |
Ctrl | ? | O | Open Scene 打開場景 |
Ctrl | ? | S | Save Scene 保存 |
Ctrl | Shift | S | Save Scene as 保存場景為 |
Ctrl | Shift | B | Build Settings... 編譯設置... |
Ctrl | ? | B | Build and run 編譯并運行 |
Edit 編輯 | |||
Ctrl | ? | Z | Undo 撤消 |
Ctrl | ? | Y | Redo 重做 |
Ctrl | ? | X | Cut 剪切 |
Ctrl | ? | C | Copy 拷貝 |
Ctrl | ? | V | Paste 粘貼 |
Ctrl | ? | D | Duplicate 復制 |
Shift | ? | Del | Delete 刪除 |
? | ? | F | Frame? selected 選擇的幀 |
Ctrl | ? | F | Find 查找 |
Ctrl | ? | A | Select All 全選 |
Ctrl | ? | P | Play 播放 |
Ctrl | Shift | P | Pause 暫停 |
Ctrl | Alt | P | Step 停止 |
?
2.2 腳本基礎開發
Unity面向組件開發,游戲物體想要實現什么樣的功能,只需要添加相對應的組件就可以了,此時會在屬性面板上顯示出來??梢韵裉砑咏M件一樣把腳本添加到游戲物體上。
腳本生命周期:
1.Awake
最早執行,在GameObejct對象的數據和狀態的初始化后執行,只會觸發一次。
tips:GameObject實例化到場景中后在激活的狀態下才會初始化,如果GameObject從來未激活,它的腳本上的Awake永遠不會被調用。
即時觸發,GameObject第一次active的時候調用。
2.Start
在腳本第一次調用Update之前調用,只會觸發一次。
3.OnEnable
在腳本狀態由disabled變為enabled狀態是觸發一次,Unity內部可能將腳本初始置為diabled,所以如果我們實例化一個激活的GameObject,并且在掛上一個enabled了的腳本后把它加入場景會調用一次OnEnable,并且早于Start。
4.OnDisable
在腳本由enabled狀態變為disabled狀態的時候會調用。
tips:OnEnable和OnDisable事件的觸發是即時的,并且這兩個事件是綜合考慮GameObject的active狀態和腳本的enabled狀態的。所以不要在OnEnable里面把腳本設置為disabled同時在OnDisable中把腳本設置為enabled,會導致死循環!!!
5.Update
在每一幀調用,用于實現各種行為邏輯
6.LateUpdate
在每一幀調用,但是是在Update之后觸發。常用的一種情況是相機跟隨移動角色:角色移動邏輯在Update里面實現,相機跟隨邏輯在LateUpdate里面實現。
7.OnDestroy
在組件被銷毀時調用,只有GameObject被激活過才會觸發。
腳本常用類:
1.Component類
2.GameObject類
3.Transform類
4. Vector3類
1.?Quaternion
Identity:該四元素無旋轉。
LookRotation:創建一個旋轉,沿著forward(Z軸)并且頭部沿著Y軸的約束注釋
2.?Time
3.?Mathf
預設體
組件的集合體 , 預制物體可以實例化成游戲對象.
創建預設體的作用: 可以重復的創建具有相同結構的游戲對象。
在腳本中,使用instantiate函數來進行預設體的實例化
Object tmpObj = Instantiate(prefabs, pos , Quaternion.identity);?
?
2.3 物理引擎
1.鍵盤輸入常用方法
GetKey:按鍵按下期間返回true
GetKeyDown:按鍵按下的第一幀返回true
GetKeyUp:按鍵松開的第一幀返回True
Input類簡介
虛擬按鍵
具體代碼和實現方式如下:
Float hor = Input.GetAxis(“Horizontal”);
鼠標事件
常用的鼠標屬性和方法
?
碰撞器組件:
當我們在場景當中創建出來一個游戲物體的方式后,引擎會自動為這個游戲物體添加碰撞器組件,其主要功能是進行碰撞檢測。
發生碰撞的條件:1、相對運動,2、兩個碰撞器,2、一個剛體
?
剛體組件
剛體組件能受到你的作用,比如:重力,反作用力,阻力,外加力,爆炸力等等
以下是剛體組件的一些屬性和常用方法
觸發器:
發生觸發的條件:1、兩個碰撞器 2、一個觸發器 3、一個剛體
?
射線
Unity提供了涉嫌集資:通過虛擬射線檢測所碰撞到的物體
Ray ray = new Ray();
Bool Raycast(Ray ray,out RaycastHit hitInfo);
Rayray=Camera.main.ScreenPointToRay(Input.mousePostion);
從主攝像機到鼠標點擊位置創建一條射線。
?
2.4 Unity2D和精靈
精靈:
圖片精靈的意思(Flash引擎里也有圖片精靈對象),將導入的圖片類型設置為Sprite即可拖到場景面板里,帶有隨屏幕大小自動縮放功能,還可以加Collider進行射線檢測,簡單實用。圖片精靈是用來繪制圖集的控件,精靈可以在一張大圖中去截取一部分(大圖就是整體圖像集合(Atlas),而截取的小圖就是一個精靈),然后給精靈命名,使用時通過精靈的名稱就能直接繪制,并且精靈還可以用來制作動畫。圖層排序:2D游戲當中的圖片之鍵沒有深度關系,都處于同一個平面上,但在實際游戲當中需要為他們排序,按視覺上的空間先后順序顯示。
2D物理組件與3D物理引擎在功能上基本相似,當我們給精靈添加了個剛體之后,他就會受到2D物理引擎的控制。
2D碰撞和觸發回調方法:
?
?
2D開發常用類:
創建序列幀動畫,按Ctrl+F6打開Animation的編輯窗口,點擊后可以添加屬性,如果要更改動畫中某一幀的位置、旋轉和縮放,只需要點擊+號即可,在Animation編輯窗口,在關鍵幀點擊天津愛時間,此時可以選擇腳本中的方法,但是該方法必須是public ,可訪問狀態
?
?
2.6 UGUI
UGUI的特點:靈活,快速和可視化,對于開發者而言,效率高,易于使用和擴展以及對Unity的兼容性高。
UGUI與GUI插件NGUI相比:
1. 由NGUI創始人參與開發
2. 與Unity結合更加密切
3. 自適應系統更加完善
4. 更方便的深度處理
5. 省去Altas,直接使用Sprite Pa
UGUI畫布:是所有UI控件的根類,所有的UI控件補習都在畫布上面。EventSystem是事件系統,負責監聽用戶的輸入,創建UI控件是,當層級試圖當中沒有CANVAS和EventSystem,系統會幫我們自動創建。
畫布的三種渲染模式模式:
1、Screen Space-Overlay:不需要UI攝像機,畫布會一直出現在攝像機最前面
2、Screen Space-Camera:需要一個UICamera,支持U前方顯示3D模型和粒子系統
3、World Space:UI控件成為3D場景中的一部分
LayoutGroup組件:對子控件進行布局,上面只能有一種布局組件,布局組件有以下三種:
1.Horizontal Layout Group (水平布局)
2.Ver tical Layout Group(垂直布局)
3.Grid Layout Group(網格布局)
1. UGUI畫布也稱為Canvas,UGUI是所有控件的父類
2. 所有UGUI控件都必須繪制在畫布上面
3. 當創建UGUI控件工程當中沒有Canvas的時候會自動創建
Canvas與EventSystem
Text控件是用來顯示文本的文本控件
Text的屬性可以在Inspector當中通過Text組件進行設置,也可以在代碼當中進行動態設置。給Canvas掛載腳本UGUISetting
Image控件主要是用來顯示圖片,顯示圖片的格式是Sprite
當我們給Image選擇一張貼圖之后會出現ImageType選項,如下圖所示。ImageType總共有四種選項:simple顯示單個會拉伸;Tilled平鋪顯示,圖片按照原始顯示;Sliced按照九宮格顯示,拉伸區域只會在九宮格中間;Filled填充顯示,可以根據不同的填充方式模擬技能冷卻的
按鈕添加監聽事件:
Button btn;
void Star t () {
//獲取到按鈕
btn = GameObject.Find(“Button”).GetComponent<Button> ();
//給按鈕添加監聽事件
btn.onClick .AddListener (BtnClick);
}
void BtnClick(){//按鈕響應事件
Debug.Log (“btn.onClick .AddListener ()”);
}?????
Slider是滑動條,Slider的屬性如圖所示:
Slider slider ;
void Star t () {
//獲取到Slider組件
slider = GameObject.Find(“Slider ”).GetComponent<Slider> ();
//添加監聽事件
slider.onValueChanged.AddListener(SliderValueChange);
}
//? 事件響應
public voidSliderValueChange (float value){
Debug.Log (“value = “+value);
}
InputField創建出來如下圖所示,InputField層級視圖當中包含Placeholder與Text,Placeholder用于顯示占位符,即輸入框沒有輸入文本時顯示的文本,例如下圖的“Enter text”,Text用于顯示輸入的內容。
RectTransform的作用用來計算UI的位置和大小,RectTransform繼承于Transform,具有Transform的所有特診,通過RectTransform能夠實現基本的布局和層級控制。
如圖所示,箭頭所指即為錨點,錨點表示的是相對于父級矩形的子矩形區域。如圖所示錨點為四邊形,錨點有多種擺放方式,可以為矩形,點狀或是為線狀。錨點移動范圍僅限于父級視圖當中。
按下T鍵選中某一個UI控件即可看到UI控件的中心點,中心點也叫中心軸,當鼠標拖動UI控件進行旋轉的時候會圍繞中心點旋轉。中心點為矩形的一部分。0對應左下角,1對應右上角
UGUI回調方法
輸入模塊StandaloneModule和TouchInputModule兩個組件會檢測到用戶的一些輸入事件,并且以事件的方式通知目標對象。實現這些回調方法需要實現相應的接口。常用的回調事件如下所示
CanvasGroup的作用:當一個控件蓋到另外一個控件上的時候,下面的控件默認是檢測不的,為了可以透過當前控件檢測到下面的控件,可以給該組件添CanvasGroup組件,其屬性blocksRaycasts設置為false時表示可以穿透該控件檢測到下面的控件,如果為true表示不能穿透,下方的控件檢測不到.
在Unity中,所有與應用程序相關的方法都寫在Application 類中。
主要功能:獲取或設置當前應用程序的一些屬性
? 加載游戲關卡場景
? 獲取資源文件路徑
? 退出當前游戲程序
? 獲取當前游戲平臺
? 獲取數據文件夾路徑
同步加載場景的方式分為兩種:
讀取新關卡后立即切換,其參數為所讀取新關卡的名稱或索引
SceneManager.LoadScene("Scene2");?????????
加載一個新的場景,當前場景不會被銷毀。
SceneManager.LoadScene("Scene2",LoadSceneMode.Additive);
異步加載新游戲場景,當新場景加載完成后進入新場景并且銷毀之前的場景。
SceneManager.LoadSceneAsync("Scene2");
同樣異步加載新場景,新場景加載完畢后,保留之前場景并且進入新場景。
SceneManager.LoadSceneAsync("Scene2",LoadSceneMode.Additive);
?
2.7 Unity 動畫系統基礎
Mecanim 功能強大的動畫系統
方便的實現人型動畫的設置和重用方便的實現動畫剪輯的設置
可視化的動畫控制界面
對動畫播放的精確控制
動畫類型分為四種
None:無任何動畫
Legacy:舊版Animation動畫
Generic:一般動畫(非人形動畫)
Humanoid:人形動畫
設置Avatat,Avatat是Mecanim系統中極為重要的模塊,因此為模型資源正確的設置Avatar也至關重要,不管Avatar自動創建過程是否成功,用戶都需要進入
根動作設置包括旋轉、Y 軸水平位置和 XZ 平面位置Bake Into Pose:烘焙進姿勢
loop match:當需要讓一個動作重復時,后面的圓點顏色就代表重復質量。綠色表示該動畫的第一幀和最
后一幀角色的姿勢相似,黃色次之,紅色質量最差。Based Upon:定根動作的參考點
Offset:偏移量用來設置指定根動作,在運動時的偏移量
動畫間的過渡需要使用狀態機和狀態參數實現,目前支持的參數類型有4種。
Animator常用方法:
改變 Float 類型狀態參數的值
animator.SetFloat(speedFloat, 2.0f );
改變 Bool 類型狀態參數的值
animator.SetFloat(deadBool, true);
BlendTree: 融合樹的功能是將兩個或多個相似的動作進行融合,可以使用多個或者一個參數來控制融合狀態。
在 Unity 中可以使用動畫層來管理不同類型的動畫分層處理。動畫層遮罩能夠在本層動畫中,身體的特定部分選擇性的激活或禁用在 Project面板下創建一個 Avatar Mask。身體遮罩包括頭部、左手臂、右手臂、左手、右手、左腿、右腿和根部,還可以選擇給手和腿添加 IK,這將決定 IK 曲線是否會包含在動畫融合中,點擊身體部分可以激活或禁用對應部位的動畫。
大多數動畫是由旋轉關節角度的骨架來預先確定的值。子關節的位置變化根據父節點的旋轉,因此關節鏈的最終位置會根據角度和它所包含的各個關節的相對位置來確定。這種方法構成的骨架被稱為正運動學。
IK動畫全名是Inverse Kinematics 意思是反向動力學,就是子骨骼節點帶動父骨骼節點運動。比如跳街舞的少年用手撐著身體在地上轉圈,手就是子骨骼,胳膊身體就是它的父骨骼,這時運動手就需要帶動胳膊身體來移動。我們需要從一個正確配置的Avatar的人形Mecanim角色開始,接下來創建一個動畫控制器,包含至少一個動畫人物。然后在動畫窗口的圖層面板中,單擊圖層的齒輪設置圖標,并在彈出的菜單中選中IK復選框。
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,1);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,1);
if (ikActive) {
animator.SetIKPosition(AvatarIKGoal.RightHand,rightHandObj.position);animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
} else{
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,0);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,0);
}
當你需要在角色動畫播放到某一幀的時候需要做其他處理時,這時可以使用動畫事件
2.8 Unity 導航系統
導航在游戲當中的概念就是從一點走到另外一點的過程,在該過程中需要考慮:阻擋,路徑選擇,可走地形,地形特點以及擬人化等多方面因素。在游戲當中導航分為兩種:
(1)ai角色:基于計算機本身控制的純導航
(2)主角:基于UI交互下的導航
導航實現方式
(1) A*算法
導航當中常用的算法是A*算法,它是一種從起點到終點探測代價最小路徑的廣度優先搜索方式,廣泛應用于2D格子型地圖。
? (2)NavigationMesh
在Unity當中采用的是基于Navigation Mesh的尋路算法原理, 是A*算法的變種,將A*算法當中的格子變成三角形或多邊形, 可以方便的從二維擴展到三維空間,是3D游戲當中的主流尋路算法。
NavMesh(導航網格)是3D游戲世界中用于實現動態物體自動尋路的一種技術,將游戲中復雜的結構組織關系簡化為帶有一定信息的網格,在這些網格的基礎上通過一系列的計算來實現自動尋路。
NavMeshAgent常見的屬性和方法:
分離路面導航:
在兩個不連通的尋路網格間,如果角色想在這兩個網格間行走就需要添
加跳躍的鏈接Off MeshLink
分層烘焙路面:
實現分層路面導航主要分為以下步驟:
(1)自定義Area層
(2)設置場景中不同區域烘焙為不同的層
(3)設置角色可以在導航網格中哪些層移動
設置不同區域在導航網格中為不同的層主要是控制角色有選擇的行走某些區域。設置好烘焙出來不同區域在場景當中呈現不同顏色,接下來通過角色自身掛載的NavMeshAgent組件里的AreaMask屬性設置代理可以在導航網格中的哪些區域移動。默認為Everything
動態障礙:
Nav Mesh Obstacle有兩種模式,一種是普通的模式,通過設置半徑與高度來確定一個范圍,阻擋代理的移動。另一種是Car ve模式,會根據模型大小界定該區域無法參與導航網格計算
?
2.9 Unity 特效渲染
粒子特效:
Unity中一個典型的粒子系統是一個對象,它包含了一個粒子發射器,一個粒子動畫和一個粒子渲染器。粒子發射器產生粒子,粒子動畫器則隨時間移動粒子,粒子渲染器則將它們渲染到屏幕中
粒子系統相關參數:
拖尾渲染:
TrailRenderer
拖尾渲染組件屬于特效當中的一種,給一個物體添加拖尾渲染組件的方式
線性渲染:
LineRenderer常用方法
?
2.10 Unity 數據庫與存儲
PlayerPrefs存儲數據
適用范圍
1. 適用設備:Mac OSX、Linux、Windows、
Windows Store Apps、Windows Phone 8、Web players
2. 存儲機制:Key-Value
3. 可存儲變量類型:int、float、string
PlayerPrefs數據存儲路徑
1. Mac OSX:~/Library/Preferences
2.Windows:HKCU\Software\[company name]\[product name]
3.Linux:~/.config/unity3d/[CompanyName]/[ProductName]
4. Windows StoreApps:%userprofile%\AppData\Local\Packages\
[ProductPackageId]>\LocalState\playerprefs.dat
5. WebPlayer
6. Mac OS X:~/Library/Preferences/Unity/WebPlayerPrefs
7. Windows:%APPDATA%\Unity\WebPlayerPrefs
PlayerPrefs常用方法;
void Example() {
PlayerPrefs.SetFloat("PlayerScore", 10.0F);
print(PlayerPrefs.GetFloat("PlayerScore"));
?
XML數據生成和解析
1. XML 指可擴展標記語言(EXtensible Markup Language)
2. XML 是一種標記語言,很類似 HTML
3. XML 的設計宗旨是傳輸數據,而非顯示數據
XML結構
每個標簽內部可以有多個屬性。標簽可以層層嵌套,形成一個樹形
結構。
例如:
<position name=“player”>
<x>18</x>
<y>5</y>
<z>30</z>
</position>
以上Alarm(元素節點),lock(屬性節點),Time(元素節點), StringValue(文本節點)都是節點(Node),
但是只有<Alarm>……</Alarm>
和<Time>StringValue</Time>是元素(Element)
XML常用的類
1. XmlDocument——XML文件類2. XmlNode——XML節點類
3. XmlAttribute——XML屬性類4. XmlElement——XML元素類
XmlNode
?
?
?
?
?
?
?
?
XmlDocument
XmlElement
Xml數據生成步驟
在Unity引擎中如何生成本地XML數據?
第一步:引用C#的命名空間 System.Xml
第二步:生成XML文檔(XmlDocument 類)
第三步:生成根元素(XmlElement類)添加給文檔對象第四步:循環生成子元素添加給父元素
第五步:將生成的XML文檔保存
Xml數據生成示例
//創建xml文件對象
XmlDocument doc = newXmlDocument();
//創建xml頭
XmlNode xmldct =doc.CreateXmlDeclaration ("1.0", "utf-8", null);
//添加xml頭
doc.AppendChild (xmldct);
//創建xml根節點(元素屬于節點)users
XmlNode root =doc.CreateElement("users");
//添加xml根節點
doc.AppendChild (root);
//創建子節點
XmlNode xn_element =doc.CreateNode (XmlNodeType.Element, "name", null); //設置子節點的值
xn element.InnerText ="Albert";
//創建屬性
XmlAttribute xa =doc.CreateAttribute ("no");
//設置屬性值
xa.Value ="1234";
//獲取元素的docment
XmlDocument xd = xnelement.OwnerDocument;
_
//設置元素屬性
xnelement.Attributes.SetNamedItem (xa);
_
//添加子節點到root節點
root.AppendChild (xn_element);
//保存xml
doc.Save(Application.dataPath+ "/test.xml");
Xml序列化
序列化是將對象狀態轉換為可保持或傳輸的格式的過程。
我們可以把對象序列化為不同的格式,比如說,Json序列化、XML序列化、二進制序列化等,以上這些不同的格式也都是為了適應具體的業務需求。
public class BaseInfo {
//BaseInfo對象中保存Person對象
? List<Person> perList = newList<Person>(); //創建元素節點
[XmlElement(ElementName="Perosn")]publicList<Person> PerList
{
get
{
return perList;
}
set
{
perList = value;
}
}
}
//用于將信息寫入字符串
StringWriter sw = newStringWriter();
//指定 Xml序列化名字空間
XmlSerializerNamespacesns = new XmlSerializerNamespaces();ns.Add("", "");
//聲明Xml序列化對象實例serializer,對BaseInfo類 進行序列化
XmlSerializer serializer= new XmlSerializer(typeof(BaseInfo));
//使用 StringWriter 和指定的名字空間 將BaseInfo 對象寫入Xml文件
serializer.Serialize(sw,baseInfo, ns);
sw.Close();
反序列化示例
//根據指定路徑讀取,實例化FileStream對象
FileStream fs = newFileStream(Application.dataPath +
"/Practise5/test.xml",FileMode.Open,FileAccess.Read);
//指定反序列化的類型
XmlSerializer serializer= new XmlSerializer(typeof(BaseInfo));BaseInfo baseInfo =(BaseInfo)serializer.Deserialize(fs);
fs.Close();
//遍歷baseinfo對象中的信息,輸出到控制臺
for (int i = 0; i <baseInfo.PerList.Count; i++)
{
Person per =baseInfo.PerList[i];
Debug.Log("名字: "+ per.Name +", 年齡:"+per.Age );
for (int j = 0; j <per.BooksList.Count; j++)
{
Books books =per.BooksList[ j];
for (int k = 0; k <books.BookList.Count; k++)
{
Book book =books.BookList[k];
Debug.Log("書名: "+book.Title+", 價格:"+book.Price);
}
}
}
?
JSON數據生成和解析
System.Json
?
1. JSON 是純文本
2. JSON 是一種輕量級的數據交換格式3. JSON 具有層級結構(值中存在值)
1. 數據在鍵值對
2. 數據由逗號分隔3. 花括號保存對象4. 方括號保存數組
LitJson.JsonMapper
1. 把對象轉化成 JSON格式字符串: JsonMapper.ToJson
2. 把JSON格式字符串轉化成對象: JsonMapper.ToObject
什么是SQLite
1. SQLite是一款輕型的數據庫
2. SQLite的設計目標是嵌入式的
3. SQLite占用資源非常的低
4. SQLite能夠支持Windows/Linux/Unix等等主流的操作系統
作用:INSERT INTO 語句用于向表格中插入新的行。
語法1:INSERT INTO 表名稱 VALUES (值1, 值2,....)
語法2:INSERT INTO table name (列1, 列2,...) VALUES (值1, 值2,....)
作用:DELETE 語句用于刪除表中的行。
語法:DELETE FROMPerson WHERE LastName = 'Wilson'
作用:Update 語句用于修改表中的數據。
語法:UPDATE 表名稱 SET 列名稱 = 新值 WHERE 列名稱 = 某值
作用:SELECT 語句用于從表中選取數據。
語法:SELECT 列名稱 FROM 表名稱
Unity當中使用SQLite:
導入mono.data.sqlite.dll到Assets文件夾代碼添加庫:using Mono.Data.Sqlite;
使用SQLiteConnection對象,進行數據庫連接,此操作可以創建空的數據庫
具體代碼如下:
//數據庫連接路徑
string path = "data source="+ Application.streamingAssetsPath +
"/UserDatabase.sqlite";
void OpenDataBase(stringconnectionString)
{
try
{
conn = newSqliteConnection(connectionString);
conn.Open();
}
catch (System.Exceptionexc)
{
Debug.Log(exc);
}
}
使用SqliteCommand數據指令,對象進行數據庫操作
//判斷數據庫中是否有UserTable這個表SqliteCommand cmd =conn.CreateCommand();
cmd.CommandText ="select count(*) from sqlite master where
_
type = 'table' and name ='UserTable'";
SqliteDataReader reader =cmd.ExecuteReader();
使用SqliteDataReader 數據讀取對象,進行數據庫內容讀取
//判斷數據庫中是否存在這張表
bool isExit = false;
while (reader.Read())
{
for (int i = 0; i <reader.FieldCount; i++)
{
if(reader.GetValue(i).ToString() == "1")
{
isExit = true;
}
}
}
數據庫操作完成之后要將數據庫關閉
//如果表不存在則建表
reader.Dispose();
reader.Close();
reader = null;
if (!isExit)
{
Debug.Log("表不存在,建表");
cmd.CommandText ="Create Table UserTable(uname text,pwd
text)";
cmd.ExecuteNonQuery();
}
cmd.Dispose();cmd =null;CloseDataBase();
執行SQL語句的三種方式
1、int ExecuteNonQuery()
返回受影響的行數(常用于執行增刪改操作)
2、object ExecuteScalar()
返回查詢到的第一個值(常用于只查詢一個結果時)3、SqliteDataReader ExecuteReader()
返回所有查詢的結果(SqliteDataReader對象)
?
數據庫封裝:
為何要封裝?
1. 方便項目管理
2. 方便開發人員的快捷的使用
3. 防止高度保密數據外泄
1. 連接數據庫
2. 通過Sql語句查詢數據
3. 通過表名查詢全表數據
…
4. 關閉數據庫連接,釋放資源
平臺選擇不同的存儲路徑:
在直接使用Application.dataPath來讀取文件進行操作,移動端是沒有訪問權
限的。
Application.streamingAssetsPath
直接使用Application.streamingAssetsPath來讀取文件進行操作,此方法在pc/Mac電腦中可實現對文件實施“增刪查改”等操作,但在移動端只支持讀取操作。
使用Application.persistentDataPath來操作文件,該文件存在手機沙盒中,因為不能直接存放文件。
1.通過服務器直接下載保存到該位置,也可以通過Md5碼比對下載更新新的資源
2.沒有服務器的,只有間接通過文件流的方式從本地讀取并寫入
Application.persistentDataPath文件下,然后再通過
Application.persistentDataPath來讀取操作。
注:
在Pc/Mac電腦以及android跟Ipad、ipone都可對文件進行任意操作,
另外在IOS上該目錄下的東西可以被iCloud自動備份。
發布到安卓端需要經過特殊處理
同樣需要上述的三個類庫和libsqlite.so文件,但不需要重新建表和重新
插入數據內容。當Android端安裝應用程序時,需要一個*.apk的安裝文件,此文件內保存著我們從Unity開發平臺導入的*.sqlite文件,所以我們可以通過www來下載該sqlite文件,從而通過IO流寫入到Android本地的persistentDataPath沙盒路徑。該文件保存著所有表格和數據,無需再次創建和插入,通常使用的都是這種方式,較為便捷。
Android端連接本地數據庫:
注意:
? 二進制文件需要放在Plugins->Android->assets中,然后根據下面的路徑就可以在Android中讀取。
string Path =jar:file://” + Application.dataPath + “!/assets/” +
“你的文件“;
?
2.11 WWW類與協程
什么是協程?
1. Unity的協程系統是基于C#的一個簡單而強大的接口
2. 簡單講,協程就是可以把一個方法拆分成多次執行的一種接口
IEnumerator ShowTime()
{
Debug.Log("FirstFrame");//第一幀執行
yield return 0;//等待下一幀
Debug.Log("SecondFrame");//第二幀執行
yield return 0;//等待下一幀
Debug.Log("ThirdFrame");//第三幀執行
}
開啟協程
//通過傳入方法開啟協程
StartCoroutine(ShowTime());
//通過傳入字符串類型的方法名稱開啟協程
StartCoroutine("ShowTime");
停止協程
StartCoroutine(“ShowTime");
//停止協程
StopCoroutine(“ShowTime”);
注意:StopCoroutine只能停止以字符串方式開啟的協程
當你“yield”一個方法時,你相當于說,“現在停止這個方法,然后在下一幀中從這里繼續開始!”。
2. 用0或者null來yield的意思是告訴協程
等待下一幀,直到繼續執行為止。
協程注意事項
1. 在程序中調用StopCoroutine()方法只能終止以字符串形式啟動(開始)的協程。
2. 多個協程可以同時運行,它們會根據各自的啟動順序來更新。
3. 協程可以嵌套任意多層。
4. 協程不是多線程(盡管它們看上去是這樣的),它們運行在同一線程中,跟普通的腳本一樣。
5. IEnumerator類型的方法不能帶ref或者out型的參數,但可以帶被傳遞的引用。
協程,線程的區別
1. 線程擁有自己獨立的棧和共享的堆,共享堆,不共享棧,線程亦由操作系統調度(標準線程是的)。
2. 協程和線程一樣共享堆,不共享棧,協程由程序員在協程的代碼里顯示調度。
3. 協程避免了無意義的調度,由此可以提高性能,但也因此,程序員必須自己承擔調度的責任,同時,協程也失去了標準線程使用多CPU的能力。
協程優點:
1. 跨平臺
2. 跨體系架構
3. 無需線程上下文切換的開銷
4. 無需原子操作鎖定及同步的開銷
5. 方便切換控制流,簡化編程模型
6. 高并發+高擴展性+低成本:一個CPU支持上萬的協程都不是問題。所以很適合用于高并發處理。
缺點:
1. 無法利用多核資源:協程的本質是個單線程,它不能同時將 單個CPU的多個核用上,協程需要和進程配合才能運行在多CPU上.當然我們日常所編寫的絕大部分應用都沒有這個必要,除非是cpu密集型應用。
2. 進行阻塞(Blocking)操作(如IO時)會阻塞掉整個程序:這一點和事件驅動一樣,可以使用異步IO操作來解決。
什么是AssetBundle。?
AssetBundle是從unity項目中打包出來的資源文件,可用于資源的更新等。AssetBundle支持3中格式的壓縮選擇,分別是LZMA,LZ4,無壓縮。默認是LZMA格式的壓縮,但是這樣雖然可以使資源文件大小大大縮小,利于下載,但是也有不利的一面,在使用時會先解壓再使用,所以會造成加載時間過長。?
不壓縮格式資源包會比較大,但是加載時不需要解壓,所以加載時會更快。
WWW類:
1. 可以簡單的訪問web頁面;
2. 這是一個小工具模塊檢索url的內容;
3. 你開始在后臺下載通過調用WWW(url),返回一個新的WWW對象;
4. 你可以檢查isDone屬性來查看是否已經下載完成,或者yield自動等待下載物體,直到它被下載完成(不會影響游戲的其余部分)。
WWW類常用屬性:
?
2.12 網絡基礎
?
網絡協議即網絡中傳遞、管理信息的一些規范,在計算機之間的相互通信需要共同遵守一定的規則,這些規則就稱為網絡協議。
TCP/IP不是一個協議,而是一個協議簇的統稱,里面包含TCP協議IP協議, UDP協議,及http、FTP等。之所以命名為TCP/IP協議,因為TCP,IP協議是兩個很重要的協議,所以以TCP/IP命名。
TCP/IP協議的四層參考模型
應用層:
應用程序間溝通的層,如簡單電子郵件傳輸(SMTP)、文件傳輸協議(FTP)、網絡遠程訪問協議
(Telnet),以及超文本傳輸協議(http) 等。
傳輸層:
在此層中,它提供了節點間的數據傳送服務,如傳輸控制協議(TCP)、用戶數據報協議(UDP)等,TCP和UDP給數據包加入傳輸數據并把它傳輸到下一層中,這一層負責傳送數據,并且確定數據已被送達并接收。
互連網絡層:
負責提供基本的數據封包傳送功能,讓每一塊數據包都能夠到達目的主機(但不檢查是否被正確接收),如網際協議(IP)。
網絡接口層:
對實際的網絡媒體的管理,定義如何使用實際網絡來傳送數據。
長連接:
是客戶端與服務器建立連接后,進行業務報文的收發,始終保持連接狀態,在沒有報文收發的情況下,可以使用心跳包來確認連接狀態的保持,很多移動端游戲類型都采用長連接,例如RPG,SLG, ACT等需要即時交互的游戲類型,使用TCP長連接協議。
短連接:
是客戶端與服務器需要進行報文交互時進行連接,交互完畢后斷開連接。例如在某種推圖游戲對戰回合中,進行不聯網的單機計算,當在本關卡結束時再聯機交互結算報文,所以例如卡牌,回合制還有例如頁游等使用http短連接協議。
TCP協議和UDP協議對比:
TCP(Transmission Control Protocol,傳輸控制協議)是面向連接的協議, 在收發數據前,必須和
對方建立可靠的連接。
客戶端主機和服務器經過三次握手進行鏈接簡單描述如下:
第一次,客戶端向服務器發送連接請求。
第二次 服務器做出收到請求和允許發送數據的應答。
第三次客戶端再次送一個確認應答,表示現在開始傳輸數據了。
UDP協議使用IP層提供的服務把從應用層得到的數據從一臺主機的某個應用程序傳給網絡上另一臺主機上的某一個應用程序UDP協議有如下的特點:
1、UDP傳送數據前并不與對方建立連接,即UDP是無連接的,在傳輸數據前,發送方和接收方相互交換信息使雙方同步。
2、UDP不對收到的數據進行排序,在UDP報文的頭中并沒有關于數據順序的信息(如TCP所采用的
序號),而且報文不一定按順序到達的,所以接收端無從排起。
3、UDP對接收到的數據報不發送確認信號,發送端不知道數據是否被正確接收,也不會重發數據。
4、UDP傳送數據較TCP快速,系統開銷也少。
總結:
從以上特點可知,UDP提供的是無連接的、不可靠的數據傳送方式,是一種盡力而為的數據交互服務,而TCP是長連接,較可靠的網絡協議。
Socket本質是對TCP/IP封裝的編程接口(API),使得程序員更方便地使用TCP/IP協議。Socket類提供了各種網絡連接,接收數據,發送數據等相關方法給程序開發人員使用。
Socket類常用方法
?
BeginConnect()?? 開始一個對遠程主機連接的異步請求
BeginReceive()?? 開始異步接收數據
BeginSend()????? 開始異步發送數據
Connect()??????? 建立與遠程主機的連接
Send()??????????? 將數據發送到連接
Receive()??????? 接收數據到緩沖區
EndConnect()???? 結束異步連接請求
EndReceive()???? 結束異步接收
EndSeed()??????? 結束異步發送
Close()????????? 關閉socket連接和釋放所有關聯
?
protocolbuffer也叫Googlebuffer,protobuf,它是谷歌的數據交換格式,獨立于語言,原生支持Java,c++ ,python 等語言,一種高效率和優秀兼容性的二進制數據傳輸格式,使用第三方工具可以良好支持C#語言,由于它獨立于語言和平臺,可以在unity客戶端和c++服務器,或python服務器之間進行良好交互,故而是目前unity移動端網絡游戲開發的主流數據交互協議。
?
基本語法
定義消息 message 關鍵字:message c2s login game request
{
required string account =1;required string password = 2;
}
1,2是分配標識號
基本語法
字段關鍵字:
Package:包定義,名空間。
required:表示該值是必須要設置的。
optional:可選字段,消息格式中該字段可以有0個或1個值(不超過1個)。
repeated:重復的值的順序會被保留,表示該值是一個集合。
注釋:
Proto文件可以使用//注釋不需要編譯的內容。
?
序列化proto數據參考代碼:
public static byte[]Serialize(IExtensible msg)
{
byte[] result;
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream,msg);result = stream.ToArray();
}
return result;
}
反序列化參考代碼:
public static TDeserialize<T>(byte[] message)
{
T result;
using (var stream = newMemoryStream(message))
{
result =Serializer.Deserialize<T>(stream);
}
return result;
}
?
2.13 性能優化
程序性能的分析
程序性能的分析主要是對Profiler的講解。Profiler工具是Unity3D提供的一套用于實時監控資源消耗的工具,通過使用該工具,我們可以直觀地查看程序運行時各個方面資源的占用情況,并勻速找到影響程序性能的線程和函數,再針對性的優化
我們可以使用快捷鍵Ctrl+7快捷鍵或依次點擊“Window->Profiler”命令來調出Profiler窗口。
下方是Profiler工具中各項參數的意義:
CPUUsage
???GC Alloc?- 記錄了游戲運行時代碼產生的堆內存分配。這會導致ManagedHeap增大,加速GC的到來。我們要盡可能避免不必要的堆內存分配,同時注意:1、檢測任何一次性內存分配大于2KB的選項;2、檢測每幀都具有20B以上內存分配的選項。
??WaitForTargetFPS?-VSync功能所致,即顯示的是當前幀的CPU等待時間。
??Overhead?-表示Profiler總體時間,即所有單項的記錄時間總和。用于記錄尚不明確的時間消耗,以幫助進一步完善Profiler的統計。(一般出現在移動設備,鋸齒狀為Vsync所致)
??Physics.Simulate?-當前幀物理模擬的CPU占用量。
??Camera.Render?-相機渲染準備工作的CPU占用量。
??RenderTexture.SetActive?-設置RenderTexture操作。比對當前幀與前一幀的ColorSurface和DepthSurface,如果一致則不生成新的RT,否則生成新的RT,并設置與之對應的Viewport和空間轉換矩陣。
??Monobehaviour.OnMouse_?-用于檢測鼠標的輸入消息接收和反饋,主要包括 SendMouseEvents和DoSendMouseEvents。
??HandleUtility.SetViewInfo?-僅用于Editor中,作用是將GUI在Editor中的顯示看起來與發布版本上的顯示一致。
???GUI.Repaint?- GUI的重繪(盡可能避免使用Unity內建GUI)。
??Event.Internal_MakeMasterEventCurrent?-負責GUI的消息傳送。
??CleanupUnused Cached Data?- 清空無用的緩存數據,主要包括RenderBuffer 的垃圾回收和TextRendering的垃圾回收。
??RenderTexture.GarbageCollectTemporary?-存在于RenderBuffer的垃圾回收中,清除臨時的FreeTexture。
??TextRendering.Cleanup?-TextMesh的垃圾回收操作。
??Application.IntegrateAssets in Background?- 遍歷預加載的線程隊列并完成加載,同時完成紋理的加載、Substance的Update等。
??Application.LoadLevelAsyncIntegrate?- 加載場景的CPU占用。
??UnloadScene?-卸載場景中的GameObjects、Component和GameManager,一般用在切換場景時。
??CollectGameObjects?-將場景中的GameObject和Component聚集到一個Array 中。
??Destroy?-刪除GameObject或Component的CPU占用。
??AssetBundle.LoadAsyncIntegrate?- 多線程加載AwakeQueue中的內容,即多線程執行資源的AwakeFormLoad函數。
??Loading.AwakeFormLoad?-在資源被加載后調用,對每種資源進行與其對應的處理。
??StackTraceUtility.PostprocessStacktrace()和StackTraceUtility.ExtractStackTrace()?- 一般是由Debug.Log或類似API造成,游戲發布后需將Debug API進行屏蔽。
??GC.Collect?-系統啟動的垃圾回收操作。當代碼分配內存過量或一定時間間隔后觸發,與現有的Garbage size及剩余內存使用粒度相關。
???GarbageCollectAssetsProfile?-引擎在執行UnloadUnusedAssets操作。
GPUUsage?
??Device.Present?-device.PresentFrame的耗時顯示,該選項出現在發布版本中。關于該參數有如下幾個常見問題:1、GPU的presentdevice確實非常耗時,一般出現在使用了非常復雜的Shader等;2、GPU運行是非??斓?#xff0c;而由于Vsync的原因,使得它需要等待較長時間;3、同樣是Vsync的原因,若其他線程非常耗時,會導致該項等待時間很長,比如過量的AssetBundle加載時容易出現該問題。
??Graphics.PresentAndSync?-GPU上的顯示和垂直同步耗時,該選項出現在發布版本中。
??Mesh.DrawVBO?-GPU中關于Mesh的Vertex Buffer Object的渲染耗時。
??Shader.Parse?-?資源加入后引擎對Shader的解析過程。
??Shader.CreateGPUProgram?-根據當前設備支持的圖形庫信息來建立GPU工程。
Memory?
???GameObjects in Scene?- 當前幀場景中的GameObject數量。
??otalObjects in Scene?- 當前幀場景中的Object數量(除了GameObject外,還有Component等)。
??TotalObject Count?- Object數量 + Asset數量。
??SceneMemory?- 記錄當前幀場景中各方面的內存占用情況,包括GameObject、所有資源、各種組件及GameManager等。
?
幀調試器(FrameDebugger)的應用
一個針對渲染的調試器。與其他的調試工具的復雜性相比,Unity原生的幀調試器非常的簡單便捷。我們可以使用它來看到游戲圖像的某一幀是如何一步步渲染出來的
需要使用幀調試器,我們首先需要在Window->Frame Debugger中打開幀調試器窗口。
GPU優化分為四個部分:
1、DrawCall:Unity每次再準備數據并通知GPU渲染的過程被稱為一次DrawCall。
優化方案:批處理(接下來我們會做詳細的講解)
2、物理組件的使用
優化方案:
? <1>設置一個合適的FixedTimestep
? <2>不要使用MeshCollider(從優化的角度上來說,我們盡量減少使用物理組建)
3、GC(Garbage Collection垃圾回收)
優化方案:減少對CPU的調用(稍后做講解)
4、代碼質量
Unity中有兩種批處理方式:
動態批處理
好處:一切處理都是自動的,不需要我們自己做任何操作,而且物體是可以移動的。
壞處:限制很多,可能一不小心我們就會破壞了這種機制,導致Unity無法批處理一些使用了相同材質的物體。
靜態批處理
好處:自由度很高,限制很少。
壞處:可能會占用更多的內存,而且經過靜態批處理后的所有物體都不可以再移動了。
GPU優化
1、減少繪制的數目
解決方案:模型的LOD技術、遮擋剔除技術
2、優化顯存的帶寬
模型的LOD技術
LOD(Level of Detail)技術。這種技術的原理是,當另一個物體離攝像機很遠時,模型上的很多細節是無法被察覺到的。因此,LOD允許當前對象逐漸原理攝像機時,減少模型上的面片數量,從而提高性能。
在Unity中,我們可以使用LODGrounp組件來為一個物體構建一個LOD。我們需要為同一個對象準備多個包含不同細節程序的模型,然后把它們賦給LODGroup組件中的不同等級,Unity就會自動判斷當前位置上需要使用哪個等級的模型。
同樣它的缺點同樣是需要占用更多的內存,而且如果沒有調整好距離的話,可能會造成模擬的突變。
遮擋剔除技術
實際開發過程中,每一個場景往往伴隨著大量的對象,其中相當一部分對象是不在攝像機拍攝范圍內的,進行著一部分對象的繪制是完全沒有必要的。強大的Unity3D引擎提供了非常實用的遮擋剔除技術,使不被拍攝到的點或面不送入渲染管線繪制。
1、Resource資源不用的要刪除,紋理、網格、音頻等等;
2、在CPU壓力不是特別大的時候,重置GameObject、組件等占用的內存;
3、在打包AssetBundle的時候,可以考慮bundle的壓縮。總結
- 上一篇: android widget包说明与应用
- 下一篇: 主流的6个Go语言Web框架