from github
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.Interaction.Toolkit;
|
||||
|
||||
//this script is the base of location and rotation sync of spawned 3D objects
|
||||
|
||||
public class ObjectGrabListener : MonoBehaviour
|
||||
{
|
||||
//stores if the object is grabbed by local player
|
||||
private bool isGrabed = false;
|
||||
//counts the frames
|
||||
private int count = 0;
|
||||
private ObjectSync objectSync;
|
||||
//index of the object in objectsyncs lists
|
||||
public int index;
|
||||
|
||||
void Start()
|
||||
{
|
||||
//add listener functions to the grabinteractor
|
||||
objectSync = GameObject.Find("ObjectSpawner").GetComponent<ObjectSync>();
|
||||
XRGrabInteractable grabinteract = GetComponent<XRGrabInteractable>();
|
||||
grabinteract.onSelectEntered.AddListener(OnGrab);
|
||||
grabinteract.onSelectExited.AddListener(OnRelease);
|
||||
grabinteract.onSelectCanceled.AddListener(OnRelease);
|
||||
}
|
||||
|
||||
public void OnGrab(XRBaseInteractor interactor)
|
||||
{
|
||||
isGrabed = true;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
public void OnRelease(XRBaseInteractor interactor)
|
||||
{
|
||||
isGrabed = false;
|
||||
//on release of the object the position and rotation should be synced one last time
|
||||
objectSync.syncLocationServerRPC(index, transform.position, transform.rotation);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
//if the object is grabbed sync its position and rotation are syned every 10 frames (performance)
|
||||
if (isGrabed)
|
||||
{
|
||||
if (count >= 10)
|
||||
{
|
||||
objectSync.syncLocationServerRPC(index, transform.position, transform.rotation);
|
||||
count = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 913bdcbc8641e0c4e8e31c8bcee85749
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,100 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
//this scripts syncs the object movement etc.
|
||||
|
||||
public class ObjectSync : NetworkBehaviour
|
||||
{
|
||||
[SerializeField] private OBJLoader objLoader;
|
||||
|
||||
//a struct that can been sent over network containing the data of an object
|
||||
public struct OBJData : INetworkSerializable
|
||||
{
|
||||
public Vector3[] vertices;
|
||||
public int[] triangles;
|
||||
public Vector3 positionVector;
|
||||
public Quaternion rotation;
|
||||
public Vector3 scale;
|
||||
|
||||
//seriealizer method for network sync
|
||||
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
|
||||
{
|
||||
serializer.SerializeValue(ref vertices);
|
||||
serializer.SerializeValue(ref triangles);
|
||||
serializer.SerializeValue(ref positionVector);
|
||||
serializer.SerializeValue(ref rotation);
|
||||
serializer.SerializeValue(ref scale);
|
||||
}
|
||||
}
|
||||
|
||||
//a list of the objects spawned on the local client NOT SYNCED!
|
||||
public List<GameObject> spawnedObjects = new List<GameObject>();
|
||||
//a list of the object data on the server NOT DIRECTLY SYNED!
|
||||
public List<OBJData> objDataList = new List<OBJData>();
|
||||
|
||||
//the clientside function to scale an object
|
||||
[ClientRpc]
|
||||
public void syncScaleClientRPC(int i, Vector3 scale)
|
||||
{
|
||||
spawnedObjects[i].transform.localScale = scale;
|
||||
}
|
||||
|
||||
//the server side function to scale an object
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void syncScaleServerRPC(int i, Vector3 scale)
|
||||
{
|
||||
syncScaleClientRPC(i, scale);
|
||||
//keep track of the scale on the servers list
|
||||
OBJData localCopy = objDataList[i];
|
||||
localCopy.scale = scale;
|
||||
objDataList[i] = localCopy;
|
||||
}
|
||||
|
||||
//the client side function to sync the position and rotation of an object
|
||||
[ClientRpc]
|
||||
public void syncLocationClientRPC(int i, Vector3 pos, Quaternion rot)
|
||||
{
|
||||
spawnedObjects[i].transform.position = pos;
|
||||
spawnedObjects[i].transform.rotation = rot;
|
||||
//Debug.Log(NetworkManager.Singleton.LocalClientId);
|
||||
}
|
||||
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void syncLocationServerRPC(int i, Vector3 pos, Quaternion rot)
|
||||
{
|
||||
syncLocationClientRPC(i, pos, rot);
|
||||
OBJData localCopy = objDataList[i];
|
||||
localCopy.positionVector = pos;
|
||||
localCopy.rotation = rot;
|
||||
objDataList[i] = localCopy;
|
||||
}
|
||||
|
||||
//the next 2 functions provide functionality to sync every object from the servers list to the client
|
||||
//for the case that a player joins after some objects are already in the scene
|
||||
[ClientRpc]
|
||||
public void syncListClientRPC(ulong id, OBJData objDat)
|
||||
{
|
||||
//only the client with the correct id (the receiving client) must create the objects (the server got the id from initial clients request)
|
||||
if (id == NetworkManager.Singleton.LocalClientId)
|
||||
{
|
||||
//create a mesh via OBJLoader width the data in objDat
|
||||
GameObject obj = objLoader.CreateMesh(objLoader.buildObjData(objDat.vertices, objDat.triangles), objDat.positionVector);
|
||||
//apply scale and rotation (maybe further parameters) to the object, that the OBJLoader is not capable to load
|
||||
obj.transform.rotation = objDat.rotation;
|
||||
obj.transform.localScale = objDat.scale;
|
||||
}
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void syncListServerRPC(ulong id)
|
||||
{
|
||||
//send each object in a seperate RPC (network buffer limit only per object, NOT FOR ALL OBJECTS)
|
||||
foreach (OBJData obj in objDataList)
|
||||
{
|
||||
syncListClientRPC(id, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96baf24ed4dfa0e4585d05667895523b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
//this script syncs player components position and rotation in a local space
|
||||
|
||||
public class PlayerComponentNetworkSync : NetworkBehaviour
|
||||
{
|
||||
private NetworkVariable<Vector3> pos = new NetworkVariable<Vector3>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
private NetworkVariable<Quaternion> rot = new NetworkVariable<Quaternion>(writePerm:NetworkVariableWritePermission.Owner);
|
||||
|
||||
private void Update()
|
||||
{
|
||||
//the owner of the player object should write to the network variable, all others should read it
|
||||
if (IsOwner)
|
||||
{
|
||||
pos.Value = transform.localPosition;
|
||||
rot.Value = transform.localRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.localPosition = pos.Value;
|
||||
transform.localRotation = rot.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88889d527159cdb4385f38abe64ef5db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
//this script syncs player components position and rotation in a global space
|
||||
|
||||
public class PlayerGlobalCompontentSync : NetworkBehaviour
|
||||
{
|
||||
//the owner of the player object should write to the network variable, all others should read it
|
||||
private NetworkVariable<Vector3> pos = new NetworkVariable<Vector3>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
private NetworkVariable<Quaternion> rot = new NetworkVariable<Quaternion>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (IsOwner)
|
||||
{
|
||||
pos.Value = transform.position;
|
||||
rot.Value = transform.rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = pos.Value;
|
||||
transform.rotation = rot.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f502141805ac51439b33dde1e80a539
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using Unity.Collections;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
//this script syncs the name and color of a player
|
||||
|
||||
public class PlayerNameAndColor : NetworkBehaviour
|
||||
{
|
||||
[SerializeField] public TMP_Text playerText;
|
||||
[SerializeField] public GameObject dummyMesh;
|
||||
[SerializeField] private Material DummyHandMaterial;
|
||||
[SerializeField] public GameObject handLeft, handRight;
|
||||
|
||||
|
||||
private NetworkVariable<FixedString64Bytes> playername = new NetworkVariable<FixedString64Bytes>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
private NetworkVariable<float> colorR = new NetworkVariable<float>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
private NetworkVariable<float> colorG = new NetworkVariable<float>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
private NetworkVariable<float> colorB = new NetworkVariable<float>(writePerm: NetworkVariableWritePermission.Owner);
|
||||
|
||||
|
||||
public void userDataSync()
|
||||
{
|
||||
//set the name tag of each individual player
|
||||
playerText.text = playername.Value.ToString();
|
||||
//set the color of each individual player to the value received from network
|
||||
dummyMesh.GetComponent<Renderer>().material.color = new Color(colorR.Value, colorG.Value, colorB.Value);
|
||||
//apply color to the hands (the standard hands material is for every players hands --> create material for each individual player)
|
||||
Material newHandMaterial = new Material(handLeft.GetComponent<Renderer>().material.shader);
|
||||
newHandMaterial.color = new Color(colorR.Value, colorG.Value, colorB.Value);
|
||||
handLeft.GetComponent<SkinnedMeshRenderer>().material = newHandMaterial;
|
||||
handRight.GetComponent<SkinnedMeshRenderer>().material = newHandMaterial;
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
base.OnNetworkSpawn();
|
||||
if(IsOwner)
|
||||
{
|
||||
//write all parameters from the playerprefs to the networkvariable if you are owner of the player object
|
||||
playerText.text = PlayerPrefs.GetString("playerName");
|
||||
playername.Value = PlayerPrefs.GetString("playerName");
|
||||
colorR.Value = PlayerPrefs.GetFloat("playerColorR");
|
||||
colorG.Value = PlayerPrefs.GetFloat("playerColorG");
|
||||
colorB.Value = PlayerPrefs.GetFloat("playerColorB");
|
||||
dummyMesh.GetComponent<Renderer>().material.color = new Color(colorR.Value, colorG.Value, colorB.Value);
|
||||
DummyHandMaterial.color = new Color(colorR.Value, colorG.Value, colorB.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
//read the player value with a little delay so the players client had enough time to set the network variables
|
||||
Invoke("userDataSync", 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c250757fc7603b4f8d7cf466013c58f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Netcode;
|
||||
using Unity.XR.CoreUtils;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.XR.Interaction.Toolkit;
|
||||
using UnityEngine.XR.Interaction.Toolkit.Inputs;
|
||||
|
||||
//this script enables important components for the owners player
|
||||
//the components listed here should be active for others player objects
|
||||
//f.e.: unity will switch to other joined players camera if not handled
|
||||
|
||||
public class PlayerRemoveNetworkComps : NetworkBehaviour
|
||||
{
|
||||
|
||||
[SerializeField] private InputActionManager inputActionManager;
|
||||
[SerializeField] private XROrigin xrOrigin;
|
||||
[SerializeField] private Camera cam;
|
||||
[SerializeField] private AudioListener audioListener;
|
||||
[SerializeField] private ActionBasedController leftController;
|
||||
[SerializeField] private ActionBasedController rightController;
|
||||
[SerializeField] private XRRayInteractor leftRayInteractor;
|
||||
[SerializeField] private XRRayInteractor rightRayInteractor;
|
||||
[SerializeField] private XRInteractorLineVisual leftLineVisual;
|
||||
[SerializeField] private XRInteractorLineVisual rightLineVisual;
|
||||
[SerializeField] private Animator rightHandAnimator;
|
||||
[SerializeField] private Animator leftHandAnimator;
|
||||
[SerializeField] private SkinnedMeshRenderer leftHandRenderer;
|
||||
[SerializeField] private SkinnedMeshRenderer rightHandRenderer;
|
||||
[SerializeField] private LocomotionSystem locomotionSystem;
|
||||
[SerializeField] private ActionBasedContinuousMoveProvider moveProvider;
|
||||
[SerializeField] private ActionBasedContinuousTurnProvider turnProvider;
|
||||
[SerializeField] private TrackedPoseDriver trackedPoseDriver;
|
||||
[SerializeField] private GameObject menuBar;
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
|
||||
if (IsOwner)
|
||||
{
|
||||
inputActionManager.enabled = true;
|
||||
xrOrigin.enabled = true;
|
||||
cam.enabled = true;
|
||||
audioListener.enabled = true;
|
||||
leftController.enabled = true;
|
||||
rightController.enabled = true;
|
||||
leftRayInteractor.enabled = true;
|
||||
rightRayInteractor.enabled = true;
|
||||
leftLineVisual.enabled = true;
|
||||
rightLineVisual.enabled = true;
|
||||
leftHandAnimator.enabled = true;
|
||||
rightHandAnimator.enabled = true;
|
||||
leftHandRenderer.enabled = true;
|
||||
rightHandRenderer.enabled = true;
|
||||
locomotionSystem.enabled = true;
|
||||
moveProvider.enabled = true;
|
||||
turnProvider.enabled = true;
|
||||
trackedPoseDriver.enabled = true;
|
||||
menuBar.SetActive(true);
|
||||
|
||||
//request all objects that have been already loaded from the server / host
|
||||
ObjectSync objSync = GameObject.Find("ObjectSpawner").GetComponent<ObjectSync>();
|
||||
objSync.syncListServerRPC(NetworkManager.Singleton.LocalClientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a05404a0dffca541898079702b8b9d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
|
||||
//this scripts is the startpoint of the classroom scene, it starts the host or creates the connection to it
|
||||
|
||||
public class onStart : NetworkBehaviour
|
||||
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
|
||||
private float starttime;
|
||||
[SerializeField] private UnityTransport hostIPAdress;
|
||||
//stores if the connection establishment check has already been performed
|
||||
private bool roomCheck = true;
|
||||
void Start()
|
||||
{
|
||||
//value to measure the time since connection attempt (for timeout)
|
||||
starttime = Time.time;
|
||||
if (PlayerPrefs.GetString("status") == "client")
|
||||
{
|
||||
try
|
||||
{
|
||||
hostIPAdress.ConnectionData.Address = PlayerPrefs.GetString("hostadress");
|
||||
NetworkManager.Singleton.StartClient();
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
//on error load the room creattion scene
|
||||
SceneManager.LoadScene("RoomCreation");
|
||||
}
|
||||
}
|
||||
else if (PlayerPrefs.GetString("status") == "host")
|
||||
{
|
||||
//set address to 0.0.0.0 to accept connection from all networks
|
||||
hostIPAdress.ConnectionData.Address = "0.0.0.0";
|
||||
NetworkManager.Singleton.StartHost();
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
//UnityEngine.Debug.Log((Time.time - starttime));
|
||||
if ((Time.time - starttime) > 15 && roomCheck)
|
||||
{
|
||||
roomCheck = false;
|
||||
//if there is no camera in the scene, the network join was not successfull XD
|
||||
if ( !(GameObject.Find("Main Camera")))
|
||||
{
|
||||
SceneManager.LoadScene("RoomCreation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f01e5b523c3afed4586251bd16692442
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user