天天看點

用unity3d實作簡單chat對話

本文是解釋鷹大的多人聯網執行個體example1思路,由于自己了解的問題,不足地方請斧正。。。

------------------------------------------華麗的分割線--------------------------------------------

主線流程

1.      awake 【設計遊戲視窗 擷取玩家名字】

function Awake(){
	//開辟聊天的視窗
	window = Rect(Screen.width/2-width/2, Screen.height-height+5, width, height);

	//We get the name from the masterserver example, if you entered your name there ;).
	//**********************************************masterserver不了解;[14.3.30
	playerName = PlayerPrefs.GetString("playerName", "");
	if(!playerName || playerName==""){
		playerName = "RandomName"+Random.Range(1,999);
	}	
	
}
           

2.      ongui 【判斷是否顯示聊天視窗 建立聊天視窗 處理回車[擷取輸入焦點]】

function OnGUI ()
{
//顯示聊天視窗時【連接配接到伺服器的用戶端,初始化後的伺服器】才繪制聊天視窗
	if(!showChat){
		return;
	}
	
	GUI.skin = skin;		
	//目前處理的事件如果是按鍵按下	并且按下的按鍵是Enter鍵 并且未有輸入值【沒輸入時按Enter鍵】
	if (Event.current.type == EventType.keyDown && Event.current.character == "\n" && inputField.Length <= 0)
	{
	//如果上次釋放螢幕到現在超過0.25秒 
		if(lastUnfocusTime+0.25<Time.time){
			usingChat=true;
			//5号視窗【聊天視窗】鎖定為活動視窗
			GUI.FocusWindow(5);
			//焦點放到輸入框
			GUI.FocusControl("Chat input field");
		}
	}
	//建立5号彈出視窗【聊天視窗】  标題為空
	window = GUI.Window (5, window, GlobalChatWindow, "");
}
           

3.      建立聊天視窗 【建立滾動條 滾動條中從對話表中逐句讀取對話處理回車[傳出對話]以及滑鼠左鍵[失焦并停止對話顯示]效果】

//建立視窗的函數
function GlobalChatWindow (id : int) {
	//【垂直方向留白10像素】-----不留沒滾動條 不太懂;]
	GUILayout.BeginVertical();
	GUILayout.Space(10);
	GUILayout.EndVertical();
	
	// Begin a scroll view. All rects are calculated automatically - 
    // it will use up any available screen space and make sure contents flow correctly.
    // This is kept small with the last two parameters to force scrollbars to appear.
    //建立一個自動布局的滾動視圖,最後兩個參數确定了強制出現滾動條的範圍
	scrollPosition = GUILayout.BeginScrollView (scrollPosition);
	
	//在存儲的對話清單中讀取對話
	for (var entry : ChatEntry in chatEntries)
	{
	//建立水準組用以顯示姓名,輸入内容
		GUILayout.BeginHorizontal();
		//姓名不存在即輸出遊戲的資訊而非對話
		if(entry.name==""){//Game message
			GUILayout.Label (entry.text);
		}else{
			GUILayout.Label (entry.name+": "+entry.text);
		}
		GUILayout.EndHorizontal();
		//下邊的範圍 3像素空隙【不加沒有滾動條顯示】
		GUILayout.Space(3);
		
	}
	// End the scrollview we began above.
    GUILayout.EndScrollView ();
	//如果輸入值後按下空格鍵
	if (Event.current.type == EventType.keyDown && Event.current.character == "\n" && inputField.Length > 0)
	{
	//把輸入的值傳出
		HitEnter(inputField);
	}
	//為輸入控件命名
	GUI.SetNextControlName("Chat input field");
	inputField = GUILayout.TextField(inputField);
	
	//滑鼠左鍵按下時
	if(Input.GetKeyDown("mouse 0")){
	//當正在聊天時單擊左鍵,失去焦點并且标記為停止聊天
		if(usingChat){
			usingChat=false;
			GUI.UnfocusWindow ();//Deselect chat
			lastUnfocusTime=Time.time;
		}
	}
}
           

4.      傳出對話 【消除換行 将對話加入到對話表 初始化會話資訊】

function HitEnter(msg : String){
//将輸入的換行取消
	msg = msg.Replace("\n", "");
	//将目前的聊天對象和打入的話以RPC傳出
	networkView.RPC("ApplyGlobalChatText", RPCMode.All, playerName, msg);
	//将行中内容清除
	inputField = ""; //Clear line
	//使目前視窗【聊天視窗】失去焦點
	GUI.UnfocusWindow ();//Deselect chat
	//設定釋放焦點時間
	lastUnfocusTime=Time.time;
	//标記停止聊天
	usingChat=false;
}
           

連接配接(connect):

1.      用戶端OnConnectedToServer()

l        辨別顯示對話框

l        通知伺服器将此用戶端資訊傳入玩家清單

