Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
ysun60's avatar
ysun60
Honored Guest
2 years ago

How do I integrate teleportation prefab with Netcode

I'm doing a multiplayer project using Unity Netcode. I'm using the LocomotionControllerInteractorGroup prefab to handle the teleportation, and there is a script from the SDK called PlayerLocomotor that changes the player position. Based on the Netcode tutorial, I should handle movement through NetworkBehavior rather than MonoBehavior, so I duplicated the script and changed it to a NetworkBehavior script, but the modified one is not functioning at all.  I attached the modified script below. Could someone give me some hits about how to integrate the locomotion prefab into the NetworkBehavior, please?

 

 

 

 

 

using System;
using System.Collections;
using System.Collections.Generic;
using Oculus.Interaction;
using Oculus.Interaction.Locomotion;
using Unity.Netcode;
using UnityEngine;


    public class RPCPlayer : NetworkBehaviour, ILocomotionEventHandler
    {
        // Start is called before the first frame update
         
        [SerializeField]
        private Transform _playerOrigin;
        [SerializeField]
        private Transform _playerHead;

        private Action<LocomotionEvent, Pose> _whenLocomotionEventHandled = delegate { };
        public event Action<LocomotionEvent, Pose> WhenLocomotionEventHandled
        {
            add
            {
                _whenLocomotionEventHandled += value;
            }
            remove
            {
                _whenLocomotionEventHandled -= value;
            }
        }

        protected bool _started;

        private Queue<LocomotionEvent> _deferredEvent = new Queue<LocomotionEvent>();

        protected virtual void Start()
        {
            this.BeginStart(ref _started);
            this.AssertField(_playerOrigin, nameof(_playerOrigin));
            this.AssertField(_playerHead, nameof(_playerHead));

            this.EndStart(ref _started);
        }

        private void OnEnable()
        {
            if (_started)
            {
                //this.RegisterEndOfFrameCallback(MovePlayer);
                //It's not available to the NetworkBehavior 
                MovePlayer();
            }
        }

        private void OnDisable()
        {
            if (_started)
            {
                _deferredEvent.Clear();
                //this.UnregisterEndOfFrameCallback();
            }
        }

        public void HandleLocomotionEvent(LocomotionEvent locomotionEvent)
        {
            _deferredEvent.Enqueue(locomotionEvent);
        }
        
        
        //[ServerRpc (RequireOwnership = false)]
        private void MovePlayer()
        {
            while (_deferredEvent.Count > 0)
            {
                LocomotionEvent locomotionEvent = _deferredEvent.Dequeue();
                Pose originalPose = _playerOrigin.GetPose();
                MovePlayer(locomotionEvent.Pose.position, locomotionEvent.Translation);
                RotatePlayer(locomotionEvent.Pose.rotation, locomotionEvent.Rotation);
                Pose delta = PoseUtils.Delta(originalPose, _playerOrigin.GetPose());
                _whenLocomotionEventHandled.Invoke(locomotionEvent, delta);
            }
        }

        private void MovePlayer(Vector3 targetPosition, LocomotionEvent.TranslationType translationMode)
        {
            if (translationMode == LocomotionEvent.TranslationType.None)
            {
                return;
            }
            if (translationMode == LocomotionEvent.TranslationType.Absolute)
            {
                Vector3 positionOffset = _playerOrigin.position - _playerHead.position;
                positionOffset.y = 0f;
                _playerOrigin.position = targetPosition + positionOffset;
            }
            else if (translationMode == LocomotionEvent.TranslationType.AbsoluteEyeLevel)
            {
                Vector3 positionOffset = _playerOrigin.position - _playerHead.position;
                _playerOrigin.position = targetPosition + positionOffset;
            }
            else if (translationMode == LocomotionEvent.TranslationType.Relative)
            {
                _playerOrigin.position = _playerOrigin.position + targetPosition;
            }
            else if (translationMode == LocomotionEvent.TranslationType.Velocity)
            {
                _playerOrigin.position = _playerOrigin.position + targetPosition * Time.deltaTime;
            }
        }

        private void RotatePlayer(Quaternion targetRotation, LocomotionEvent.RotationType rotationMode)
        {
            if (rotationMode == LocomotionEvent.RotationType.None)
            {
                return;
            }
            Vector3 originalHeadPosition = _playerHead.position;
            if (rotationMode == LocomotionEvent.RotationType.Absolute)
            {
                Vector3 headForward = Vector3.ProjectOnPlane(_playerHead.forward, _playerOrigin.up).normalized;
                Quaternion headFlatRotation = Quaternion.LookRotation(headForward, _playerOrigin.up);
                Quaternion rotationOffset = Quaternion.Inverse(_playerOrigin.rotation) * headFlatRotation;
                _playerOrigin.rotation = Quaternion.Inverse(rotationOffset) * targetRotation;
            }
            else if (rotationMode == LocomotionEvent.RotationType.Relative)
            {
                _playerOrigin.rotation = targetRotation * _playerOrigin.rotation;
            }
            else if (rotationMode == LocomotionEvent.RotationType.Velocity)
            {
                targetRotation.ToAngleAxis(out float angle, out Vector3 axis);
                angle *= Time.deltaTime;

                _playerOrigin.rotation = Quaternion.AngleAxis(angle, axis) * _playerOrigin.rotation;
            }
            _playerOrigin.position = _playerOrigin.position + originalHeadPosition - _playerHead.position;
        }

        #region Inject
        public void InjectAllPlayerLocomotor(Transform playerOrigin, Transform playerHead)
        {
            InjectPlayerOrigin(playerOrigin);
            InjectPlayerHead(playerHead);
        }

        public void InjectPlayerOrigin(Transform playerOrigin)
        {
            _playerOrigin = playerOrigin;
        }

        public void InjectPlayerHead(Transform playerHead)
        {
            _playerHead = playerHead;
        }
        #endregion
    }

 

 

1 Reply

Replies have been turned off for this discussion
  • I don't know either but I also want to know a solution as I would like to not only set up multiplayer but also set up continuous joystick movement and I am being frustrated in a similar way.