Unity(C#)初心者・入門者向けチュートリアル ひよこのたまご

AndroidやiOS向けアプリを簡単に作れるゲーム開発環境Unity(ユニティ)の使い方を、チュートリアル方式で一緒に学びましょう!

【Unity9】UNETのlatency(遅延時間)を改善する【UNET4】

Unity5.1.1p3 Personal(2015年7月)

前回の続きです〜

今回扱うlatencyは、データを要求してからこちらに届くまでの遅延時間のことを言います〜
part4はこのlatencyの改善についてです〜



UNET Part 4 - Latency Simulation! - YouTube

【目標】latency(遅延時間)を改善する

①FixedUpdate→Update

動画によると、ちょっとした書き間違いがあったようです〜

前回までに作成したPlayer_SyncPositionとPlayer_SyncRotationで、Time.deltaTimeが使われているメソッドをFixedUpdateメソッドから呼び出していたのですが、これがまずかったようです〜


Time.deltaTime: 2フレーム間で経過する時間。

Updateメソッド: 毎フレーム呼び出されるメソッド。呼び出し頻度はマシンスペックに依存する。

FixedUpdateメソッド: 固定された回数だけ呼び出されるメソッド。
呼び出し頻度はEdit > Project Settings > TimeにあるFixed Timestepで設定。デフォルトだと0.02。


UpdateメソッドやFixedUpdateの呼び出し頻度=Time.deltaTimeの値なのですが、今のところFixedUpdateから呼び出されたメソッド内にTime.deltaTimeがあるので、必ず0.02になってしまっています〜

	void LerpPosition ()
	{
		if (!isLocalPlayer) {
			myTransform.position = Vector3.Lerp(myTransform.position, syncPos, Time.deltaTime * lerpRate);
//********** 開始 **********//
			Debug.Log(Time.deltaTime.ToString());
//********** 終了 **********//
		}
	}

Player_SyncPosition.cs


f:id:hiyotama:20150707143241p:plain
FixedUpdateメソッドのTime.deltaTime


この0.02は自分が使っているマシンには最適かもしれないですが、ネットワーク越しの他の人が使っているマシンにとっては遅いかもしれないし、早いかもしれないです〜
なので、Time.deltaTimeが書かれているLerpRotationsメソッドはFixedUpdateメソッドからではなく、Updateメソッドから呼び出すように修正します〜

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Player_SyncPosition : NetworkBehaviour {
	
	[SyncVar]
	private Vector3 syncPos;
	[SerializeField] Transform myTransform;
	[SerializeField] float lerpRate = 15;

	private Vector3 lastPos;
	private float threshold = 0.5f;

//********** 開始 **********//
	//LerpPositionメソッドの呼び出しをFixedUpdateから移動させる
	void Update ()
	{
		LerpPosition();
	}
//********** 終了 **********//

	void FixedUpdate ()
	{
		TransmitPosition(); 
	}
	
	void LerpPosition ()
	{
		if (!isLocalPlayer) {
			myTransform.position = Vector3.Lerp(myTransform.position, syncPos, Time.deltaTime * lerpRate);
//********** 開始 **********//
			Debug.Log(Time.deltaTime.ToString());
//********** 終了 **********//
		}
	}

	[Command]
	void CmdProvidePositionToServer (Vector3 pos)
	{
		syncPos = pos;
//		Debug.Log("Command");
	}
	
	[ClientCallback]
	void TransmitPosition ()
	{
		if (isLocalPlayer && Vector3.Distance(myTransform.position, lastPos) > threshold) {
			CmdProvidePositionToServer(myTransform.position);
			lastPos = myTransform.position;
		}
	}
}

Player_SyncPosition.cs


f:id:hiyotama:20150707143151p:plain
UpdateメソッドのTime.deltaTime


これでマシンスペックによって同期がうまくいかないことの対策は完了です〜

②Network Simulator設定

続いてネットワークを経由したタイムラグの対策を行います〜


まずはネットワークをシミュレートできるNetwork Simulatorを使ってみます〜
MenuシーンにあるNetworkManagerのInspectorビューにある、Use Network Simulatorにチェックを入れて下さい〜
動画では150ミリ秒(0.15秒)の遅延と、1%のパケット消失を設定しているので、同じ設定にします〜
遅延に関しては、サーバーへの送信に0.15秒、サーバーからの受信に0.15秒の計0.3秒の遅延となります〜


f:id:hiyotama:20150707161521p:plain
Network Simulator設定


それではホストとクライアントに分けて、Network Simulatorが有効な状態でのテストをしてみましょう〜
Network Simulatorが有効だとホストになれないので、ビルド側をホストに、開発画面側をクライアントにして下さい〜


f:id:hiyotama:20150707162111p:plain
開発機側はクライアントで接続


実行すると、遅延が発生してカクカクした動きになっていることが確認できます〜
遅延とパケット消失のせいで補間が間に合わなくなり、ネットワークの渋滞が起こったためです〜


このタイミングでAdvanced Configurationという欄の設定も解説していますが、今回はあまり関係がないようです〜


f:id:hiyotama:20150707164359p:plain
Advanced Configuration


Channel0のところがデフォルトでReliable Sequencedとなっています〜信頼できる順番という意味です〜

Reliable Sequenced状態だと、データの変更を同期する際にパケットを消失してしまった時、もう一度パケットが送られてくるまで待機する
Unreliable状態だと、パケットを消失してもそのまま待たずにデータの変更を同期する


みたいな説明をしている気がするのですが、まぁあまり気にしないで進みます〜


長くなってきたので、今回はここまでです〜

ありがとうございました〜


【Unity9】UNETでマルチプレイヤーなオンラインゲーム開発【UNET1】
【Unity9】UNETでプレイヤーの動きを補間し、なめらかな動きを実現する【UNET1-2】
【Unity9】UNETでネットワーク越しに傾き(Rotation)を同期させる【UNET2】
【Unity9】UNETでオンライン開始時のプレイヤー生成位置を変更する【UNET2-2】
【Unity9】UNETのネットワークトラフィックを軽減し、効率化する【UNET3】
【Unity9】UNETのlatency(遅延時間)を改善する【UNET4】
【Unity9】UNETのlatency(遅延時間)を表示して、ちょっとだけ改善する【UNET4-2】
【Unity9】UNETのSyncVarのhookの使用例と、前時代の同期方法【UNET5】
【Unity9】UNETを使ってRotationを同期させる【UNET6】
【Unity9】UNETで各プレイヤーにPlayerIDを設定する【UNET7】
【Unity9】UNETで敵プレイヤーにダメージを与える!【UNET8】
【Unity9】UNETでHPを画面に表示し、Playerへダメージを与える【UNET9】
【Unity9】UNETでHPが0以下になった時、Playerを破壊する!【UNET10】
【Unity9】UNETで死んだPlayerを生き返らせる!【UNET11】
【Unity9】UNETでゾンビAIを出現させる!【UNET12】
【Unity9】UNETでゾンビ生成時にユニークなIDを付ける!【UNET13】
【Unity9】UNETでゾンビを撃つ!【UNET14】
【Unity9】UNETでゾンビに攻撃させる!【UNET15】
【Unity9】UNETでゾンビの動きをスムーズにシンクロさせる!【UNET16】
【Unity9】UNETでゾンビ発生地点を増やす【UNET17】
【Unity9】UNETで発生したバグを取り除く【UNET18】
【Unity9】Unity MultiPlayerを使ってネットワーク越しにマッチメイキング!【UNET19】
【Unity9】GUIを改善して、Network Managerを見やすくする!【UNET20】
【Unity9】表示したGUI(Network Manager)を機能させる!【UNET20-2】
【Unity9】UNETでAnimationを同期させる!【UNET21】