ãUnity9ãUNETã使ã£ã¦RotationãåæããããUNET6ã
Unity5.1.1p3 Personal(2015å¹´7æ)
前回の続きã§ãã
ååã¾ã§ã§ä½ç½®æ å ±ããUNETã使ã£ãåææ¹æ³ã¨åæ代ã®åææ¹æ³ã使ã£ãææ³ã®ï¼ã¤ãå®è£ ãã¾ããã
ä»åã¯ä½ç½®æ å ±ã®æã¨å ¨ãåãæé ã§ãUNETã使ã£ãåææ¹æ³ã¨åæ代ã®åææ¹æ³ãè§åº¦ã«ãé©ç¨ãã¦ããã¾ãã
UNET Part 6 - Efficient Rotation Syncing - YouTube
ãç®æ¨ãUNETã使ã£ã¦Rotationã®åæããã
â ã¹ã¯ãªããã®ä¿®æ£
ä½ç½®æ
å ±ã®æã¨å
¨ãåãå½¢ã§ãè§åº¦ã®åææ¹æ³ãä¿®æ£ãã¦ããã¾ãã以ä¸ã½ã¼ã¹ã§ãã
using UnityEngine; using UnityEngine.Networking; using System.Collections; //********** éå§ **********// //Listã使ãããã®ã©ã¤ãã©ãª using System.Collections.Generic; //********** çµäº **********// public class Player_SyncRotation : NetworkBehaviour { //********** éå§ **********// //Quaternionåããfloatåã«ä¿®æ£ //hook: SyncVarå¤æ°ãå¤æ´ãããæã«ãSyncVarå¤æ°ãå¼æ°ã«ãã¦æå®ããã¡ã½ãããå®è¡ [SyncVar (hook = "OnPlayerRotSynced")] private float syncPlayerRotation; [SyncVar (hook = "OnCamRotSynced")] private float syncCamRotation; //********** çµäº **********// [SerializeField] private Transform playerTransform; [SerializeField] private Transform camTransform; //********** éå§ **********// //Serialize Fieldãåé¤ private float lerpRate = 17; //Quaternionåããfloatå(ãªã¤ã©ã¼è§ã360度ã®ãã¤ã)ã«å¤æ´ private float lastPlayerRot; private float lastCamRot; //ãããå¤ã1ã«å¤æ´ private float threshold = 1; //è§åº¦ä¿åç¨ã®List private List<float> syncPlayerRotList = new List<float>(); private List<float> syncCamRotList = new List<float>(); //HistoricalInterpolationã§è§åº¦ã®å¤å®ã«ä½¿ç¨ private float closeEnough = 0.4f; //åæ代ã®è§åº¦åæã¡ã½ããã使ãã [SerializeField] private bool useHistoricalInterpolation; //********** çµäº **********// void Update () { LerpRotations(); } void FixedUpdate () { TransmitRotations(); } void LerpRotations () { if (!isLocalPlayer) { //********** éå§ **********// // playerTransform.rotation = Quaternion.Lerp (playerTransform.rotation, // syncPlayerRotation, Time.deltaTime * lerpRate); // camTransform.rotation = Quaternion.Lerp (camTransform.rotation, // syncCamRotation, Time.deltaTime * lerpRate); if (useHistoricalInterpolation) { //åæ代ã®è§åº¦åæå¤å® HistoricalInterpolation(); } else { //UNETã使ç¨ããè§åº¦åæå¤å® OrdinaryLerping(); } //********** çµäº **********// } } //********** éå§ **********// //åæ代ã®è§åº¦åæå¤å® void HistoricalInterpolation () { //Listã1ã¤ã§ããã£ãã if (syncPlayerRotList.Count > 0) { LerpPlayerRotation (syncPlayerRotList[0]); if (Mathf.Abs (playerTransform.localEulerAngles.y - syncPlayerRotList[0]) < closeEnough) { syncPlayerRotList.RemoveAt(0); } Debug.Log(syncPlayerRotList.Count.ToString() + " syncPlayerRotList Count"); } if (syncCamRotList.Count > 0) { LerpCamRotation (syncCamRotList[0]); if (Mathf.Abs (camTransform.localEulerAngles.x - syncCamRotList[0]) < closeEnough) { syncCamRotList.RemoveAt(0); } Debug.Log(syncCamRotList.Count.ToString() + " syncCamRotList Count"); } } void OrdinaryLerping() { LerpPlayerRotation(syncPlayerRotation); LerpCamRotation(syncCamRotation); } //ãã¬ã¤ã¤ã¼ã®ç¾å¨è§åº¦ãè£é void LerpPlayerRotation(float rotAngle){ //å¼æ°ã®ãªã¤ã©ã¼è§ããVector3ã®å½¢ã§ä¿å Vector3 playerNewRot = new Vector3(0, rotAngle, 0); //Lerp: ç¾å¨ã®è§åº¦ã¨åãåã£ãè§åº¦ã®è£éå¤ãæ±ãã //Euler: ãªã¤ã©ã¼è§ãQuaternionè§ã«å¤æãã¦ããã playerTransform.rotation = Quaternion.Lerp(playerTransform.rotation, Quaternion.Euler(playerNewRot), lerpRate * Time.deltaTime); } //ã«ã¡ã©ã®ç¾å¨è§åº¦ãè£é void LerpCamRotation(float rotAngle){ Vector3 camNewRot = new Vector3(rotAngle, 0, 0); //ã«ã¡ã©ã¯åãªãã¸ã§ã¯ãã®ããã親ãªãã¸ã§ã¯ãã®åããç¶æ¿ããlocalRotationã使ã camTransform.localRotation = Quaternion.Lerp(camTransform.localRotation, Quaternion.Euler(camNewRot), lerpRate * Time.deltaTime); } //********** çµäº **********// [Command] //********** éå§ **********// //å¼æ°ãfloatå(ãªã¤ã©ã¼è§)ã«ä¿®æ£ void CmdProvideRotationsToServer (float playerRot, float camRot) { syncPlayerRotation = playerRot; syncCamRotation = camRot; } //********** çµäº **********// [Client] void TransmitRotations () { if (isLocalPlayer) { //********** éå§ **********// // if (Quaternion.Angle (playerTransform.rotation, lastPlayerRot) > threshold || // Quaternion.Angle (camTransform.rotation, lastCamRot) > threshold) { //localEulerAngles: Quaternionè§ããªã¤ã©ã¼è§(æ®éã®360度)ã§å転éã表ã if (CheckIfBeyondThreshold(playerTransform.localEulerAngles.y, lastPlayerRot) || CheckIfBeyondThreshold(camTransform.localEulerAngles.x, lastCamRot)){ //lastPlayerRotã¨lastCamRotãç¾å¨è§åº¦ã«æ´æ° lastPlayerRot = playerTransform.localEulerAngles.y; lastCamRot = camTransform.localEulerAngles.x; //ç¾å¨è§åº¦ã«æ´æ°ããlastPlayerRotã¨lastCamRotã§ã¡ã½ããå®è¡ CmdProvideRotationsToServer (lastPlayerRot, lastCamRot); //********** çµäº **********// } } } //********** éå§ **********// //ç¾å¨è§åº¦ã¨åãã¬ã¼ã ã®ãªã¤ã©ã¼è§ãæ¯è¼ããthreshold(1度)以ä¸éãããã£ããtrueãè¿ã bool CheckIfBeyondThreshold (float rot1, float rot2) { //Mathf.Abs: 絶対å¤åå¾ if (Mathf.Abs (rot1 - rot2) > threshold) { return true; } else { return false; } } //syncPlayerRotationå¤æ°ãå¤æ´ãããæã«å®è¡(hook) //Clientã®ã¿å®è¡ [Client] void OnPlayerRotSynced(float latestPlayerRot) { //hookã¯èªåã§åæããå¿ è¦ããã syncPlayerRotation = latestPlayerRot; //Listã«ç»é² syncPlayerRotList.Add(syncPlayerRotation); } //syncCamRotationå¤æ°ãå¤æ´ãããæå®è¡(hook) //Clientã®ã¿å®è¡ [Client] void OnCamRotSynced(float latestCamRot) { //hookã¯èªåã§åæããå¿ è¦ããã syncCamRotation = latestCamRot; //Listã«ç»é² syncCamRotList.Add(syncCamRotation); } //********** çµäº **********// }
Player_SyncRotation.cs
大ããå¤ãã£ãç¹ã¨ãã¦ã以åã¾ã§ã¯Quaternionåã§è§åº¦ã®èª¿ç¯ããã¦ãã¾ããããããããå ¨ã¦ãªã¤ã©ã¼è§(floatåã360度ã§ä¸å¨ã®ãã¤)ã«å¤æ´ãã¦ãã¾ãã
ã¾ã注æç¹ã¨ãã¦ãPlayerã¯y軸ã®å¤ã®ã¿ãå¤æ´ããå転ããCameraã¯x軸ã®å¤ã®ã¿ãå¤æ´ããå転ãããã¨ãããããã¾ãã
ããã§ã¯ã¹ã¯ãªãããã²ã¨ã¤ãã¤è¦ã¦ããã¾ãããã
ã¾ãã¯FixedUpdateã¡ã½ããããè¦ã¦ããã¾ãã
FixedUpdateã¡ã½ããã§TransmitRotationsã¡ã½ãããå®è¡ãããç¾å¨è§åº¦ã¨åãã¬ã¼ã ã®è§åº¦ã®å·®ãthresholdã§æå®ãã以ä¸ã®éãããã£ãããCmdProvideRotationsToServerãå®è¡ãã¦SyncVarå¤æ°ãå¤æ´ãã¾ãã
SyncVarå¤æ°ãå¤æ´ãããã¨ãhookãä½åãå ¨ã¯ã©ã¤ã¢ã³ãã®OnPlayerRotSyncedã¡ã½ããã¨OnCamRotSyncedã¡ã½ãããå®è¡ãããææ°ã®è§åº¦ãæ´æ°ããã¾ããã¾ããåæã«Listã«ãææ°ã®è§åº¦ãç»é²ããã¾ãã
ç¶ãã¦Updateã¡ã½ãããè¦ã¦ããã¾ãã
Updateã¡ã½ããã§LerpRotationsã¡ã½ãããå®è¡ãããã¨ãuseHistoricalInterpolationãtrueã®æã«ã¯HistoricalInterpolationã¡ã½ããããfalseã®æã«ã¯OrdinaryLerpingãå®è¡ããã¾ãã
HistoricalInterpolationã¡ã½ããã§ã¯Listã1ã¤ä»¥ä¸ããæãListå é ã®è§åº¦ãå¼æ°ã«ãã¦è§åº¦è£éç¨ã®ã¡ã½ãããå®è¡ããã¾ãã
OrdinaryLerpingã¡ã½ããã§ã¯SyncVarå¤æ°ãå¼æ°ã«ãè§åº¦è£éç¨ã®ã¡ã½ãããå®è¡ããã¾ãã
è§åº¦ä¿ç®¡ç¨ã®ã¡ã½ããï¼LerpPlayerRotationã»LerpCamRotationï¼ã§ã¯ãæå®ããè§åº¦ãVector3åã«ããLerpã¡ã½ããã使ã£ã¦ç¾å¨è§åº¦ãæ´æ°ãã¦ãã¾ãã
ã²ã¼ã ãå®è¡ããã¨ããã¬ã¤ã¤ã¼ã®è§åº¦ãåæã§ãã¦ãããã¨ã確èªã§ãã¾ãã
åæ確èª
ä»åã¯ããã¾ã§ã§ãã
ãããã¨ããããã¾ããã
ã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ã