UNet Control the "same" object?

Hello & Good evening!

now I have rethought it… and my result looks like you can see on the following screenshot:

One player is able to control the car and the other can control the tower and shoot. But I think the
implementation/logic behind sucks :stuck_out_tongue:

My Idea:
I have dragged a car model in the scene (just with a rigidbody, box collider, wheel collider etc.).
And I spawn a player (empty Gameobject with the “CAR1” Script on it.
Is there a better solution or an advice?

Thank you :slight_smile:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;

[System.Serializable]
public class AxleInfo11
{
    public WheelCollider leftWheel;
    public WheelCollider rightWheel;
    public bool motor;
    public bool steering;
}

public class CAR1 : NetworkBehaviour
{
    public List<AxleInfo11> axleInfos;
    public float maxMotorTorque;    public float maxSteeringAngle;

    private float LerpValue = 2;
    private float MinPosDist = 0.5F; 
    public int playerMODE = 0;

    private CAR1 carScript;
    GameObject carCRAB;
    private Transform towerObject;
    private Transform cannon;
    private Transform gunTIP;

    private Vector3 lastTankpos;        private Quaternion lastTankRot;

    //Geschützturm
    private float lsTowerRotationY;   private float LerpTurningTower = 2; private float MinMovementTower = 2F;
    private float lsCannonRotZ;   private float LerpTurningCannon = 2; private float MinMovmentCannon = 2F;

    //Motor-Steering
    private float lsTankSteering;         private float LerpTankSteering = 0.5F; private float MinAngleSteering = 2F;
    private float lsTankMotor;            private float LerpTankMotor = 0.5F; private float MinAngleMotor = 2F;

    [SyncVar]    private Vector3 cTankPos;
    [SyncVar]    private Quaternion cTankRot;
    [SyncVar]    public float motorVar;
    [SyncVar]    public float steeringVar;

    [SyncVar]    public float towerRotationY;
    [SyncVar]    public float cannonRotationZ;

    private float rotationZ = 0f;
    private float sensitivityZ = 2f;

    private AudioSource shootSound;
    private ParticleSystem particleShootingSmoke;
    void Start()
    {
        //FIND TANK
        carCRAB = GameObject.Find("CarLokal");
        towerObject = GameObject.Find("Drehturm").transform;
        shootSound = towerObject.GetComponent<AudioSource>();
        cannon = GameObject.Find("Drehkanone").transform;
        gunTIP = GameObject.Find("WEAPONTIP").transform;
        particleShootingSmoke = gunTIP.GetChild(0).transform.GetComponent<ParticleSystem>();
        carScript = GetComponent<CAR1>();
              
        carScript.axleInfos[0].leftWheel = carCRAB.transform.GetChild(1).transform.GetComponent<WheelCollider>(); ;
        carScript.axleInfos[0].rightWheel = carCRAB.transform.GetChild(2).transform.GetComponent<WheelCollider>(); ;
        carScript.axleInfos[1].leftWheel = carCRAB.transform.GetChild(3).transform.GetComponent<WheelCollider>(); ;
        carScript.axleInfos[1].rightWheel = carCRAB.transform.GetChild(4).transform.GetComponent<WheelCollider>(); ;
      
        //tank won't flip that easy
        Rigidbody rb = carCRAB.GetComponent<Rigidbody>();
        rb.centerOfMass = new Vector3(0, -0.4F, 0);


        playerMODE = GameObject.Find("NETWORKMANAGER").GetComponent<CurrentPos>().playerMODE;

        if (playerMODE == 1)
        {
            rb.isKinematic = true;
        }
  }
    void Update()
    {
        if(playerMODE==1)
        {
            if (Input.GetButtonDown("Fire1"))
            {
                StopCoroutine("Shoot");
                StartCoroutine("Shoot");
            }
        }
    }

    // example unity
    public void ApplyLocalPositionToVisuals(WheelCollider collider)
    {
        if (collider.transform.childCount == 0)
        {
            return;
        }

        Transform visualWheel = collider.transform.GetChild(0);

        Vector3 position;
        Quaternion rotation;
        collider.GetWorldPose(out position, out rotation);

        visualWheel.transform.position = position;
        visualWheel.transform.rotation = rotation;
    }
    private void ChangeAxisValues(float steering1, float motor1)
    {
        foreach (AxleInfo11 axleInfo in axleInfos)
        {
            if (axleInfo.steering)
            {
                axleInfo.leftWheel.steerAngle = steering1;
                axleInfo.rightWheel.steerAngle = steering1;
            }
            if (axleInfo.motor)
            {
                axleInfo.leftWheel.motorTorque = motor1;
                axleInfo.rightWheel.motorTorque = motor1;
            }
            ApplyLocalPositionToVisuals(axleInfo.leftWheel);
            ApplyLocalPositionToVisuals(axleInfo.rightWheel);
        }
    }


    public void FixedUpdate()
    {
        //MODE == DRIVER
        if (playerMODE == 0)
        {
            float motor = maxMotorTorque * Input.GetAxis("Vertical");
            float steering = maxSteeringAngle * Input.GetAxis("Horizontal");
            ChangeAxisValues(steering, motor);


            Vector3 currPos = carCRAB.transform.position;
            ChangeCarPosition(currPos);

            Quaternion currRot = carCRAB.transform.rotation;
            ChangeCarRotation(currRot);

            if (isOverThreshold(lastTankpos, currPos, MinPosDist))
            {
                CmdSendPosition(currPos);
                lastTankpos = currPos;
                CmdSendRotation(currRot);
                lastTankRot = currRot;

                CmdSendMotor(motor);
                lsTankMotor = motor;
            }

            //TOWER
            InterpolateTurretY();
            InterpolateKanoneZ();
     
         
            if (isOverThresholdFloat(lsTankSteering, steering, MinAngleSteering))
            {
                CmdSendSteering(steering);
                lsTankSteering = steering;
            }
          
        }
        else         //MODE == SHOOTER
        {
            Interpolate();
            InterpolateRot();
                 
            ChangeAxisValues(InterpolateSteering(), motorVar);

            //ROTATION WHOLE TOWER
            towerObject.transform.Rotate(0.0f, Input.GetAxis("Horizontal") * 2, 0.0f);
            if (isOverThresholdTurret(lsTowerRotationY, towerObject.transform.localRotation.y, MinMovementTower))
            {
                CmdSendTowerY(towerObject.transform.localEulerAngles.y);
                lsTowerRotationY = towerObject.transform.localEulerAngles.y;
            }

            //TOTATE CANNON
            rotationZ += Input.GetAxis("Vertical") * sensitivityZ;
            rotationZ = Mathf.Clamp(rotationZ, -20, 90);
            cannon.transform.localEulerAngles = new Vector3(cannon.transform.localEulerAngles.x, cannon.transform.localEulerAngles.y, -rotationZ);
            if (isOverThresholdDrehKanone(lsCannonRotZ, cannon.transform.localEulerAngles.z, MinMovmentCannon))
            {
                CmdSendDrehKanoneZ(cannon.transform.localEulerAngles.z);
                lsCannonRotZ = cannon.transform.localEulerAngles.z;
            }          
        }   
    }
    //CAR POSITION
    [Command]
    private void CmdSendPosition(Vector3 pos)
    {
        cTankPos = pos;
    }
    [Client]
    private void ChangeCarPosition(Vector3 pos)
    {
        carCRAB.transform.position = pos;
    }

    [Command]
    private void CmdSendMotor(float motor)
    {
        motorVar = motor;
    }
    [Command]
    private void CmdSendSteering(float steering)
    {
        steeringVar = steering;
    }

    //CAR ROTATION
    [Command]
    private void CmdSendRotation(Quaternion rot)
    {
        cTankRot = rot;
    }
    [Client]
    private void ChangeCarRotation(Quaternion rot)
    {
        carCRAB.transform.rotation = rot;
    }


    //TOWER
    [Command]
    private void CmdSendTowerY(float rotY)
    {
        lsTowerRotationY = rotY;
    }
    [Command]
    private void CmdSendDrehKanoneZ(float rotZ)
    {
        lsCannonRotZ = rotZ;
    }



    //INTERPOLATION STUFF --> simplify later on
    private void Interpolate()
    {
        Vector3 pos = Vector3.Lerp(carCRAB.transform.position, cTankPos, Time.deltaTime * LerpValue);
        carCRAB.transform.position = pos;
    }

    private void InterpolateRot()
    {
        Quaternion rot = Quaternion.Lerp(carCRAB.transform.rotation, cTankRot, Time.deltaTime * LerpValue);
        carCRAB.transform.rotation = rot;
    }

    private void InterpolateTurretY()
    {
        towerObject.transform.localEulerAngles = new Vector3(towerObject.transform.localEulerAngles.x, Mathf.Lerp(towerObject.transform.localEulerAngles.y, lsTowerRotationY, LerpTurningTower), towerObject.transform.localEulerAngles.z);
    }

    private void InterpolateKanoneZ()
    {
        cannon.transform.localEulerAngles = new Vector3(cannon.transform.localEulerAngles.x, cannon.transform.localEulerAngles.y, Mathf.Lerp(cannon.transform.localEulerAngles.y, lsCannonRotZ, LerpTurningCannon));
    }

    private float InterpolateSteering()
    {
        return Mathf.Lerp(lsTankSteering, steeringVar, LerpTankSteering);
    }
    private float InterpolateMotor()
    {
        return Mathf.Lerp(lsTankMotor, motorVar, LerpTankMotor);
    }

    private bool isOverThreshold(Vector3 old, Vector3 pos, float threshold)
    {
        return Vector3.Distance(old, pos) > threshold;
    }

    private bool isOverThresholdTurret(float old, float pos, float angleThreshold)
    {
        return (old - pos) > angleThreshold || (old - pos) < angleThreshold;
    }

    private bool isOverThresholdDrehKanone(float old, float pos, float angleThreshold)
    {
        return (old - pos) > angleThreshold || (old - pos) < angleThreshold;
    }


    private bool isOverThresholdFloat(float old, float pos, float angleThreshold)
    {
        return (old - pos) > angleThreshold || (old - pos) < angleThreshold;
    }



    IEnumerator Shoot()
    {
        while (Input.GetButton("Fire1"))
        {
            CmdShoot();

            shootSound.Stop();
            shootSound.Play();
            particleShootingSmoke.Play();

            Vector3 fwd = gunTIP.transform.TransformDirection(Vector3.forward);
            Debug.DrawRay(gunTIP.transform.position, fwd * 50, Color.green);
            RaycastHit hit;

            if (Physics.Raycast(gunTIP.transform.position, fwd, out hit, 100))
            {
                Debug.DrawLine(gunTIP.transform.position, hit.point, Color.red);

                if (hit.transform.tag == "ENEMY")
                {
                    Debug.Log("TEST");
                }
            }
            particleShootingSmoke.Stop();
            yield return new WaitForSeconds(0.1F);
        }
    }
    [Command]
    public void CmdShoot()
    {
        shootSound.Stop();
        shootSound.Play();
        particleShootingSmoke.Play();

        Vector3 fwd = gunTIP.transform.TransformDirection(Vector3.forward);
        Debug.DrawRay(gunTIP.transform.position, fwd * 50, Color.green);
        RaycastHit hit;

        if (Physics.Raycast(gunTIP.transform.position, fwd, out hit, 100))
        {
            Debug.DrawLine(gunTIP.transform.position, hit.point, Color.red);

            if (hit.transform.tag == "ENEMY")
            {
                Debug.Log("TEST");
            }
        }
        particleShootingSmoke.Stop();
    }
}

OLD THOUGHTS

firstly I’ve found similar threads but unfortunately I can’t really solve my problem :frowning:
I’ve tried several things but I’m… stuck.

Idea:
I want the user to join a room and then walk to different vehicles and control them. Further more I want that player1 controls the car movement and player2 the rotation of the turret (or is able to control the radio etc…).
Simplification:
Empty Gameobject Player spawns:
currentmode =0 → Player can control the car
currentmode =1 → Player can control the turret

Problem.
I’m not sure about the logic behind the scenario.

  1. My first thought was to create 1 car in my scene add a network identity, check Local Player Authority, add a network transform to that car. And when the game starts each player can control this 1 car.

  2. Or do I instantiate for all player in that car 1 car object and disable the visibility and then sync.
    Player 1 → syncs turret rotation/ receives car position
    Player 2 → syncs car movement/ receives turret rotation

Hmm appreciate some hints/help :slight_smile:

Short:
I want two ore more player to control different car gadgets.

And for those who aren’t confused yet…: :wink:


My plan:

  1. Empty Gameobject (Network Identity → local player authority checked) assigned to the Network Manager Script
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class PlayerController : NetworkBehaviour {
    GameObject car;
    int currentmode = 0;
    public GUISkin guistyle;
    private CarController carcontroller;
    private CarShooter carShooter;
    void Start()
    {
        car = GameObject.Find("CarLokal");
        carcontroller = car.GetComponent<CarController>();
        carShooter = car.GetComponent<CarShooter>();
    }

    void OnGUI()
    {
        if(!isLocalPlayer || isServer)
        {
            return;
        }
        GUI.skin = guistyle;
        GUI.color = Color.red;
        GUILayout.BeginArea(new Rect(Screen.width / 2 - 200, Screen.height - 100, 400, 400));
        if (GUILayout.Button("Mode1"))
        {
            currentmode = 0;
        }
        if (GUILayout.Button("Mode2"))
        {
            currentmode = 1;
        }
        GUILayout.Label("MODE: " + currentmode);
        GUILayout.EndArea();
    }

    void Update () {
        if (!isLocalPlayer)
        {
            return;
        }

        if(currentmode==0)
        {
            if(carcontroller !=null)
            {
                    carcontroller.GiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
                //  carcontroller.RpcGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
                //  carcontroller.CmdGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
            }
        }
        else
        {
            if(carShooter !=null)
            {
                carShooter.GiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
             // carShooter.RpcGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
             //  carShooter.CmdGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
            }
        }
    }
}

Car placed in the scene (Network Identity-> Local Player Authority checked + Car Shooter (Script) + Network Transform?!)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;

[System.Serializable]
public class AxleInfo2
{
    public WheelCollider leftWheel;
    public WheelCollider rightWheel;
    public bool motor;
    public bool steering;
}

public class CarController : NetworkBehaviour {

    public List<AxleInfo2> axleInfos;
    public float maxMotorTorque;
    public float maxSteeringAngle;

    private PlayerCamera playerCamera;

    void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
        rb.centerOfMass = new Vector3(0, -0.4F, 0);
    }


    // finds the corresponding visual wheel
    // correctly applies the transform
    public void ApplyLocalPositionToVisuals(WheelCollider collider)
    {
        if (collider.transform.childCount == 0)
        {
            return;
        }

        Transform visualWheel = collider.transform.GetChild(0);

        Vector3 position;
        Quaternion rotation;
        collider.GetWorldPose(out position, out rotation);

        visualWheel.transform.position = position;
        visualWheel.transform.rotation = rotation;
    }


    [SyncVar]
    public float currentVert=0;

    [SyncVar]
    public float currentHori=0;


    //Now let's start the confusion party :)
    [Command]
    public void CmdGiveVal(float currentVert, float currentHori)
    {
        this.currentVert = currentVert;
        this.currentHori = currentHori;
    }

    public void GiveVal(float currentVert, float currentHori)
    {
        this.currentVert = currentVert;
        this.currentHori = currentHori;
    }

      [ClientRpc]
      public void RpcGiveVal(float currentVert, float currentHori)
      {
          this.currentVert = currentVert;
          this.currentHori = currentHori;
      }

    public void FixedUpdate()
    {

        //   if (!isServer)
        //    {
        //        RpcSpreadVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
        //   }

        //  if (isLocalPlayer)
        //   {
        //       RpcGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
        //     }


  //      if(!isLocalPlayer)
   //     {
    //        return;
  //      }
   //     GiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));


        float motor = maxMotorTorque * currentVert;
        float steering = maxSteeringAngle * currentHori;

        foreach (AxleInfo2 axleInfo in axleInfos)
        {
            if (axleInfo.steering)
            {
                axleInfo.leftWheel.steerAngle = steering;
                axleInfo.rightWheel.steerAngle = steering;
            }
            if (axleInfo.motor)
            {
                axleInfo.leftWheel.motorTorque = motor;
                axleInfo.rightWheel.motorTorque = motor;
            }
            ApplyLocalPositionToVisuals(axleInfo.leftWheel);
            ApplyLocalPositionToVisuals(axleInfo.rightWheel);
        }
    }

}
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class CarShooter : NetworkBehaviour {
    public Transform tower;
    public Transform towerBarrel;
    [SyncVar]
    public float currentVert = 0;

    [SyncVar]
    public float currentHori = 0;

    [Command]
    public void CmdGiveVal(float currentVert, float currentHori)
    {
        this.currentVert = currentVert;
        this.currentHori = currentHori;
    }
    // Use this for initialization
    void Start () {

    }

    float speed = 4;
    [ClientRpc]
    public void RpcGiveVal(float currentVert, float currentHori)
    {
        this.currentVert = currentVert;
        this.currentHori = currentHori;
    }
    public void GiveVal(float currentVert, float currentHori)
    {
        this.currentVert = currentVert;
        this.currentHori = currentHori;
    }


    private float rotationZ = 0f;
    private float sensitivityZ = 2f;


    // Update is called once per frame
    void Update () {

     //   GiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));

     //   if(isLocalPlayer)
    //    {
     //       RpcGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
     //   }

        //  if (!isServer)
        //  {
        //       RpcSpreadVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
        //   }

        tower.transform.Rotate(0.0f, currentHori * speed, 0.0f);

        //  towerBarrel.transform.Rotate(0.0f, -Input.GetAxis("V") * speed, 0.0f);


        //  towerBarrel.transform.Rotate(0, Input.GetAxis("Vertical") * speed * Time.deltaTime, 0);
        //The function is Mathf.Clamp(value, min, max)
        rotationZ += currentVert * sensitivityZ;
        rotationZ = Mathf.Clamp(rotationZ, -20, 90);

        towerBarrel.transform.localEulerAngles = new Vector3(towerBarrel.transform.localEulerAngles.x, towerBarrel.transform.localEulerAngles.y, -rotationZ);

        /* if (Input.GetKey(KeyCode.A))
         {
             transform.Rotate(Vector3.up * speed * Time.deltaTime);
         }

         if (Input.GetKey(KeyCode.D))
                 transform.Rotate(-Vector3.up * speed * Time.deltaTime);

         */
    }
}

