Unity-使用Lerp去平滑同步位置

文章目录[x]
  1. 0.1:前言
  2. 0.2:功能描述
  3. 0.3:代码实现
  4. 0.4:整合动画

前言

在做厂区可视化项目的时候,我们会接入第三方的定位系统,例如UWB定位或GPS定位,但是他们的系统不像做游戏时服务器高频率的给客户端发送其他玩家角色的位置。他们一般发送频率为1秒发送1次,在展示人员位置的时候如果直接用接收到的位置赋值到transform.position就会出现人员模型是瞬移的,这种展示效果不是很理想,所以做了一个平滑移动的功能。

功能描述

1、收到位置信息后立即朝目标位置移动,速度为当前位置到目标的距离/发送位置消息的间隔。

2、可以控制角色是否朝向目标。

3、可以开启预测位置,当出现网络延迟的时候,角色会根据当前速度继续向前移动(预测时候速度可以减小,防止移动过多)。

代码实现

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

public class SmoothPosition : MonoBehaviour
{
    private bool firstReceive = true;

    private Vector3 lerpStartPos;
    private Vector3 lerpEndPos;
    private Quaternion lerpStartRot = Quaternion.identity;
    private Quaternion lerpEndRot = Quaternion.identity;
    private float lerpTime = 0;
    public float receiveInterval=1;//接受间隔 默认1秒接受一次
    public float maxSnapDistance = 3f;//最大的校准距离:当接收到的位置与现在距离过大时,直接瞬移过去,以防止误差过大。
    public bool usePrediction;//使用预测:如果没有准时收到下一个位置,则按当前方向继续移动
    public bool useLookTarget;//使用面朝目标

    private void Update()
    {
        #region 使用鼠标点击模拟接收消息
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit hitInfo;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hitInfo))
            {
                CommandMove(hitInfo.point);
            }
        }
        #endregion
        if (lerpTime / receiveInterval > 1)
        {
            lerpTime += Time.deltaTime / 2;//预测时速度减弱
        }
        else
        {
            lerpTime += Time.deltaTime;
        }
        if(usePrediction)
        {
            
            transform.position = Vector3.LerpUnclamped(lerpStartPos, lerpEndPos, lerpTime/receiveInterval);
        }
        else
        {
            transform.position = Vector3.Lerp(lerpStartPos, lerpEndPos, lerpTime / receiveInterval);
        }
        if(useLookTarget)
        {
            transform.rotation = Quaternion.Lerp(lerpStartRot, lerpEndRot, lerpTime / receiveInterval * 5);//快速旋转到目标朝向
        }
    }
        

    private void CommandMove(Vector3 targetPos)
    {
        lerpStartPos = transform.position;
        lerpEndPos = targetPos;
        lerpStartRot = transform.rotation;
        lerpEndRot = Quaternion.LookRotation(lerpEndPos - lerpStartPos, Vector3.up);
        lerpTime = 0;
        if(firstReceive)
        {
            lerpStartPos = lerpEndPos;
            lerpTime = 1;
            firstReceive = false;
        }
    }
}

整合动画

上面实现了同步角色位置和旋转,下面结合Animator实现静止、走、跑的动画。模型动画使用的都是Unity官方提供的standard asset里面的内容。

点赞

发表回复

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像