導航:首頁 > IDC知識 > photon游戲伺服器

photon游戲伺服器

發布時間:2020-11-26 17:21:16

1、photon游戲伺服器,使用js版本的sdk,如何監聽joinRandomRoom 失敗?

你好!javax.Swing實現button的監聽有兩種方式: 方法一:實現 implements ActionListener介面。然後實現它的抽象方法 public void

2、有人會用PhotonServer 作為unity 的伺服器嗎

看英文是 證書獲取抄 初始化 失敗
可能是證書有問題,其實我並不清楚
找到類似的文件
[email protected]
.license是證書的後綴,前面是你的注冊郵箱找到一這個為結尾的文件就行
找到後,復制到你這個啟動文件的目錄。
友情提示:網上的教程已經過時,這個軟體的一些構造函數已經變了,除非你能看懂官方文檔,或者有人教你,不然,慎重選擇

3、photon可以做moba類游戲的伺服器嗎

伺服器端源碼:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
*
* 文件名:ServerReceive.java
* 實現功能:作為伺服器接收客戶端發送的文件
*
* 具體實現過程:
* 1、建立SocketServer,等待客戶端的連接
* 2、當有客戶端連接的時候,按照雙方的約定,這時要讀取一行數據
* 其中保存客戶端要發送的文件名和文件大小信息
* 3、根據文件名在本地創建文件,並建立好流通信
* 4、循環接收數據包,將數據包寫入文件
* 5、當接收數據的長度等於提前文件發過來的文件長度,即表示文件接收完畢,關閉文件
* 6、文件接收工作結束

public class ServerReceive {

public static void main(String[] args) {

/**與伺服器建立連接的通信句柄*/
ServerSocket ss = null;
Socket s = null;

/**定義用於在接收後在本地創建的文件對象和文件輸出流對象*/
File file = null;
FileOutputStream fos = null;

/**定義輸入流,使用socket的inputStream對數據包進行輸入*/
InputStream is = null;

/**定義byte數組來作為數據包的存儲數據包*/
byte[] buffer = new byte[4096 * 5];

/**用來接收文件發送請求的字元串*/
String comm = null;

/**建立socekt通信,等待伺服器進行連接*/
try {
ss = new ServerSocket(4004);
s = ss.accept();
} catch (IOException e) {
e.printStackTrace();
}

/**讀取一行客戶端發送過來的約定信息*/
try {
InputStreamReader isr = new InputStreamReader(s.getInputStream());
BufferedReader br = new BufferedReader(isr);
comm = br.readLine();
} catch (IOException e) {
System.out.println("伺服器與客戶端斷開連接");
}

/**開始解析客戶端發送過來的請求命令*/
int index = comm.indexOf("/#");

/**判斷協議是否為發送文件的協議*/
String xieyi = comm.substring(0, index);
if(!xieyi.equals("111")){
System.out.println("伺服器收到的協議碼不正確");
return;
}

/**解析出文件的名字和大小*/
comm = comm.substring(index + 2);
index = comm.indexOf("/#");
String filename = comm.substring(0, index).trim();
String filesize = comm.substring(index + 2).trim();

/**創建空文件,用來進行接收文件*/
file = new File(filename);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("伺服器端創建文件失敗");
}
}else{
/**在此也可以詢問是否覆蓋*/
System.out.println("本路徑已存在相同文件,進行覆蓋");
}

/**【以上就是客戶端代碼中寫到的伺服器的准備部分】*/

/**
* 伺服器接收文件的關鍵代碼*/
try {
/**將文件包裝到文件輸出流對象中*/
fos = new FileOutputStream(file);
long file_size = Long.parseLong(filesize);
is = s.getInputStream();
/**size為每次接收數據包的長度*/
int size = 0;
/**count用來記錄已接收到文件的長度*/
long count = 0;

/**使用while循環接收數據包*/
while(count < file_size){
/**從輸入流中讀取一個數據包*/
size = is.read(buffer);

/**將剛剛讀取的數據包寫到本地文件中去*/
fos.write(buffer, 0, size);
fos.flush();

/**將已接收到文件的長度+size*/
count += size;
System.out.println("伺服器端接收到數據包,大小為" + size);
}

} catch (FileNotFoundException e) {
System.out.println("伺服器寫文件失敗");
} catch (IOException e) {
System.out.println("伺服器:客戶端斷開連接");
}finally{
/**
* 將打開的文件關閉
* 如有需要,也可以在此關閉socket連接
* */
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}//catch (IOException e)
}//finally

}//public static void main(String[] args)
}//public class ServerReceive