Regards Leo

Hmm ok now I have an idea :slight_smile:
Here’s a small script for changing the color of one cube (every player in the scene can change it)
(This is the same idea/just for movement right?) - Or is this script terrible (insecure?)

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class PlayerColor : NetworkBehaviour {
    GameObject cubeObj;
    private MeshRenderer meshRend;

    void Start () {
        cubeObj = GameObject.Find("Cube");
        meshRend = cubeObj.GetComponent<MeshRenderer>();
    }
   
    void Update () {
        if (isLocalPlayer)
        {
            if(Input.GetButtonDown("Fire1"))
            {
                Color32 colornew = GenColor();
                ChangeMaterialColor(colornew);
                CmdSendColor(colornew);
            }
        }
    }

    [Command]
    private void CmdSendColor(Color32 materialColor)
    {
        meshRend.material.color = materialColor;
        RpcSyncMaterialcolor(materialColor);
    }

    Color32 GenColor()
    {
        return new Color32((byte)Random.Range(0, 255), (byte)Random.Range(0, 255), (byte)Random.Range(0, 255), 255); ;
    }

    [ClientRpc]
    private void RpcSyncMaterialcolor(Color32 materialColor)
    {
        ChangeMaterialColor(materialColor);
    }

    [Client]
    private void ChangeMaterialColor(Color32 materialColor)
    {
        meshRend.material.color = materialColor;
    }
}

Sry for the push :slight_smile: I’ve edited the main thread and tried to make it more specific and clear.