I am developing a VR multiplayer drawing feature using Unity’s VR multiplayer template (Netcode) and a drawing script from Logitech. I made some modifications to this script to support synchronized drawing across multiple players, but it still hasn’t worked. The drawing on the server is only visible locally. How can I make this component’s information synchronize across the network?
public class NewBehaviourScript : NetworkBehaviour
{
[SerializeField] private GameObject linePrefab;
private List<GameObject> _lines = new List<GameObject>();
private LineRenderer _currentLine;
private List<float> _currentLineWidths = new List<float>();
[SerializeField] float _maxLineWidth = 0.01f;
[SerializeField] float _minLineWidth = 0.0005f;
[SerializeField] private Color _currentColor = Color.white;
[SerializeField] private StylusHandler _stylusHandler;
private bool _isDrawing = false;
private Vector3 _previousLinePoint;
private const float _minDistanceBetweenLinePoints = 0.0005f;
private NetworkObject _currentLineNetworkObject;
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
Debug.Log("OnNetworkSpawn called - Network object spawned.");
}
private void StartNewLine()
{
Debug.Log("StartNewLine called.");
// 使用预制体实例化新线条对象
GameObject lineObject = Instantiate(linePrefab);
_currentLine = lineObject.GetComponent<LineRenderer>();
_currentLine.positionCount = 0;
_currentLine.material.color = _currentColor;
_currentLine.startWidth = _minLineWidth;
_currentLine.endWidth = _minLineWidth;
_lines.Add(lineObject);
_previousLinePoint = new Vector3(0, 0, 0);
_currentLineNetworkObject = lineObject.GetComponent<NetworkObject>();
_currentLineNetworkObject.Spawn();
Debug.Log("New line spawned and synced in network.");
}
[ServerRpc(RequireOwnership = false)]
private void AddPointServerRpc(Vector3 position, float width)
{
Debug.Log("AddPointServerRpc called - Position: " + position);
AddPointClientRpc(position, width);
}
[ClientRpc]
private void AddPointClientRpc(Vector3 position, float width)
{
if (_currentLine != null)
{
Debug.Log("AddPointClientRpc called - Position: " + position);
if (Vector3.Distance(position, _previousLinePoint) > _minDistanceBetweenLinePoints)
{
_previousLinePoint = position;
_currentLine.positionCount++;
_currentLine.SetPosition(_currentLine.positionCount - 1, position);
AnimationCurve curve = new AnimationCurve();
_currentLineWidths.Add(Math.Max(width * _maxLineWidth, _minLineWidth));
for (int i = 0; i < _currentLineWidths.Count; i++)
{
curve.AddKey(i / (float)(_currentLineWidths.Count - 1), _currentLineWidths[i]);
}
_currentLine.widthCurve = curve;
}
}
}
void Update()
{
if (_stylusHandler != null)
{
if (IsOwner && _stylusHandler.CanDraw())
{
float analogInput = Mathf.Max(_stylusHandler.CurrentState.tip_value, _stylusHandler.CurrentState.cluster_middle_value);
if (analogInput > 0)
{
if (!_isDrawing)
{
Debug.Log("Starting a new line.");
StartNewLine();
_isDrawing = true;
}
AddPointServerRpc(_stylusHandler.CurrentState.inkingPose.position, analogInput);
}
else
{
_isDrawing = false;
}
}
}
else
{
Debug.LogError("StylusHandler is null.");
}
}
}