Newer
Older
Simple-Multiplayer-Unity3D / Assets / Scripts / LobbyPlayer.cs
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class LobbyPlayer : MonoBehaviour
{
    public PlayerData playerData;

    //DisplayPlayerWorldUI
    [SerializeField] private TextMeshPro tmp;

    [Header("Movement Settings")]
    private Vector3 nextPosition;
    private Vector3 previousPosition;
    public float interpolationSpeed = 10f;
    private Quaternion nextRotation;

    [Header("Animation Settings")]
    [SerializeField] private float positionDiffThreshold = 0.005f;
    [SerializeField] private float movingSmoothing = 8f;
    [SerializeField] private float stoppingSmoothing = 25f;
    [SerializeField] private float stopDeadzone = 0.01f;

    private Vector3 _smoothedVelocity;
    private float _lastMoveTime;


    //Components
    [SerializeField] private Animator animator;

    //Properties
    public Vector3 NextPosition {
        get => nextPosition;
        set => nextPosition = value;
    }

    public Quaternion NextRotation
    {
        get => nextRotation;
        set => nextRotation = value;
    }

    //Components
    Rigidbody rb;

    public void SetPlayerData(PlayerData playerData) => this.playerData = playerData;


    private void Awake()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Start()
    {
        tmp.text = playerData.username;
    }

    void Update()
    {
        // Calculate movement difference
        Vector3 positionDiff = transform.position - previousPosition;
        float distanceMoved = positionDiff.magnitude;
        previousPosition = transform.position;

        // Movement detection with hysteresis
        bool isMoving = distanceMoved > positionDiffThreshold;
        if (isMoving) _lastMoveTime = Time.time;

        // Force stop if no recent movement (handles network latency)
        bool shouldStop = (Time.time - _lastMoveTime) > 0.1f;

        // Calculate velocity
        Vector3 currentVelocity = (isMoving && !shouldStop) ?
            positionDiff / Time.deltaTime :
            Vector3.zero;

        // Convert to local space
        Vector3 localVelocity = transform.InverseTransformDirection(currentVelocity);

        // Apply aggressive stopping when needed
        if (shouldStop)
        {
            localVelocity = Vector3.zero;
            _smoothedVelocity = Vector3.Lerp(_smoothedVelocity, localVelocity, Time.deltaTime * stoppingSmoothing * 2f);
        }
        else
        {
            // Normal smoothing
            float smoothing = isMoving ? movingSmoothing : stoppingSmoothing;
            _smoothedVelocity = Vector3.Lerp(_smoothedVelocity, localVelocity, Time.deltaTime * smoothing);
        }

        // Apply deadzone for stopping
        if (_smoothedVelocity.magnitude < stopDeadzone && !isMoving)
        {
            _smoothedVelocity = Vector3.zero;
        }

        // Always update animator (but with properly smoothed values)
        animator.SetFloat("velocityX", _smoothedVelocity.x);
        animator.SetFloat("velocityY", _smoothedVelocity.z);
    }

    void FixedUpdate()
    {
        // Stable interpolation with velocity consideration
        float t = Time.fixedDeltaTime * interpolationSpeed;
        Vector3 newPos = Vector3.Lerp(rb.position, nextPosition, t);
        rb.MovePosition(newPos);

        // Rotation interpolation - use the full yaw rotation
        Quaternion newRot = Quaternion.Lerp(rb.rotation, nextRotation, t);
        rb.MoveRotation(newRot);
    }

    private void OnCollisionEnter(Collision collision)
    {

        if (collision.gameObject.CompareTag("Player"))
        {
            Physics.IgnoreCollision(GetComponent<Collider>(), collision.collider, true);
        }
    }

}