Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Integrate robot arm into multiplayer application

Discussion in 'Multiplayer' started by Flix2299, Dec 31, 2023.

  1. Flix2299

    Flix2299

    Joined:
    Jun 8, 2022
    Posts:
    3
    Hi,
    i'm still a beginner when it comes to multiplayer, and my question may not be that complicated, but I just don't know what else to try. I want to integrate a robot arm, which I took directly from the Unity robot demo (see https://github.com/Unity-Technologies/articulations-robot-demo), into a multiplayer application, so that several users can connect and one can always control the robot at the same time, with the other users synchronizing this use of the robot. Later on, it should be possible to transfer the right to use the robot to another user, but this is not the main problem. I have already tried a similar application with a simpler object, and it worked there, but not quite here. Currently, when I let two users join via ParrelSync, it shows me that both connect, one as host, the other as client, and no problems occur. I can also control the robot arm with the host, the only problem is that the client is not synchronized. Of course, the robot arm cannot be controlled with the client, as it is server-authoritative.
    upload_2023-12-31_16-45-23.png
    UR3 is the robotic arm. This is controlled via the empty ManualInput object. The robot arm has a NetworkObject and a NetworkTransform. ManualInput only has one NetworkObject. The new input system is used. As I understand it, the properties of the parent object also apply to its child objects, so if the root object of UR3 has a Network Transform, this also applies to all its child objects. Perhaps I have already made a mistake here, as the scripts for control are not directly on the robot arm?
    Another problem is that the robot arm uses articulation bodies. I know that with Rigidbody there is the Network Rigidbody that you have to add, but this is not possible with Articulation Bodies. Is this possibly the problem? How can I make ArticulationBody's multiplayer capable?

    I don't know if the code could have anything to do with it, but here are the three main scripts that are responsible for controlling the joints:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Netcode;
    4. using UnityEngine;
    5.  
    6. public class RobotManualInput : NetworkBehaviour
    7. {
    8.     public GameObject robot;
    9.  
    10.  
    11.     void Update()
    12.     {
    13.         if (!IsOwner)
    14.         {
    15.             return;
    16.         }
    17.        
    18.         ControlRobotServerRpc();
    19.     }
    20.    
    21.     [ServerRpc(RequireOwnership = false)]
    22.     private void ControlRobotServerRpc()
    23.     {
    24.         RobotController robotController = robot.GetComponent<RobotController>();
    25.         for (int i = 0; i < robotController.joints.Length; i++)
    26.         {
    27.             float inputVal = Input.GetAxis(robotController.joints[i].inputAxis);
    28.             if (Mathf.Abs(inputVal) > 0)
    29.             {
    30.                    
    31.                 RotationDirection direction = GetRotationDirection(inputVal);
    32.                 robotController.RotateJoint(i, direction);
    33.                 return;
    34.             }
    35.         }
    36.  
    37.         robotController.StopAllJointRotations();
    38.     }
    39.  
    40.     // HELPERS
    41.  
    42.     static RotationDirection GetRotationDirection(float inputVal)
    43.     {
    44.         if (inputVal > 0)
    45.         {
    46.             return RotationDirection.Positive;
    47.         }
    48.         else if (inputVal < 0)
    49.         {
    50.             return RotationDirection.Negative;
    51.         }
    52.         else
    53.         {
    54.             return RotationDirection.None;
    55.         }
    56.     }
    57. }
    58.  
    RobotManualInput is responsible for the initial execution from the ManualInput object. The control functions can be found at the root body of the articulation of UR3 in the RobotController script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Netcode;
    4. using UnityEngine;
    5.  
    6.  
    7. public class RobotController : NetworkBehaviour
    8. {
    9.     [System.Serializable]
    10.     public struct Joint
    11.     {
    12.         public string inputAxis;
    13.         public GameObject robotPart;
    14.     }
    15.     public Joint[] joints;
    16.  
    17.  
    18.     // CONTROL
    19.  
    20.     public void StopAllJointRotations()
    21.     {
    22.         for (int i = 0; i < joints.Length; i++)
    23.         {
    24.             GameObject robotPart = joints[i].robotPart;
    25.             UpdateRotationState(RotationDirection.None, robotPart);
    26.         }
    27.     }
    28.  
    29.     public void RotateJoint(int jointIndex, RotationDirection direction)
    30.     {
    31.         StopAllJointRotations();
    32.         Joint joint = joints[jointIndex];
    33.         UpdateRotationState(direction, joint.robotPart);
    34.     }
    35.  
    36.     // HELPERS
    37.  
    38.     static void UpdateRotationState(RotationDirection direction, GameObject robotPart)
    39.     {
    40.         ArticulationJointController jointController = robotPart.GetComponent<ArticulationJointController>();
    41.         jointController.rotationState = direction;
    42.     }
    43.  
    44.  
    45.  
    46. }
    And finally, the actual application of the joint movements can be found in the ArticulationJointController script, which is attached to every single joint of UR3:

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using Unity.Netcode;
    5. using UnityEngine;
    6.  
    7. public enum RotationDirection { None = 0, Positive = 1, Negative = -1 };
    8.  
    9. public class ArticulationJointController : NetworkBehaviour
    10. {
    11.     public RotationDirection rotationState = RotationDirection.None;
    12.     public float speed = 300.0f;
    13.  
    14.     private ArticulationBody articulation;
    15.  
    16.  
    17.     // LIFE CYCLE
    18.  
    19.     void OnEnable()
    20.     {
    21.         articulation = GetComponent<ArticulationBody>();
    22.     }
    23.  
    24.     void FixedUpdate()
    25.     {
    26.         if (rotationState != RotationDirection.None) {
    27.             float rotationChange = (float)rotationState * speed * Time.fixedDeltaTime;
    28.             float rotationGoal = CurrentPrimaryAxisRotation() + rotationChange;
    29.             RotateTo(rotationGoal);
    30.         }
    31.     }
    32.  
    33.  
    34.     // MOVEMENT HELPERS
    35.  
    36.     float CurrentPrimaryAxisRotation()
    37.     {
    38.         float currentRotationRads = articulation.jointPosition[0];
    39.         float currentRotation = Mathf.Rad2Deg * currentRotationRads;
    40.         return currentRotation;
    41.     }
    42.  
    43.     void RotateTo(float primaryAxisRotation)
    44.     {
    45.         var drive = articulation.xDrive;
    46.         drive.target = primaryAxisRotation;
    47.         articulation.xDrive = drive;
    48.     }
    49.  
    50.  
    51.  
    52. }
    As I said, the main problem is that the movement from the host is not synchronized with the other clients. In case my description was not clear enough, I have uploaded the project with the corresponding scene here https://github.com/flix123/Robot-arm-multiplayer. I am grateful for any help.

    A happy new year to all of you.