客戶端源碼:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;

/**
*
* 文件名:ClientSend.java
* 實現功能:作為客戶端向伺服器發送一個文件
*
* 具體實現過程:
* 1、建立與伺服器端的連接,IP:127.0.0.1, port:4004
* 2、將文件的名字和大小通過自定義的文件傳輸協議,發送到伺服器
* 3、循環讀取本地文件,將文件打包發送到數據輸出流中
* 4、關閉文件,結束傳輸
*
* */

public class ClientSend {

public static void main(String[] args) {

/**與伺服器建立連接的通信句柄*/
Socket s = null;

/**定義文件對象,即為要發送的文件
* 如果使用絕對路徑,不要忘記使用'/'和'\'的區別
* 具體區別,請讀者自行查詢
* */
File sendfile = new File("API.CHM");
/**定義文件輸入流,用來打開、讀取即將要發送的文件*/
FileInputStream fis = null;
/**定義byte數組來作為數據包的存儲數據包*/
byte[] buffer = new byte[4096 * 5];

/**定義輸出流,使用socket的outputStream對數據包進行輸出*/
OutputStream os = null;

/**檢查要發送的文件是否存在*/
if(!sendfile.exists()){
System.out.println("客戶端:要發送的文件不存在");
return;
}

/**與伺服器建立連接*/
try {
s = new Socket("127.0.0.1", 4004);
}catch (IOException e) {
System.out.println("未連接到伺服器");
}

/**用文件對象初始化fis對象
* 以便於可以提取出文件的大小
* */
try {
fis = new FileInputStream(sendfile);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}

/**首先先向伺服器發送關於文件的信息,以便於伺服器進行接收的相關准備工作
* 具體的准備工作,請查看伺服器代碼。
*
* 發送的內容包括:發送文件協議碼(此處為111)/#文件名(帶後綴名)/#文件大小
* */
try {
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("111/#" + sendfile.getName() + "/#" + fis.available());
ps.flush();
} catch (IOException e) {
System.out.println("伺服器連接中斷");
}

/**
* 此處睡眠2s,等待伺服器把相關的工作準備好
* 也是為了保證網路的延遲
* 讀者可自行選擇添加此代碼
* */
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}

/**之前的准備工作結束之後
* 下面就是文件傳輸的關鍵代碼
* */
try {

/**獲取socket的OutputStream,以便向其中寫入數據包*/
os = s.getOutputStream();

/** size 用來記錄每次讀取文件的大小*/
int size = 0;

/**使用while循環讀取文件,直到文件讀取結束*/
while((size = fis.read(buffer)) != -1){
System.out.println("客戶端發送數據包,大小為" + size);
/**向輸出流中寫入剛剛讀到的數據包*/
os.write(buffer, 0, size);
/**刷新一下*/
os.flush();
}
} catch (FileNotFoundException e) {
System.out.println("客戶端讀取文件出錯");
} catch (IOException e) {
System.out.println("客戶端輸出文件出錯");
}finally{

/**
* 將打開的文件關閉
* 如有需要,也可以在此關閉socket連接
* */
try {
if(fis != null)
fis.close();
} catch (IOException e) {
System.out.println("客戶端文件關閉出錯");
}//catch (IOException e)
}//finally

}//public static void main(String[] args)
}//public class ClientSend

4、unity3d 網游伺服器端如何選擇

如果對樓主有幫助,給個採納好不,謝謝啦

Photon和KBEngineunity3d是最適用Unity3d游戲開發的兩個伺服器引擎,但它們還是有區別的,只有清楚地了解區別在哪才能正確使用,下面簡單描述下兩者的共同點和不同點。

