++Unity網絡基礎
++++Unity基本網絡知識
++++NetworkManager類創建服務器和客戶端
++++RPC(遠程過程調用)技術
++++Unity網絡管理器
++Unity網絡:
++++NetworkServer 創建服務器(註冊事件)
++++NetworkClient 連接服務器,註冊事件,註冊預設體
++++NetworkBehavior : IsLocalPlayer,區分不同網絡對象的所有者
++++Rpc技術:
--Command :從客戶端發起,在服務器執行。
--RpcClient : 從服務器發起,在客戶端執行。
++++同步變量:
--[SyncVar] : float int v3[struct] string
++1、網絡是什麼?
++++網絡:
++2、網絡的作用?
++++1、信息交互
++++2、資源共享
++++3、分佈式處理
++3、網絡通訊協議
++++1、TCP/IP 4層模型
--應用層
--傳輸層
--互聯網層
--網絡接口層
++++2、TCP/IP 5層模型
--應用層
--傳輸層
--互聯網層
--數據鏈路層
--物理層
++++3、OSI 7層模型
--應用層
--表示層
--會話層
--傳輸層
--網絡層
--數據鏈路層
--物理層
++4、IP地址
++++網際協議地址
++++IPV4--32位
++++IPV6--128位
++5、NAT地址轉換
++++PC1: 192.168.200.2
++++內網
++++SecPath F1000-E
++++外網
--PC2: 218.197.70.2
--PC3: 218.197.70.3
--PC4: ...
++6、端口Port
++++每個端口對應一個服務。
++7、軟件系統體系結構
++++C/S
++++Client/Server
++++客戶端/服務器
++8、網絡遊戲
++9、Unity網絡框架解析
++++多人遊戲和網絡
++++Unity新版網絡API
++++HLAPI架構圖
++10、多人遊戲和網絡
++++思考一下,製作類似Data或者LOL這樣的多人競技遊戲,需要實現那些功能?
++11、Unity新版網絡API
++++Unity網絡The High Level API(HLAPI)是爲在Unity中創建多人在線遊戲所建立的一套系統,HLAPI封裝了網絡遊戲中大部分功能,提升開發效率,簡化簡單網絡遊戲的難度。
++++主要實現功能如下:
--網絡狀態管理[創建服務器、主機、客戶端]
--狀態同步
--過程過程調用
--互聯網服務[中繼服務器、遊戲大廳、匹配比賽]
++12、HLAPI架構圖
++++Low Level API
--Transport / Configuration
++++Messaging & Serialization
--Connection / Reader / Writer
++++Connection Management
--NetworkClient / NetworkServer
++++Object state & Actions
--NetworkIdentity / NetworkBehaviour
++++Object Life Cycle
--NetworkScene / ClientScene
++++Game Control
--NetworkManager
++++Player Control
--NetworkLobbyManager
++++Engine Integration
--NetworkTransform
--NetworkAnimator
--NetworkProimityChecker
++1.1、NetworkServer
++++NetworkServer類負責創建服務器監聽接口,管理客戶端的連接,它也負責處理遊戲相關的一些特性: 玩家管理、監聽、卵生對象和消息處理。
++1.2、Server方法(靜態方法)
++++靜態方法: 功能
++++Listen :根據指定端口開啓服務器。
++++RegisterHandler :註冊回調函數。
++++Spawn : 在所有已準備的客戶端上實例化物體。
++++SpawnWithClientAuthority :跟Spawn()方法一樣,並且設置客戶端權限。
++++Destroy : 在所有客戶端上刪除物體。
++++AddPlayerForConnection :將卵生的物體與客戶端建立關係。
++1.3、Server屬性
++++靜態變量 : 功能
++++active : 檢查服務器是否開啓。
++++connections : 當前所有連接的客戶端列表。
++++handlers : 以字典形式返回服務器註冊的所有回調方法。
++++listenPort : 服務器監聽端口。
++++localClientActive : 在服務器上的客戶端,即爲主機是返回true。
++++maxDelay : 連接之間發送數據的最大延遲。
++1.4、創建服務器
Button StartServerButton;
void OnEnable(){
Application.runInBackground = true;
StartServerButton = GetComponent<Button>();
StartServerButton.onClick.RemoveAllListeners();
StartServerButton.onClick.AddListener(StartServer);
}
void StartServer(){
//服務器是否開啓
if(!NetworkServer.active){
NetworkServer.Listen(7777); //根據指定端口,開啓服務器
Debug.Log(「服務器開啓」);
}
}
++2.1、NetworkClient
++++該類對象負責連接服務器,並與服務器通信(即收到服務器消息和發送消息給服務器)。
++2.2、Client方法
++++Connect : 根據指定IP和Port連接服務器。
++++RegisterHandler : 註冊回調函數。
++2.3、創建客戶端
++++NetworkClient用於連接服務器
Button clientButton;
NetworkClient client;
void OnEnable(){
clientButton = GetComponent<Button>();
clientButton.onClick.AddListener(Connect);
}
void Connect(){
client = new NetworkClient(); //創建一個客戶端對象
client.RegisterHandler(MsgType.Connect, OnClientConnect); //註冊回調函數
client.Connect(「127.0.0.1」,7777); //連接服務器
}
//成功連接服務器之後
void OnClientConnect(NetworkMessage netMsg){
clientButton.GetComponentInChildren<Text>().text = 「連接成功!」;
}
++2.4、Client屬性
++++Client屬性
++3.1、卵生對象
++++網絡中,所有網絡對象都應該由服務器產生。
++++客戶端玩家對象生成步驟:
--1、客戶端發請求
--2、服務器接收請求後實例化客戶端對象
++3.2、卵生對象步驟
++++1、新建預設體,添加NetWorkIdentity組件,標示爲網絡物體。
++++2、客戶端調用ClientScene.Ready()方法告知服務器自己已經準備好。
++++3、客戶端調用ClientScene.RegisterPrefab()註冊網絡預設體。
++++4、客戶端調用ClientScene.AddPlayer()方法告訴服務器卵生對象。
++++5、服務器RegisterHandler->MsgType.AddPlayer的回調AddPlayer。
++++6、服務器在AddPlayer方法實例化物體,調用Spawn方法卵生。
++3.3、客戶端代碼
//成功連接服務器之後
void OnClientConnect(NetworkMessage msg){
clientButton.GetComponentInChildren<Text>().text = 「連接成功!」;
ClientScene.Ready(msg.conn); //告訴服務器已就位
ClientScene.RegisterPrefab(playerPrefab); //提前註冊網絡預設體
ClientScene.AddPlayer(0); //告訴服務器實例化預設體,參數暫不重要
}
++3.4、服務器代碼
void OnServerAddPlayer(NetworkMessage netMsg){
Debug.Log(「收到客戶端發送添加玩家的請求」);
GameObject player = (GameObject)Instantiate(playerPrefab);
//將物體與客戶端建立關係,即表示該物體由該客戶端生成
NetworkServer.AddPlayerForConnection(netMsg.conn, player, 0);
//卵生[同步到其他客戶端]
NetworkServer.Spawn(player);
}
++4.1、NetworkIdentity
++++NetworkIdentity組件是網絡的核心,用NetworkServer.Spawn卵生的物體都必須具備該組件。該組件在卵生的時候會自動分配assetId和權限。
++++屬性: 功能
++++isClient : 物體在客戶端上時返回True。
++++isServer : 物體在服務器上時返回True。
++++hasAuthority : 有權限時返回True。
++++localPlayerAuthority : 只有當本地的客戶端玩家時返回True。
++4.2、NetworkBehaiour
++++NetworkBehavior組件是一個特殊組件,它依賴NetworkIdentity組件,用來實現RPC技術和狀態同步屬性。我們想實現網絡物體的控制腳本,必須繼承自NetworkBehaviour。
public class PlayerScript:NetworkBehavior{
[SyncVar]
public int HP;
[ClientCallback] //表示只在客戶端調用
void Update(){
if(isLocalPlayer){
//表示本地客戶端玩家
h = Input.GetAxis(「Horizontal」);
v = Input.GetAxis(「Vertical」);
transform.Translate(new Vector(h,0,v) *Time.deltaTime);
}
}
}
++4.3、特性
++++NetworkBehaviour組件內包含的常用特性[Attrivute]如下:
--[SyncVar] : 用於標識序列化變量,實現變量同步。
--[Client] : 表示只能在客戶端調用。
--[ClientCallback] : 表示客戶端執行的回調。
--[Command] : 表示客戶端向服務器發送的命令,在服務器執行。
--[ClientRpc] : 表示服務器向客戶端發送的命令,在客戶端執行。
++1、遠程調用
++++網絡系統可以實現客戶端和服務器的通信,我們將這種通信稱之爲: 遠程調用(Remote Procedure Calls),即RPC。
++++RPC框架可以方便實現方法調用,使用戶不需要關心如何編碼、連接和傳輸。
++++Unity中的RPC有兩種類型:
--客戶端調用服務器方法(Command)
--服務器調用客戶端方法(ClientRpc)
++2、RPC類型圖解
++++Command : 由客戶端發送給服務器[在服務器執行方法]
++++ClientRPC : 由服務器發送給客戶端[在客戶端執行方法]
++3、RPC編程步驟
++++編程:
public class RPCTest:NetworkBehaviour{
private GameObject img;
void Start(){
img = Resources.Load(「Canvas」) as GameObject;
CmdTest();
}
void Update(){
if(!isLocalPlayer){
return;
}
if(Input.GetKeyDown(KeyCode.Space)){
CmdTest();
}
}
[Command] //表示爲RPC方法--Command類型,方法名必須加前綴Cmd
void CmdTest(){ //Command方法只能在服務器調用
Instantiate(img);
Debug.Log(1);
}
}
++++前提: 創建好網絡工程。
--第一步: 給客戶端新建腳本RPCTest,繼承自NetworkBehaviour。
--第二步: 創建Command方法或ClientRPC方法。
--第三步: 調用RPC方法。
++1、NetworkManager組件
++++網絡管理器(NetworkManager)是Unity新版網絡HLAPI中的一個核心組件,該組件封裝了網絡創建、運行和Debug等各種方法。
++++初級開發者,不需要寫一行代碼,即可實現簡單的網絡遊戲。
++2、組件方法講解
++++方法 : 功能
++++StartServer : 調用該方法,將開啓一個新服務器。
++++OnStartServer : 回調方法,服務器開啓後會自動調用該方法[On前綴方法爲回調方法]
++++StartHost : 調用該方法,將開啓一個主機。
++++OnStartHost : 回調方法,主機開啓後會自動調用該方法。
++++OnServerConnect : 服務器回調方法,當有客戶端連接時調用。
++++OnClientConnect : 客戶端回調方法,當客戶端連接到服務器時調用。
++練習:
++++新建腳本MyNetworkManager組件,繼承自NetworkManager組件,使用OnGUI回調函數,繪製按鈕,開啓服務器,並在服務器開啓之後自動輸出:Server OK!
++++NetworkManager組件在UnityEngine.Networking命名空間下。
++++思考:
public class MyNetworkManager:NetworkManager{
bool isAtStartUp = false;
void OnGUI(){
if(isAtStartUp){
this.enabled=false;
}
if(GUILayout.Button(「創建服務器」)){ //客戶端如何連接?
StartServer();
isAtStartUp = true;
}
}
public override void OnStartServer(){
base.OnStartServer();
print(「Server OK!」);
}
}
++組件屬性講解
++3、使用步驟
++++1、新建場景A,新建一個空物體,並給其添加NetworkManager組件和NetworkManagerHUD組件。
++++2、保存場景,並添加到Scenes In Build中。
++++3、將場景A拖到NetworkManager的Offline Scene框中。
++++4、新建場景B,保存並添加到Scenes In Build中。
++++5、將場景B拖到NetworkManager的Online Scene中。
++++6、新建一個小球,添加組件Network Identity組件,勾選Local Player Authority選項,拖成預設體,在Hierarchy視圖中刪除該物體。
++++7、將預設體小球拖到NetworkManager的Player Prefab框中,運行程序。
++總結
++++NetworkManager包含功能如下:
--遊戲狀態管理
--卵生管理
--場景管理
--Debug輸出
--匹配比賽
--用戶自定義
++UNet的一個簡單應用
++++MyNet_AppConst.cs
++++Scene02NetWorkManager.cs
++++Scene02PlayerAController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyNet_AppConst{
public const int myServerPort=34567;
public const string myServerIp= 「127.0.0.1」;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //引入UI命名空間
using unityEngine.Networking; //引入Unet網絡命名空間
publicclassScene02NetWorkManager:MonoBehaviour{
[HideInInspector]
public static Scene02NetWorkManager MyNetInstance; //一個快捷訪問簡單實例
Button m_createServerBtn; //1、創建服務器button
Button m_connectServBth;
InputField m_myInputServIp;
InputField m_myInputServPort;
NetworkClient m_MyClient;
public GameObject mPlayerPrefab; //16、增加玩家
private void Awake(){
myNetInstance = this;
//0、後臺運行
Application.runInBackground = true;
}
void Start(){
//2、找到創建服務器的button
m_createServerBtn = GameObject.Find(「Button_CreateServer」).GetComponent<Button>();
m_createServerBtn.onClick.AddListener(OnMyServerInitAction);
m_MyClient = new NetworkClient();
m_connectServBtn = GameObject.Find(「Button_ConnectServer」).GetComponent<Button>();
m_connectServBtn.onClick.AddListener(OnMyClientConnectToServAction);
m_myInputServIp = GameObject.Find(「InputField_ServIP」).GetComponent<InputField>();
m_myInputServPort = GameObject.Find(「InputField_ServPort」).GetComponet<InputField>();
}
void Update(){
}
//3、創建服務器
private void OnMyServerInitAction(){
//4、啓動服務器
bool bListen = NetworkServer.Listen(MyNet_AppConst.myServerPort);
if(bListen){
m_createServerBtn.interactable = false; //取消交互
}else{
}
//5、MsgType事件註冊方法
//MsgType.AddPlayer;
//MsgType.Animation;
//MsgType.AnimationParameters;
//MsgType.AnimationTrigger;
//MsgType.Command;
//MsgType.Connect;
//MsgType.CRC;
//MsgType.Disconnect;
//MsgType.Error;
//MsgType.Fragment;
//5、爲事件註冊方法
NetworkServer.RegisterHandler(MsgType.AddPlayer, OnMyServerAddPlayer);
NetworkServer.RegisterHandler(MsgType.Connect, OnMyServerConnectTo); //一旦有人連接到服務器,就會執行
NetworkServer.RegisterHandler(MsgType.Disconnect, OnMyServerDisConnect);
//22、對服務器玩家的創建過程單獨處理
m_MyClient = ClientScene.ConnectLocalServer();
m_MyClient.RegisterHandler(MsgType.Conncet, OnMyClientConnectSuccess);
}
//6、收到客戶端添加玩家的請求
private void OnMyServerAddPlayer(NetworkMessage netMsg){
//18、收到了客戶端發送的添加玩家的消息
float randomPos = UnityEngine.Random.Range(-2,2);
GameObject playerA = GameObject.Instantiate(myPlayerPrefab, new Vector3(randomPos, 1,randomPos), Quaternion.identity);
//19、爲該遊戲對象指明權限
NetworkServer.AddPlayerForConnection(netMsg.conn, playerA, 0);
//20、卵生出去
NetworkServer.Spawn(playerA);
}
//7、有人連接服務器的回調方法
private void OnMyServerConnectTo(NetworkMessage netMsg){
}
//8、有人斷開服務器的回調方法
private void OnMyServerDisConnect(NetworkMessage netMsg){
}
//點擊連接服務器的事件
private void OnMyClientConnectToServAction(){
//12、連接服務器
string servIpStr;
int servPortInt;
if(m_myInputServIp.text.Length == 0){
servIpStr = MyNet_AppConst.myServerIp;
}else{
servIpStr = m_myInputServIp.text;
}
if(m_myInputServPort.text.Length == 0){
servPortInt = MyNet_AppConst.myServerPort;
}else{
servPortInt = int.Parse(m_myInputServPort.text);
}
m_MyClient.Connect(servIpStr, servPortInt); //連接服務器
//13、註冊連接成功的回調
m_MyClient.RegisterHandler(MsgType.Connect, OnMyClientConnectSuccess);
}
//14、客戶端連接服務器成功的方法
public void OnMyClientConnectSuccess(NetworkMessage netMsg){
//15、告訴服務器,當前客戶端已經準備好
ClientScene.Ready(netMsg.conn);
//21、註冊預製體
ClientScene.RegisterPrefab(mPlayerPrefab); //fix:特別重要
//17、實例化預設體
//網絡遊戲對象必須由服務器產生,卵生到客戶端
ClientScene.AddPlayer(0); //發送 //fix:特別重要
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class Scene02PlayerAContoller:NetworkBehaiour{
float hor,ver;
public GameObject bulletPrefab; //子彈預設體
public Transform firePos; //炮口
//計時器
public float myTimer=0f;
public float myTimeCd=1f;
//血條
public Scrollbar myScrollbar; //血條
//血量--全局變量(客戶端修改,所有客戶端同步修改)
//同步變量的修改,一定要通過服務器。
[SyncVar]
float hp = 100; //血量
void Start(){
//血條需要共同刷新
myScrollbar.size = hp/100f; //設置血條百分比
myScrollbar.transform.rotation=Camera.main.transform.rotation; //血條和主攝像機四元數方向一致
if(isLocalPlayer == false){
return;
}
hor=Input.GetAxis(「Horizontal」);
ver=Input.GetAxis(「Vertical」);
if(hor!=0){
transform.Rotate(Vector3.up*Time.deltaTime*180f*hor);
}
if(ver!=0){
transform.postion+=transform.forward*Time.deltaTime*3f*ver;
}
//開火
myTimer -= Time.deltaTime;
if(Input.GetMouseButtonDown(0)){
if(myTimer<=0){
Cmd_MyPlayer_Fire();
myTimer = myTimeCd;
}
}
//模擬受到傷害
if(Input.GetKeyDown(KeyCode.Space)){
Cmd_MyPlayer_TakeDamage(10f);
}
}
//開火
[Commad]
public void Cmd_MyPlayer_Fire(){
//服務器中執行
GameObject mybullet = GameObject.Instantiate(bulletPrefab, firePos.position, firePos.rotation);
Rigidbody rig = mybullet.GetComponent<Rigidbody>();
rig.velocity = mybullet.transform.forward*100f;
Destroy(mybullet, 5f);
NetworkServer.Spawn(mybullet);
}
//受到傷害
[Command]
public void Cmd_MyPlayer_TakeDamage(float damage){
hp -= damage;
if(hp <= 0){
NetworkServer.Destroy(gameObject);
}
}
}
++Unity的UNET組件
++++新建一個UnetProject。
++++新建一個GameObject重命名爲Network Manager,給它添加Network Manager組件,這是Unet提供的一個核心管理組件,可以在腳本里訪問Network Manager進行網絡開發。
++++還需要添加一個Network Manager HUD組件,這個用來顯示UI,UI上的按鈕會跟Network Manager交互。
++Network Manager HUD組件
++++LAN Host(H) : 把本機作爲Server + Client,即服務器加客戶端。
++++LAN Client(C) : 與服務器連接,後面填ip地址(localhost就是本機)。
++++LAN Server Only(S) : 本機只作爲服務器。
++++一般在測試時纔會用這個組件。
++搭建一個Player
++++現在用Unity自帶的模型拼裝一個Player出來(隨便就行),給他添加Network Identity組件,這是一個網絡標識符,擁有標識符的物體可以在網絡上生成,也就是同步到其他客戶端。
++++Server Only :只會在服務器端時纔有權限對他進行操作。
++++Local Player Authority : 會在客戶端時有權限,是一個局部角色。
++++我們給Player選中Local Player Authority,表示運行時連接上服務器我們也可以對他進行操作。
++++爲了讓他能在局域網生成,這表示我們要生成的角色是哪個,這樣在每次聯機時Network Manager會自動根據Player Prefab創建一個角色。
++++Auto Create Player : 每次服務器,客戶端連接都會創建一個Player,現在運行看見的效果不明顯,優化角色控制後再運行看效果。
++++新建PlayerController腳本並編輯:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
//爲了能讓腳本在連上局域網的同時還能分別控制物體,需要繼承NetworkBehaviour
public class PlayerController:NetworkBehaviour{
public float traSpeed = 3; //移動的速度
public float rotSpeed=120; //一秒旋轉的角度
void Update(){
if(!isLocalPlayer){
//isLocalPlayer是NetworkBehaviour的內置屬性
//如果不是本地客戶端,就返回,不執行下面的操作
return;
}
float h = Input.GetAxis(「Horizontal」);
float v = Input.GetAxis(「Vertical」);
transform.Translate(Vector3.forward*v*traSpeed*Time.deltaTime); //朝某個方向移動
transform.Rotate(Vector3.up* h *rotSpeed*Time.deltaTime); //圍繞某軸旋轉
}
}
++添加Network Transform組件
++++還需要給Player添加一個Network Transform組件,這是一個同步Transform的組件,包括:position、rotation、scale。它的同步是單向的,就是將你控制的物體同步到其他客戶端,當你在服務端改變物體時,客戶端不會跟着改變。
++添加差異化腳本
++++兩個角色看起來一樣,添加控制腳本。
//這是重寫NetworkBehaviour內的方法
//這個方法只會在創建本地角色時調用
public override void OnStartLocalPlayer(){
GetComponent<MeshRenderer>().material.color = Color.bule;
}
++++運行:
++++自己控制的是藍色,另外一個是默認的白色。
++給角色添加槍和子彈
++++給角色添加上槍和子彈,讓他可以射擊。
++++還要給子彈添加上Rigidbody組件,取消重力。
++++把槍的碰撞器去掉,它不需要做檢測。
#立鑽哥哥Unity 學習空間: http://blog.csdn.net/VRunSoftYanlz/
++立鑽哥哥推薦的拓展學習鏈接(Link_Url):
++++立鑽哥哥Unity 學習空間: http://blog.csdn.net/VRunSoftYanlz/
++++Unity引擎基礎:http://www.noobyard.com/article/p-ggcuedyq-ka.html
++++Unity面向組件開發:http://www.noobyard.com/article/p-eiunlkzw-dt.html
++++Unity物理系統:http://www.noobyard.com/article/p-mcqnwufb-kd.html
++++Unity2D平臺開發:http://www.noobyard.com/article/p-brjbvtac-hs.html
++++UGUI基礎:http://www.noobyard.com/article/p-nvzrvath-mc.html
++++UGUI進階:http://www.noobyard.com/article/p-tpspjolu-gt.html
++++UGUI綜合:http://www.noobyard.com/article/p-nfgrebqx-gg.html
++++Unity動畫系統基礎:http://www.noobyard.com/article/p-otjpnbzz-dq.html
++++Unity動畫系統進階:http://www.noobyard.com/article/p-hxghrtgb-bp.html
++++Navigation導航系統:http://www.noobyard.com/article/p-skpvrobt-t.html
++++Unity特效渲染:http://www.noobyard.com/article/p-sudpqrhk-bp.html
++++Unity數據存儲:http://www.noobyard.com/article/p-ybvcceul-m.html
++++Unity中Sqlite數據庫:http://www.noobyard.com/article/p-vxpuqxev-ca.html
++++WWW類和協程:http://www.noobyard.com/article/p-alggjlwu-cy.html
++++Unity網絡:http://www.noobyard.com/article/p-bjvfgzwg-dw.html
++++C#事件:http://www.noobyard.com/article/p-dietpjzv-gm.html
++++C#委託:http://www.noobyard.com/article/p-oiohmxtc-gh.html
++++C#集合:http://www.noobyard.com/article/p-vdfpislb-ex.html
++++C#泛型:http://www.noobyard.com/article/p-vujvnprk-ee.html
++++C#接口:http://www.noobyard.com/article/p-emexlwmu-dm.html
++++C#靜態類:https://blog.csdn.net/vrunsoftyanlz/article/details/78630979
++++C#中System.String類:http://www.noobyard.com/article/p-uchiaxzw-cq.html
++++C#數據類型:http://www.noobyard.com/article/p-kqtbvoyq-ba.html
++++Unity3D默認的快捷鍵:http://www.noobyard.com/article/p-gbllyjbs-s.html
++++遊戲相關縮寫:http://www.noobyard.com/article/p-pzpxsztf-gm.html
++++設計模式簡單整理:http://www.noobyard.com/article/p-scmbzocc-hg.html
++++U3D小項目參考:https://blog.csdn.net/vrunsoftyanlz/article/details/80141811
++++UML類圖:http://www.noobyard.com/article/p-aakurcwi-bm.html
++++Unity知識點0001:http://www.noobyard.com/article/p-bqmetnys-ep.html
++++U3D_Shader編程(第一篇:快速入門篇):http://www.noobyard.com/article/p-ptwlpwbc-gz.html
++++U3D_Shader編程(第二篇:基礎夯實篇):http://www.noobyard.com/article/p-dadqpvvp-hv.html
++++立鑽哥哥Unity 學習空間: http://blog.csdn.net/VRunSoftYanlz/
--_--VRunSoft : lovezuanzuan--_--