function OnConnectedToServer() {
//用戶端連接配接到伺服器或者伺服器初始化時初始化聊天視窗
	ShowChatWindow();
	//傳輸連接配接玩家名字用以顯示
	networkView.RPC ("TellServerOurName", RPCMode.Server, playerName);
	// //We could have also announced ourselves:
	// addGameChatMessage(playerName" joined the chat");
	// //But using "TellServer.." we build a list of active players which we can use for other stuff as well.
}
           

2.      伺服器OnServerInitialized()

l        辨別顯示對話框

l        直接将伺服器資訊存入玩家清單[當伺服器也作為一個玩家存在]

l        通知顯示伺服器加入對話【系統通知】

function OnServerInitialized() {
	ShowChatWindow();
	//I wish Unity supported sending an RPC on the server to the server itself :(
	// If so; we could use the same line as in "OnConnectedToServer();"
	var newEntry : PlayerNode = new PlayerNode();
	newEntry.playerName=playerName;
	newEntry.networkPlayer=Network.player;
	playerList.Add(newEntry);	
	//伺服器也作為一個聊天的玩家
	addGameChatMessage(playerName+" joined the chat");
}
           

伺服器OnPlayerConnected(player: NetworkPlayer)

l        傳遞顯示加入玩家加入遊戲的資訊【系統通知】

function OnPlayerConnected(player: NetworkPlayer) {
//玩家連接配接到伺服器時,伺服器廣播玩家資訊
	addGameChatMessage("Player connected from: " + player.ipAddress +":" + player.port);
}
           

掉線(disconnect)

1.        用戶端OnDisconnectedFromServer()

l        标記隐藏對話框

function OnDisconnectedFromServer(){
//從伺服器斷開後,用戶端關閉聊天視窗
	CloseChatWindow();
}
           

2.        伺服器OnPlayerDisconnected(player: NetworkPlayer)

l        傳遞顯示玩家掉線的資訊【系統通知】

l        在玩家清單删除掉線玩家資訊[依賴networkplayer擷取具體玩家資訊]

function OnPlayerDisconnected(player: NetworkPlayer) {
//玩家掉線時,伺服器調用,删除清單中的玩家
	addGameChatMessage("Player disconnected from: " + player.ipAddress+":" + player.port);
	
	//Remove player from the server list
	playerList.Remove( GetPlayerNode(player) );
}
           

封裝函數

1.      RPC函數

l        通知伺服器将用戶端的資訊傳入玩家清單【将傳入的資訊加入玩家清單通知顯示該玩家加入對話】

@RPC
//Sent by newly connected clients, recieved by server
//伺服器獲得用戶端傳輸的玩家資訊,并廣播
function TellServerOurName(name : String, info : NetworkMessageInfo){
	var newEntry : PlayerNode = new PlayerNode();
	newEntry.playerName=name;
	newEntry.networkPlayer=info.sender;
	playerList.Add(newEntry);
	
	addGameChatMessage(name+" joined the chat");
}
           

l        将對話加入到對話表

@RPC
function ApplyGlobalChatText (name : String, msg : String)
{
//将傳入的對話存儲到對話清單中
	var entry = new ChatEntry();
	entry.name = name;
	entry.text = msg;

	chatEntries.Add(entry);
	
	//Remove old entries
	//當對話清單中内容超過4條時銷毀第一條對話
	if (chatEntries.Count > 4){
		chatEntries.RemoveAt(0);
	}
	//将滾動條y軸數值設定極大,使得每次輸入後螢幕上都顯示最後一次輸入的内容
	scrollPosition.y = 1000000;	
}
           

2.      普通函數

l        依賴networkplayer擷取具體玩家資訊【逐條從玩家清單取出資訊比對】

function GetPlayerNode(networkPlayer : NetworkPlayer){
	for(var entry : PlayerNode in  playerList){
		if(entry.networkPlayer==networkPlayer){
			return entry;
		}
	}
	Debug.LogError("GetPlayerNode: Requested a playernode of non-existing player!");
	return null;
}
           

l        辨別顯示對話框【辨別顯示對話框輸入值、對話清單初始化】

function ShowChatWindow ()
{
	showChat = true;
	inputField = "";
	chatEntries = new ArrayList();
}
           

l        辨別隐藏對話框【辨別隐藏對話框輸入值、對話清單初始化】

function CloseChatWindow ()
{
	showChat = false;
	inputField = "";
	chatEntries = new ArrayList();
}
           

l        遊戲資訊的通知【系統通知】

//輸出遊戲資訊【**登入等等】伺服器的通知
function addGameChatMessage(str : String){
	ApplyGlobalChatText("", str);//通知自己
	if(Network.connections.length>0){
	//通知其他玩家
		networkView.RPC("ApplyGlobalChatText", RPCMode.Others, "", str);	
	}	
}
           

繼續閱讀