語言

對於大部分的程序員語言簡直就是宗教信仰。

Photon使用C#開發,當然使用者也是用C#進行各類游戲功能開發。前後端同種語言,這對使用Unity3d游戲開發也有很大的好處。

KBEngine使用C++開發,邏輯開發是用python,也是很不錯很快速的。

開源與收費情況

Photon是Exit Games公司的產品,不開源,有好多種收費模式,官網上可以看到。開發階段可以用免費的license,後期可以看流量用戶活躍度來選擇付費模式。後續的支持,似乎是免費的,你可以選擇郵件或是到論壇發帖求助,當然是E文。

KBEngine是國人開發,開源免費,但從官網上並沒有看到商業使用的案例。有中文論壇,你可以在論壇上向開發者求助。

雖然兩者的模式不同,但作為一個Unity3d游戲開發者,我們最希望的其實是把游戲引擎當作一個安全穩定的黑箱。

操作系統

之前說了Photon使用C#開發很自然的,配套的工具也是使用C#,比如最重要的PhotonControl。所以開發環境和生產環境最好都是windows。

雖然在跨平台上有mono,在伺服器代碼部分是系統無關的,但是不管你信不信,我是不信它的一套窗體工具也能運行在Linux下。反正,官網說法是,開發和生產環境都是用windows。

KBEngine建議開發環境選擇Windows,生產環境選擇linux。畢竟你總不希望開一組伺服器打開9個Console窗體,一不小心把哪個點X了吧~

協議

Photon有自己的序列化反序列化方式,你也可以使用protobuf這類的來做應用層傳輸協議。

KBEngine在這方面表示不支持自定義協議,它幫你選擇了有效的方法來處理,如果你習慣了他規定的方式,會喜歡上的。

看法

在功能上,我毫無疑問地更喜歡KBEngine,腳本化和自動持久化是極富魅力的功能。而Photon幾乎沒做這方面的功能,可能和老外的觀念有關系。就目前我對兩者功能的理解看來,Photon其實是個和SuperSocket差不多的東西,而SS是作為輕量級伺服器框架存在的,Photon卻是說自己是Unity3d游戲引擎,除去提供的MMO示例代碼(未解讀),沒看到什麼游戲引擎的魅力。

5、unity photon 能取代傳統伺服器嗎

* 具體實現過程:
* 1、建立SocketServer,等待客戶端的連接
* 2、當有客戶端連接的時候,按照雙方的約定,這時要讀取一行數據
* 其中保存客戶端要發送的文件名和文件大小信息
* 3、根據文件名在本地創建文件,並建立好流通信
* 4、循環接收數據包,將數據包寫入文件
* 5、當接收數據的長度等於提前文件發過來的文件長度,即表示文件接收完畢,關閉文件
* 6、文件接收工作結束

public class ServerReceive {

public static void main(String[] args) {

/**與伺服器建立連接的通信句柄*/
ServerSocket ss = null;
Socket s = null;

/**定義用於在接收後在本地創建的文件對象和文件輸出流對象*/
File file = null;
FileOutputStream fos = null;

/**定義輸入流,使用socket的inputStream對數據包進行輸入*/
InputStream is = null;

/**定義byte數組來作為數據包的存儲數據包*/
byte[] buffer = new byte[4096 * 5];

/**用來接收文件發送請求的字元串*/
String comm = null;

/**建立socekt通信,等待伺服器進行連接*/
try {
ss = new ServerSocket(4004);
s = ss.accept();
} catch (IOException e) {
e.printStackTrace();
}

/**讀取一行客戶端發送過來的約定信息*/
try {
InputStreamReader isr = new InputStreamReader(s.getInputStream());
BufferedReader br = new BufferedReader(isr);
comm = br.readLine();
} catch (IOException e) {
System.out.println("伺服器與客戶端斷開連接");
}

/**開始解析客戶端發送過來的請求命令*/
int index = comm.indexOf("/#");

/**判斷協議是否為發送文件的協議*/
String xieyi = comm.substring(0, index);
if(!xieyi.equals("111")){
System.out.println("伺服器收到的協議碼不正確");
return;
}

/**解析出文件的名字和大小*/
comm = comm.substring(index + 2);
index = comm.indexOf("/#");
String filename = comm.substring(0, index).trim();
String filesize = comm.substring(index + 2).trim();

/**創建空文件,用來進行接收文件*/
file = new File(filename);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("伺服器端創建文件失敗");
}
}else{
/**在此也可以詢問是否覆蓋*/
System.out.println("本路徑已存在相同文件,進行覆蓋");
}

