Unity進階之ET網絡游戲開發框架 07-修正游客登錄的異步BUG


版權申明:

  • 本文原創首發於以下網站:
  1. 博客園『優夢創客』的空間:https://www.cnblogs.com/raymondking123
  2. 優夢創客的官方博客:https://91make.top
  3. 優夢創客的游戲講堂:https://91make.ke.qq.com
  4. 『優夢創客』的微信公眾號:umaketop
  • 您可以自由轉載,但必須加入完整的版權聲明!

由來

  • 我的上一篇博文中的OnStartClick方法采用的是async異步方法,但是由於微軟並未保證async創建的方法一定在其調用線程中執行,所以不能保證程序是單線程的
  • ET整個框架都是基於多進程單線程這一設計思想的(為了避免多線程帶來的性能損失和邏輯錯誤),所以為了避免async造成的多線程陷阱,ET自定義了一套多線程任務系統,其返回值類型都是以ET開頭的,例如:
    • Task → ETTask
    • void → ETVoid
    • Task → ETTask
    • ET作者說過這么一句話:async方法的返回值永遠不要用.NET原生的Task,全部采用ETTask
  • 配套的,我們需要修改原有的代碼,如下:
public class MyStartUIComponent : Component
{
	GameObject goStartButton;

	public void OnAwake()
	{
		var rc = this.Parent.GameObject.GetComponent<ReferenceCollector>();
		goStartButton = rc.Get<GameObject>("StartButton");
		goStartButton.GetComponent<Button>().onClick.AddListener(OnStartClick);
	}

	private void OnStartClick()
	{
		// Coroutine()方法模擬將OnStartClickAsync()作為協程執行的效果(確保在單線程中執行)
		OnStartClickAsync().Coroutine();
	}

	private async ETVoid OnStartClickAsync()
	{
		// 處理游客登錄點擊
		try
		{
			// 1: 創建一個realmSession,並利用此session去call一個rpc消息(模型層session表示具體網絡參數和連接,熱更層負責通信邏輯,它調用模型層)
			ETModel.Session session = ETModel.Game.Scene.GetComponent<NetOuterComponent>().Create(GlobalConfigComponent.Instance.GlobalProto.Address);
			Session realmSession = ComponentFactory.Create<Session, ETModel.Session>(session);

			// 2:若登錄失敗,會收到異常;若成功,則會得到認證信息(模型層沒有C2R_Login的類定義,所以必須配套由熱更層的session去call)
			var r2cLogin = await realmSession.Call(new C2R_Login()
			{
				Account = Guid.NewGuid().ToString(),
				Password = "111111",
			}) as R2C_Login;

			// 3:再利用此認證信息中的網關服務器地址,去創建gateSession
			session = ETModel.Game.Scene.GetComponent<NetOuterComponent>().Create(r2cLogin.Address);
			Session gateSession = ComponentFactory.Create<Session, ETModel.Session>(session);

			// 4:用gateSession去登錄gate服(傳入登錄key)
			var g2cLoginGate = await gateSession.Call(new C2G_LoginGate()
			{
				Key = r2cLogin.Key
			}) as G2C_LoginGate;

			// 5:登錄成功后,用返回的playerId,創建Player對象
			var p = ETModel.ComponentFactory.CreateWithId<Player>(g2cLoginGate.PlayerId);
			ETModel.Game.Scene.GetComponent<PlayerComponent>().MyPlayer = p;

			// 6:發送登錄完成事件
			Game.EventSystem.Run(MyEventType.MyLoginFinish);
		}
		catch (Exception e)
		{
			Log.Error(e);
		}
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM