【UNET自学日志】Part6 更有效率的旋转同步

对于旋转的同步,其主要的思路和运动的同步是一样的,设置一个List,每次角度变化的时候将这个变化的数值存入List当中,当物体旋转的角度和List的第一个数值足够接近的时候,删除List中的第一个数值。值得一提的是,此方法只是改善画面的流畅性,并不能消除延迟所带来的同步问题。

下面是Player_SyncRotation的代码

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

public class Player_SyncRotation : NetworkBehaviour {

    [SyncVar(hook="OnPlayerRotSynced")]private float syncPlayerRotation;
    [SyncVar(hook = "OnCamRotSynced")]private float syncCamRotation;

    [SerializeField]private Transform playerTransform;
    [SerializeField]private Transform camTransform;
    private float lerpRate=20;

    private float lastPlayerRot;
    private float lastCamRot;
    private float threshold = 1;

    private List<float>syncPlayerRotList=new List<float>();
    private List<float>syncCamRotList=new List<float>();
    private float closeEnough = 0.4f;
    [SerializeField]private bool useHistoricalInterpolation;

    void Update()
    {
        LerpRotations();
    }

	void FixedUpdate ()
    {
        TransmitRotations();
	}

    void LerpRotations()
    {
        if (!isLocalPlayer)
        {
            if (useHistoricalInterpolation)
            {
                HistoricalLerping();
            }
            else
            {
                OrdinaryLerping();
            }          
        }
    }

    void OrdinaryLerping()
    {
        LerpPlayerRot(syncPlayerRotation);
        LerpCamRot(syncCamRotation);
    }

    void LerpPlayerRot(float rotAngle)
    {
        Vector3 playerNewRot = new Vector3(0, rotAngle, 0);
        playerTransform.rotation = Quaternion.Lerp(playerTransform.rotation, Quaternion.Euler(playerNewRot), lerpRate * Time.deltaTime);
    }

    void LerpCamRot(float rotAngle)
    {
        Vector3 camNewRot = new Vector3(rotAngle, 0, 0);
        camTransform.localRotation = Quaternion.Lerp(camTransform.localRotation, Quaternion.Euler(camNewRot), lerpRate * Time.deltaTime);
    }

    void HistoricalLerping()
    {
        if (syncPlayerRotList.Count > 0)
        {
            LerpPlayerRot(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)
        {
            LerpCamRot(syncCamRotList[0]);

            if (Mathf.Abs(camTransform.localEulerAngles.x - syncCamRotList[0]) < closeEnough)
            {
                syncCamRotList.RemoveAt(0);
            }

            Debug.Log(syncCamRotList.Count.ToString() + " syncCamRotList Count");
        }
    }

    [Command]
    void CmdProvideRotationToServer(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)
            if(CheckIfBeyondThreshold(playerTransform.localEulerAngles.y,lastPlayerRot)||CheckIfBeyondThreshold(camTransform.localEulerAngles.x,lastCamRot))
            {
                lastPlayerRot = playerTransform.localEulerAngles.y;
                lastCamRot = camTransform.localEulerAngles.x;
                CmdProvideRotationToServer(lastPlayerRot,lastCamRot);
            }
        }
    }

    bool CheckIfBeyondThreshold(float rot1,float rot2)
    {
        if (Mathf.Abs(rot1 - rot2) > threshold)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    [Client]
    void OnPlayerRotSynced(float latestPlayerRot)
    {
        syncPlayerRotation = latestPlayerRot;
        syncPlayerRotList.Add(syncPlayerRotation);
    }

    [Client]
    void OnCamRotSynced(float latestCamRot)
    {
        syncCamRotation = lastCamRot;
        syncCamRotList.Add(syncCamRotation);
    }
}

List中保存的是一个Float,当Player旋转的时候,在父物体中只是改变其Y轴,在子物体中只是改变其X轴,故可以用float来记录。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在训练Unet网络时,学习率的设置是一个重要的超参数,它可以影响模型的收敛速度和性能。以下是几种常用的学习率设置方法: 1. 固定学习率:将学习率设置为一个固定的常数值。这是最简单的设置方式,适用于训练过程中学习率无需调整的情况。例如: ```python from keras.optimizers import Adam lr = 0.001 # 设置学习率 optimizer = Adam(lr=lr) model.compile(optimizer=optimizer, loss='binary_crossentropy') ``` 2. 学习率衰减:随着训练的进行,逐渐降低学习率。可以根据训练的轮数或者验证集上的性能来进行学习率的调整。以下是使用指数衰减方式进行学习率衰减的示例: ```python from keras.optimizers import Adam from keras.callbacks import LearningRateScheduler def lr_decay(epoch): initial_lr = 0.001 # 初始学习率 decay_rate = 0.1 # 衰减率 decay_step = 10 # 衰减步数 lr = initial_lr * (decay_rate ** (epoch // decay_step)) return lr optimizer = Adam() model.compile(optimizer=optimizer, loss='binary_crossentropy') lr_scheduler = LearningRateScheduler(lr_decay) model.fit(X_train, y_train, callbacks=[lr_scheduler]) ``` 3. 动态调整学习率:根据训练过程中的某些指标来动态调整学习率。常用的方法包括基于验证集性能的提升情况、基于损失函数的化等。以下是使用ReduceLROnPlateau回调函数动态调整学习率的示例: ```python from keras.optimizers import Adam from keras.callbacks import ReduceLROnPlateau optimizer = Adam() model.compile(optimizer=optimizer, loss='binary_crossentropy') lr_scheduler = ReduceLROnPlateau(factor=0.1, patience=3, min_lr=0.00001) model.fit(X_train, y_train, callbacks=[lr_scheduler]) ``` 以上是几种常用的学习率设置方法,具体选择哪种方式取决于数据集、模型和训练任务的特点。根据实际情况进行调试和优化,找到最合适的学习率设置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值