/**【以上就是客戶端代碼中寫到的伺服器的准備部分】*/

/**
* 伺服器接收文件的關鍵代碼*/
try {
/**將文件包裝到文件輸出流對象中*/
fos = new FileOutputStream(file);
long file_size = Long.parseLong(filesize);
is = s.getInputStream();
/**size為每次接收數據包的長度*/
int size = 0;
/**count用來記錄已接收到文件的長度*/
long count = 0;

/**使用while循環接收數據包*/
while(count < file_size){
/**從輸入流中讀取一個數據包*/
size = is.read(buffer);

/**將剛剛讀取的數據包寫到本地文件中去*/
fos.write(buffer, 0, size);
fos.flush();

/**將已接收到文件的長度+size*/
count += size;
System.out.println("伺服器端接收到數據包,大小為" + size);
}

} catch (FileNotFoundException e) {
System.out.println("伺服器寫文件失敗");
} catch (IOException e) {
System.out.println("伺服器:客戶端斷開連接");
}finally{
/**
* 將打開的文件關閉
* 如有需要,也可以在此關閉socket連接
* */
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}//catch (IOException e)
}//finally

}//public static void main(String[] args)
}//public class ServerReceive

客戶端源碼:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;

/**
*
* 文件名:ClientSend.java
* 實現功能:作為客戶端向伺服器發送一個文件
*
* 具體實現過程:
* 1、建立與伺服器端的連接,IP:127.0.0.1, port:4004
* 2、將文件的名字和大小通過自定義的文件傳輸協議,發送到伺服器
* 3、循環讀取本地文件,將文件打包發送到數據輸出流中
* 4、關閉文件,結束傳輸
*
* */

public class ClientSend {

public static void main(String[] args) {

/**與伺服器建立連接的通信句柄*/
Socket s = null;

/**定義文件對象,即為要發送的文件
* 如果使用絕對路徑,不要忘記使用'/'和'\'的區別
* 具體區別,請讀者自行查詢
* */
File sendfile = new File("API.CHM");
/**定義文件輸入流,用來打開、讀取即將要發送的文件*/
FileInputStream fis = null;
/**定義byte數組來作為數據包的存儲數據包*/
byte[] buffer = new byte[4096 * 5];

/**定義輸出流,使用socket的outputStream對數據包進行輸出*/
OutputStream os = null;

/**檢查要發送的文件是否存在*/
if(!sendfile.exists()){
System.out.println("客戶端:要發送的文件不存在");
return;
}

/**與伺服器建立連接*/
try {
s = new Socket("127.0.0.1", 4004);
}catch (IOException e) {
System.out.println("未連接到伺服器");
}

/**用文件對象初始化fis對象
* 以便於可以提取出文件的大小
* */
try {
fis = new FileInputStream(sendfile);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}

/**首先先向伺服器發送關於文件的信息,以便於伺服器進行接收的相關准備工作
* 具體的准備工作,請查看伺服器代碼。
*
* 發送的內容包括:發送文件協議碼(此處為111)/#文件名(帶後綴名)/#文件大小
* */
try {
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("111/#" + sendfile.getName() + "/#" + fis.available());
ps.flush();
} catch (IOException e) {
System.out.println("伺服器連接中斷");
}

/**
* 此處睡眠2s,等待伺服器把相關的工作準備好
* 也是為了保證網路的延遲
* 讀者可自行選擇添加此代碼
* */
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}

/**之前的准備工作結束之後
* 下面就是文件傳輸的關鍵代碼
* */
try {

/**獲取socket的OutputStream,以便向其中寫入數據包*/
os = s.getOutputStream();

/** size 用來記錄每次讀取文件的大小*/
int size = 0;

/**使用while循環讀取文件,直到文件讀取結束*/
while((size = fis.read(buffer)) != -1){
System.out.println("客戶端發送數據包,大小為" + size);
/**向輸出流中寫入剛剛讀到的數據包*/
os.write(buffer, 0, size);
/**刷新一下*/
os.flush();
}
} catch (FileNotFoundException e) {
System.out.println("客戶端讀取文件出錯");
} catch (IOException e) {
System.out.println("客戶端輸出文件出錯");
}finally{

/**
* 將打開的文件關閉
* 如有需要,也可以在此關閉socket連接
* */
try {
if(fis != null)
fis.close();
} catch (IOException e) {
System.out.println("客戶端文件關閉出錯");
}//catch (IOException e)
}//finally

}//public static void main(String[] args)
}//public class ClientSend

