日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

unity-unet-多人在线同步问题解决方案

發(fā)布時(shí)間:2023/12/20 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unity-unet-多人在线同步问题解决方案 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  • 看了些文章,大牛對(duì)同問(wèn)題的解決方案
  • 傳送門(mén):Fast-Paced Multiplayer

文中大體的思路:

  • A玩家 移動(dòng)時(shí),本機(jī)自行移動(dòng),并發(fā)送移動(dòng)指令給服務(wù)端,假設(shè)移動(dòng)是成功的,服務(wù)端同步其他客戶(hù)端 B玩家,B玩家 中用一個(gè)隊(duì)列 Queue 來(lái)裝服務(wù)端來(lái)的移動(dòng)指令,然后客戶(hù)端在updata中做插值 (lerp ) 處理,這樣 A玩家 在 B玩家客戶(hù)端中移動(dòng)起來(lái)就比較平滑

  • 如果 A玩家 移動(dòng)很頻繁,B玩家 中的 指令隊(duì)列 Queue 會(huì)堆積的很大,這里可以做個(gè)優(yōu)化,就是當(dāng) Queuesize 超過(guò)某個(gè)臨界值 (threshold)時(shí),加快插值(lerp)的速率

  • A玩家 移動(dòng)時(shí),本機(jī)自行移動(dòng) 并保留一份此次移動(dòng)的 副本 (copy)到一個(gè) 隊(duì)列 中,并發(fā)送移動(dòng)指令給服務(wù)端,如果服務(wù)端判定移動(dòng)是失敗的(比如穿墻之類(lèi)的),則服務(wù)端下發(fā)指令給 A玩家 修復(fù)此次移動(dòng)的位置,然后 隊(duì)列 中移除此次移動(dòng)的副本

  • 關(guān)于攻擊時(shí)的同步,客戶(hù)端A 中自行播放攻擊動(dòng)作并上行給服務(wù)的此次攻擊的指令,服務(wù)端同步其他 客戶(hù)端B 播放攻擊動(dòng)作,同時(shí)同步給所有客戶(hù)端(客戶(hù)端A和B)扣血指令,為防止客戶(hù)端作弊必須有服務(wù)端運(yùn)行計(jì)算實(shí)際扣血量。


  • 下面是部分關(guān)于位置同步的代碼

    using UnityEngine; using System.Collections; using UnityEngine.Networking; using System.Collections.Generic;/// <summary> /// 可以通過(guò) /// 1. 減少發(fā)包率(意思就是 增大 sendInterval 發(fā)包間隔) /// 2. 增大 closeEnough 距離 /// 3. 增大 normalLerpRate、fasterLerpRate 插值速率 /// </summary>[NetworkSettings(channel = 0, sendInterval = 0.1f)] public class SmoothMove : NetworkBehaviour {[SyncVar(hook = "SyncPostionsValues")]private Vector3 syncPos; //同步變量[SerializeField]Transform myTransform; //SerializeField用于inspector中顯示非public變量private float lerpRate;private float normalLerpRate = 16.0f;private float fasterLerpRate = 27.0f;private Vector3 lastPos;private float threshold = 0.5f;private List<Vector3> syncPosList = new List<Vector3>();[SerializeField]private bool useHistoriicalLerping = false; //是否啟用平滑插值的開(kāi)關(guān),直接在 inspector 中設(shè)置private float closeEnough = 0.11f;public void Start(){lerpRate = normalLerpRate;}public void Update(){LerpPosition(); //因?yàn)榉椒ɡ昧薚ime.deltaTime,所以只能在 Updata中調(diào)用}public void FixedUpdate() //1. server 和 client 都執(zhí)行FixedUpdate{TransmitPosition(); //2. 因?yàn)槭?ClientCallback,所以只有客戶(hù)端調(diào)用}void LerpPosition(){if (!isLocalPlayer) //5. 只有非本機(jī)玩家才進(jìn)行插值移動(dòng)到最新的 syncPos 位置{if (useHistoriicalLerping) //更加平滑{HistoryLerping();}else{OrdinaryLerping();}}}[Command]void CmdProvidePositionToServer(Vector3 pos){syncPos = pos; //4. 服務(wù)端收到信息同步給所有客戶(hù)端的該對(duì)象的syncPos變量}[Client]void TransmitPosition(){if (isLocalPlayer && Vector3.Distance(myTransform.position, lastPos) > threshold) //3. 只用本機(jī)玩家才提交位置信息到server上{CmdProvidePositionToServer(myTransform.position);}}[Client]public void SyncPostionsValues(Vector3 lastPos){syncPos = lastPos;syncPosList.Add(syncPos); //將所有服務(wù)端同步過(guò)來(lái)的 pos 全都保存在隊(duì)列中}void OrdinaryLerping() //普通插值,有卡頓現(xiàn)象{myTransform.position = Vector3.Lerp(myTransform.position, syncPos, Time.deltaTime * lerpRate);}void HistoryLerping() //平滑插值{if (syncPosList.Count > 0){//取出隊(duì)列中的第一個(gè)設(shè)為插值的目標(biāo)myTransform.position = Vector3.Lerp(myTransform.position, syncPosList[0], Time.deltaTime * lerpRate);//位置足夠接近,從隊(duì)列中移除第一個(gè),緊接著就是第二個(gè)if (Vector3.Distance(myTransform.position, syncPosList[0]) < closeEnough){syncPosList.RemoveAt(0);}//如果同步隊(duì)列過(guò)大,加快插值速率,使其更快到達(dá)目標(biāo)點(diǎn)if (syncPosList.Count > 10){lerpRate = fasterLerpRate;}else{lerpRate = normalLerpRate;}Debug.LogFormat("--- syncPosList, count:{0}", syncPosList.Count);}} }

    總結(jié)

    以上是生活随笔為你收集整理的unity-unet-多人在线同步问题解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。