using System.Collections.Generic; using Unity.Netcode; using Unity.Netcode.Components; using UnityEngine; public class PlayerMovement : NetworkTransform { public float Speed = 4.0f; public float RotSpeed = 1.0f; private Rigidbody m_Rigidbody; /// Used by public static Dictionary Players = new Dictionary(); /// /// Make this PlayerMovement-NetworkTransform component /// Owner Authoritative /// protected override bool OnIsServerAuthoritative() { return false; } private bool m_IsTeleporting; public bool IsTeleporting { get { return m_IsTeleporting; } } private float m_TickFrequency; private float m_DelayInputForTeleport; private Quaternion m_PreviousRotation; private RigidbodyInterpolation m_OrginalRigidbodyInterpolation; public void Telporting(Vector3 destination) { if (IsSpawned && IsOwner && !m_IsTeleporting) { m_IsTeleporting = true; // With rigid bodies, if you already know you are using standard // transform interpolation (not NetworkTransform) on the authoritative // side then you need to set it to Kinematic, preserve the current rigid // body interpolation value, and then finally set interpolation to none. m_Rigidbody.isKinematic = true; m_OrginalRigidbodyInterpolation = m_Rigidbody.interpolation; m_Rigidbody.interpolation = RigidbodyInterpolation.None; // We want to provide a few network ticks to pass in time before restoring // the rigid body back to its settings prior to being teleported. m_DelayInputForTeleport = Time.realtimeSinceStartup + (3f * m_TickFrequency); // Since the player-cube is a cube, when colliding with something it could // cause the cube to rotate based on the surface being collided against // and the facing of the cube. This prevents rotation from being changed // due to colliding with a side wall (and then teleported) transform.rotation = m_PreviousRotation; // Now teleport Teleport(destination, transform.rotation, transform.localScale); } } public override void OnNetworkSpawn() { if (IsOwner) { var temp = transform.position; temp.y = 0.5f; transform.position = temp; m_Rigidbody = GetComponent(); m_TickFrequency = 1.0f / NetworkManager.NetworkTickSystem.TickRate; } /// Used by Players[OwnerClientId] = this; base.OnNetworkSpawn(); } public override void OnNetworkDespawn() { if (Players.ContainsKey(OwnerClientId)) { Players.Remove(OwnerClientId); } base.OnNetworkDespawn(); } /// /// LateUpdate is being used to check for the end of /// a player's teleporting cycle. /// private void LateUpdate() { if (!IsSpawned || !IsOwner || !m_IsTeleporting) { return; } if (Time.realtimeSinceStartup >= m_DelayInputForTeleport) { m_IsTeleporting = false; m_Rigidbody.isKinematic = false; m_Rigidbody.interpolation = m_OrginalRigidbodyInterpolation; } } private void FixedUpdate() { if (!IsSpawned || !IsOwner) { return; } else { transform.position = Vector3.Lerp(transform.position, transform.position + Input.GetAxis("Vertical") * Speed * transform.forward, Time.fixedDeltaTime); var rotation = transform.rotation; var euler = rotation.eulerAngles; euler.y += Input.GetAxis("Horizontal") * 90 * RotSpeed * Time.fixedDeltaTime; rotation.eulerAngles = euler; transform.rotation = rotation; /// We store this to handle a collision rotation issue: m_PreviousRotation = transform.rotation; } } }