6、如果網路游戲運營商的伺服器是光子伺服器那游戲還坑錢嗎?光子伺服器能耗極小

玩兒游戲充值或者不充值是看自己意願,再說了廠商研發的主要目的是賺錢。

7、PhotonServer伺服器連接mysql資料庫報錯,實在無力了,求大神!

本文將對NHibernate數據進行簡單封裝,方便在PhotonServer伺服器中進行調用

[csharp] view plain copy

using NHibernate;  

using NHibernate.Cfg;  

using MyGameServer.Domain;  

using NHibernate.Criterion;  

using System.Collections.Generic;  

namespace MyGameServer.Helper  

{  

public static class NHibernateHelper  

{  

private static ISessionFactory sessionFactory = null;  

private static ISession session = null;  

public static ISession GetSession  

{  

get  

{  

if (sessionFactory == null)  

{  

Configuration cfg = new Configuration();  

//解析固定路徑配置文件.cfg.xml  

cfg.Configure();  

//映射目標程序集 解析映射文件 Student.xml ......  

cfg.AddAssembly(typeof(Student).Assembly);  

//獲取會話對象  

sessionFactory = cfg.BuildSessionFactory();  

}  

session = sessionFactory.OpenSession();  

return session;  

}  

private set { }  

}  

//添加行  

public static void AddData<T>(T t)  

{  

using (ISession session = GetSession)  

{  

using (ITransaction transaction=session.BeginTransaction())  

{  

GetSession.Save(t);  

transaction.Commit();  

}  

}  

}  

//添加列  

public static void RemoveData<T>(T t)  

{  

using (ISession session = GetSession)  

{  

using (ITransaction transaction = session.BeginTransaction())  

{  

GetSession.Delete(t);  

transaction.Commit();  

}  

}  

}  

//通過ID獲取對象  

public static T GetDataById<T>(int id)  

{  

using (ISession session = GetSession)  

{  

using (ITransaction transaction = session.BeginTransaction())  

{  

T t = session.Get<T>(id);  

transaction.Commit();  

return t;  

}  

}  

}  

/// <summary>  

/// 通過名稱獲取對象  

/// </summary>  

/// <typeparam name="T">需要獲取的對象</typeparam>  

/// <param name="dataBaseName">在資料庫中的列名稱</param>  

/// <param name="targetName">獲取對象的目標名</param>  

/// <returns></returns>  

public static T GetDataByName<T>(string dataBaseName, string targetName)  

{  

using (ISession session = GetSession)  

{  

T t = session.CreateCriteria(typeof(T)).Add(Restrictions.Eq(dataBaseName, targetName)).UniqueResult<T>();  

return t;  

}  

}  

/// <summary>  

/// 得到表內的全部對象  

/// </summary>  

/// <typeparam name="T"></typeparam>  

/// <returns></returns>  

public static ICollection<T> GetAllUsers<T>()  

{  

using (ISession session = GetSession)  

{  

IList<T> ts = session.CreateCriteria(typeof(T)).List<T>();  

return ts;  

}  

}  

//查詢是否有符合id和姓名相同的對象  

public static bool VerifyUser<T>(params object[] arg)  

{  

using (ISession session = GetSession)  

{  

T t = session  

.CreateCriteria(typeof(T))  

.Add(Restrictions.Eq(arg[0].ToString(), arg[1]))//類屬性名 屬性值  

.Add(Restrictions.Eq(arg[2].ToString(), arg[3]))  

.UniqueResult<T>();  

if (t == null)  

{  

return false;  

}  

return true;  

}  

}  

/// <summary>  

/// 更新數據表  

/// </summary>  

/// <typeparam name="T">數據表映射的對象</typeparam>  

/// <param name="t"></param>  

public static void UpdateData<T>(T t)  

{  

using (ISession session = GetSession)  

{  

using (ITransaction transaction=session.BeginTransaction())  

{  

session.Update(t);  

transaction.Commit();  

}  

}  

}  

}  

}  



在主函數調用

[csharp] view plain copy

using NHibernate;  

using NHibernate.Cfg;  

using LJL.Domain;  

using LJL.Helper;  

namespace LJL  

{  

class Program  

{  

static void Main(string[] args)  

{  

Student sd = new Student { mID = 6, mName = "小張", mScore = 10 };  

NHibernateHelper.AddData(sd);  

}  

}  

}  



運行程序,一切正常,打開SQLyog,在student數據表中添加一行數據

接下來就是在PhotonServer中調用,來實現與MySQL資料庫交互

按圖下將類、配置文件集成到類庫中(注意需要修改下類和配置文件中的程序集及命名空間)


接下來就是在Unity3d游戲客戶端中與PhotonServer通信進而訪問本地資料庫

在Unity3d客戶端上創建UI(這里簡單拖入輸入框和按鈕)

如下圖創建腳本


我們的游戲有很多中請求(比如登入、注冊請求等等)

所以都繼承自BaseRequest

[csharp] view plain copy

using ExitGames.Client.Photon;  

using System.Collections;  

using System.Collections.Generic;  

using UnityEngine;  

public abstract class BaseRequest : MonoBehaviour  

{  

[HideInInspector]  

//該請求的操作類型  

public Collective.OperationMode operationMode = Collective.OperationMode.Default;  

public virtual void Start() { }  

public abstract void OnOperationRequest();  

public abstract void OnOperationResponse(OperationResponse operationResponse);  

}  



這里博主簡單的做了一下登錄請求

[csharp] view plain copy

using ExitGames.Client.Photon;  

using System.Collections;  

using System.Collections.Generic;  

using UnityEngine;  

using UnityEngine.UI;  

public class LoginRequest : BaseRequest  

{  

//用戶名  

private InputField mInputName;  

//密碼  

private InputField mInputPassword;  

public override void Start()  

{  

operationMode = Collective.OperationMode.LOGIN;  

GameContext.GetInstance.AddRequest(this);  

mInputName = GameObject.Find("IDInputField").GetComponent<InputField>();  

mInputPassword = GameObject.Find("NameInputField").GetComponent<InputField>();  

//登錄按鈕點擊事件  

GameObject.Find("LoginButton").GetComponent<Button>().onClick.AddListener(() => { OnOperationRequest(); });  

}  

public override void OnOperationRequest()  

{  

GameContext.GetInstance.peer.OpCustom(  

(byte)this.operationMode,  

new Dictionary<byte, object> { { (byte)Collective.ParameterMode.NAME, mInputName.text }, { (byte)Collective.ParameterMode.PASSWORD, mInputPassword.text } },  

true  

);  

}  

public override void OnOperationResponse(OperationResponse operationResponse)  

{          

Collective.OperationResult resultCode = (Collective.OperationResult)operationResponse.ReturnCode;  

if (resultCode == Collective.OperationResult.SUCCESS)  

{  

//登錄成功  

Debug.Log("用戶登錄成功");  

}  

else if(resultCode == Collective.OperationResult.FAIL)  

{  

//登錄失敗  

Debug.Log("登錄失敗");  

}  

}  

}  



最後附上上篇博文GameContext腳本,在這里有些地方發生了更新

[csharp] view plain copy

using System.Linq;  

using System.Collections.Generic;  

using UnityEngine;  

using UnityEngine.UI;  

using ExitGames.Client.Photon;  

public class GameContext : MonoBehaviour,IPhotonPeerListener  

{  

/// <summary>  

/// 存儲操作類型與請求  

/// </summary>  

public Dictionary<Collective.OperationMode, BaseRequest> requestDic = new Dictionary<Collective.OperationMode, BaseRequest>();  

public PhotonPeer peer;  

private static GameContext _instance;  

public static GameContext GetInstance  

{  

get  

{  

if (_instance == null)  

{  

_instance = GameObject.Find("GameContext").GetComponent<GameContext>();  

}  

return _instance;  

}  

}  

public void DebugReturn(DebugLevel level, string message)  

{         

}  

//接收伺服器發來的事件  

public void OnEvent(EventData eventData)  

{  

switch (eventData.Code)  

{  

case 0:  

//獲取事件數據  

object value = eventData.Parameters.FirstOrDefault(q => q.Key == 1).Value;  

Debug.Log(value.ToString());  

break;  

default:  

break;  

}  

}  

//接收響應數據(客戶端發送了請求)  

public void OnOperationResponse(OperationResponse operationResponse)  

{  

BaseRequest request = requestDic.FirstOrDefault(q => q.Key == (Collective.OperationMode)operationResponse.OperationCode).Value;  

if (request != null)  

{  

request.OnOperationResponse(operationResponse);  

}  

else  

{  

//獲取響應數據失敗  

Debug.LogError("獲取響應數據失敗");  

}  

}  

//連接狀態發送改變  

public void OnStatusChanged(StatusCode statusCode)  

{  

Debug.Log("數據連接狀態發生的改變:" + statusCode);  

}  

private void Start()  

{  

//傳輸協議UDP 、 通過Listener接收伺服器端的響應  

peer = new PhotonPeer(this, ConnectionProtocol.Udp);  

//連接本地伺服器  

peer.Connect("127.0.0.1:5055", "MYGameServer");  

}  

private void Update()  

{  

//和伺服器實時保持數據連接  

peer.Service();                   

}  

private void OnDestroy()  

{  

if (peer != null && peer.PeerState == PeerStateValue.Connected)  

{  

//斷開連接  

peer.Disconnect();  

}  

}  

public void AddRequest(BaseRequest request)  

{  

8、用photonserver使用到了哪些技術

Photon Server是一套套裝的游戲伺服器,以往開發線上游戲都必需自行花費大筆的研發資金和人力先從研發游戲引擎和伺服器開始,後來慢慢的游戲引擎開始走向套裝化,研發人員有許多現成的游戲引擎可以選擇,像是unreal或是unity等等,接著,游戲伺服器也開始朝套裝發展,市面上常見的套裝Game Server有 smart fox server 、 electro server 5 、 Photon等等,這幾個都是非常優秀的套裝伺服器,市面上非常多的FB游戲都是利用這些套裝伺服器作為通訊用平台,都是經過市場驗證過的產品。

為什麼選擇 Photon Server?

Photon Server的核心是用C++開發,不同 於其他伺服器採用的java,因此在效能上凌駕於其他server不少,在 Server 端 Script 採用C#語言,算是一種很容易學習的語言,Photon的Client端支援C++、.net、java、html5 、flash、Unity、mamalade、iOS、android、winphone、cocos等,市面上常見的平台全部都有支援,使用容易、效能高、支援平台多,這些優點讓photon成為一個優越的套裝socket server。

Photon Server 有什麼缺點?

若要說Photon最大的缺點大概就是文件實在不是很好,市面上教學非常少 ,到目前為止也沒有專門的書籍,官方的手冊語焉不詳而且也很沒有系統,更諻論中文相關的教學了,大多在評估套裝伺服器的人都是在第一步打退堂豉而選擇了其他的Server,但只要跨過門欄就能發現Photon開發起來是比其他Server容易的多,附加的Lobby Server和MMO Server功能都非常強大完善而且效能極高,官方及討論區的服務快速而且熱心,這點足以彌補資料及手冊的不足了。

與photon游戲伺服器相關的知識