Author Topic: Multi car testing and some error  (Read 2045 times)

ilanb

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 19
    • View Profile
Multi car testing and some error
« on: July 19, 2013, 09:16:44 AM »
Hi,

I try TNet and have some problem to control more one player.
I'v a prefab with a gameobject "Player" with a Rigidbody, JCar class, TNObject, TNSync Rigidbody and TNAuto sync.
I'v Sync property position and rotation for Transform and velocity, rotation and position for Rigidbody.

In the scene I'v a gameobject with TNAutoCreate and "Player" Prefab attached to it like your tuto :-)
+ one Main Camera and ground that's all.

here is a part of my JCar.cs

  1. void Awake ()
  2.         {
  3.                 if ( TNManager.isThisMyObject )
  4.                 {
  5.                         instance = this;
  6.                        
  7.                         obj = GameObject.Find("Main Camera");
  8.                         num = Random.Range(0,1234);
  9.                         carGo = GameObject.Find("Player(Clone)");
  10.                         carGo.name = "Car N°"+num.ToString();
  11.  
  12.                         if (obj != null)
  13.                         {
  14.                                 obj.GetComponent<FollowTrackingCamera>().SetFallowTransform(carGo.transform);
  15.                         }
  16.                 }
  17.         }

In this class I have also all properties and functions to control my car.

When I launch unity and open builded app I'v 2 car in my scenes Ex : car N°2323 and car N°...

Problem:

When I drive a car in unity I have no problem, is moving and I can see in app my car moved with wheels... but when I try to move second car it's stay in place or move very slow.
other problem if I turn wheel, other car have wheel turned too.

Where is my mistake ? How my car can move correctly and independently ?

Thanks !

here is JCar.cs complete if needed

  1. using UnityEngine;
  2. using System.Collections;
  3. using TNet;
  4.  
  5. public enum JWheelDrive {
  6.     Front = 0,
  7.     Back = 1,
  8.     All = 2
  9. }
  10.  
  11. public class JCar : MonoBehaviour {
  12.  
  13.         static public JCar instance;
  14.        
  15.         private GameObject obj;
  16.         private GameObject carGo;
  17.  
  18.         private int num;
  19.        
  20.     // if connected the controls will block if object not  active
  21.     // (for example steer only if car camera is active).
  22.     public GameObject checkForActive;
  23.  
  24.     public Transform wheelFR; // connect to Front Right Wheel transform
  25.     public Transform wheelFL; // connect to Front Left Wheel transform
  26.     public Transform wheelBR; // connect to Back Right Wheel transform
  27.     public Transform wheelBL; // connect to Back Left Wheel transform
  28.  
  29.     public float suspensionDistance = 0.2f; // amount of movement in suspension
  30.     public float springs = 1000.0f; // suspension springs
  31.     public float dampers = 2f; // how much damping the suspension has
  32.     public float wheelRadius = 0.25f; // the radius of the wheels
  33.     public float torque = 100f; // the base power of the engine (per wheel, and before gears)
  34.     public float brakeTorque = 2000f; // the power of the braks (per wheel)
  35.     public float wheelWeight = 3f; // the weight of a wheel
  36.     public Vector3 shiftCentre = new Vector3(0.0f, -0.25f, 0.0f); // offset of centre of mass
  37.  
  38.     public float maxSteerAngle = 30.0f; // max angle of steering wheels
  39.     public JWheelDrive wheelDrive = JWheelDrive.Front; // which wheels are powered
  40.  
  41.     public float shiftDownRPM = 1500.0f; // rpm script will shift gear down
  42.     public float shiftUpRPM = 2500.0f; // rpm script will shift gear up
  43.     public float idleRPM = 500.0f; // idle rpm
  44.  
  45.     public float fwdStiffness = 0.1f; // for wheels, determines slip
  46.     public float swyStiffness = 0.1f; // for wheels, determines slip
  47.  
  48.     // gear ratios (index 0 is reverse)
  49.     public float[] gears = { -10f, 9f, 6f, 4.5f, 3f, 2.5f };
  50.  
  51.     // automatic, if true car shifts automatically up/down
  52.     public bool automatic = true;
  53.  
  54.     public float killEngineSoundTimeout = 3.0f; // time until engine sound is cut off (in s.)
  55.  
  56.     // table of efficiency at certain RPM, in tableStep RPM increases, 1.0f is 100% efficient
  57.     // at the given RPM, current table has 100% at around 2000RPM
  58.     float[] efficiencyTable = { 0.6f, 0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 0.95f, 0.80f, 0.70f, 0.60f, 0.5f, 0.45f, 0.40f, 0.36f, 0.33f, 0.30f, 0.20f, 0.10f, 0.05f };
  59.  
  60.     // the scale of the indices in table, so with 250f, 750RPM translates to efficiencyTable[3].
  61.     float efficiencyTableStep = 250.0f;
  62.  
  63.     int currentGear = 1; // duh.
  64.  
  65.     // shortcut to the component audiosource (engine sound).
  66.     AudioSource audioSource;
  67.        
  68.         private Vector3 lp;
  69.  
  70.     // every wheel has a wheeldata struct, contains useful wheel specific info
  71.     class WheelData {
  72.         public Transform transform;
  73.         public GameObject go;
  74.         public WheelCollider col;
  75.         public Vector3 startPos;
  76.         public float rotation = 0.0f;
  77.         public float maxSteer;
  78.         public bool motor;
  79.     };
  80.  
  81.     WheelData[] wheels; // array with the wheel data
  82.  
  83.     // setup wheelcollider for given wheel data
  84.     // wheel is the transform of the wheel
  85.     // maxSteer is the angle in degrees the wheel can steer (0f for no steering)
  86.     // motor if wheel is driven by engine or not
  87.     WheelData SetWheelParams(Transform wheel, float maxSteer, bool motor) {
  88.         if (wheel == null) {
  89.             throw new System.Exception("wheel not connected to script!");
  90.         }
  91.         WheelData result = new WheelData(); // the container of wheel specific data
  92.  
  93.         // we create a new gameobject for the collider and move, transform it to match
  94.         // the position of the wheel it represents. This allows us to do transforms
  95.         // on the wheel itself without disturbing the collider.
  96.         GameObject go = new GameObject("WheelCollider");
  97.         go.transform.parent = transform; // the car, not the wheel is parent
  98.         go.transform.position = wheel.position; // match wheel pos
  99.  
  100.         // create the actual wheel collider in the collider game object
  101.         WheelCollider col = (WheelCollider) go.AddComponent(typeof(WheelCollider));
  102.         col.motorTorque = 0.0f;
  103.  
  104.         // store some useful references in the wheeldata object
  105.         result.transform = wheel; // access to wheel transform
  106.         result.go = go; // store the collider game object
  107.         result.col = col; // store the collider self
  108.         result.startPos = go.transform.localPosition; // store the current local pos of wheel
  109.         result.maxSteer = maxSteer; // store the max steering angle allowed for wheel
  110.         result.motor = motor; // store if wheel is connected to engine
  111.  
  112.         return result; // return the WheelData
  113.     }
  114.  
  115.         void Awake ()
  116.         {
  117.                 if ( TNManager.isThisMyObject )
  118.                 {
  119.                         instance = this;
  120.                        
  121.                         obj = GameObject.Find("Main Camera");
  122.                         num = Random.Range(0,1234);
  123.                         carGo = GameObject.Find("Player(Clone)");
  124.                         carGo.name = "Car N°"+num.ToString();
  125.  
  126.                         if (obj != null)
  127.                         {
  128.                                 obj.GetComponent<FollowTrackingCamera>().SetFallowTransform(carGo.transform);
  129.                         }
  130.                 }
  131.         }
  132.        
  133.     // Use this for initialization
  134.     void Start () {
  135.         // 4 wheels, if needed different size just modify and modify
  136.         // the wheels[...] block below.
  137.         wheels = new WheelData[4];
  138.  
  139.         // setup wheels
  140.         bool frontDrive = (wheelDrive == JWheelDrive.Front) || (wheelDrive == JWheelDrive.All);
  141.         bool backDrive = (wheelDrive == JWheelDrive.Back) || (wheelDrive == JWheelDrive.All);
  142.  
  143.         // we use 4 wheels, but you can change that easily if neccesary.
  144.         // this is the only place that refers directly to wheelFL, ...
  145.         // so when adding wheels, you need to add the public transforms,
  146.         // adjust the array size, and add the wheels initialisation here.
  147.         wheels[0] = SetWheelParams(wheelFR, maxSteerAngle, frontDrive);
  148.         wheels[1] = SetWheelParams(wheelFL, maxSteerAngle, frontDrive);
  149.         wheels[2] = SetWheelParams(wheelBR, 0.0f, backDrive);
  150.         wheels[3] = SetWheelParams(wheelBL, 0.0f, backDrive);
  151.  
  152.         // found out the hard way: some parameters must be set AFTER all wheel colliders
  153.         // are created, like wheel mass, otherwise your car will act funny and will
  154.         // flip over all the time.
  155.         foreach (WheelData w in wheels) {
  156.             WheelCollider col = w.col;
  157.             col.suspensionDistance = suspensionDistance;
  158.             JointSpring js = col.suspensionSpring;
  159.             js.spring = springs;
  160.             js.damper = dampers;            
  161.             col.suspensionSpring = js;
  162.             col.radius = wheelRadius;
  163.             col.mass = wheelWeight;
  164.  
  165.             // see docs, haven't really managed to get this work
  166.             // like i would but just try out a fiddle with it.
  167.             WheelFrictionCurve fc = col.forwardFriction;
  168.             fc.asymptoteValue = 5000.0f;
  169.             fc.extremumSlip = 2.0f;
  170.             fc.asymptoteSlip = 20.0f;
  171.             fc.stiffness = fwdStiffness;
  172.             col.forwardFriction = fc;
  173.             fc = col.sidewaysFriction;
  174.             fc.asymptoteValue = 7500.0f;
  175.             fc.asymptoteSlip = 2.0f;
  176.             fc.stiffness = swyStiffness;
  177.             col.sidewaysFriction = fc;
  178.         }
  179.  
  180.         // we move the centre of mass (somewhere below the centre works best.)
  181.         rigidbody.centerOfMass += shiftCentre;
  182.  
  183.         // shortcut to audioSource should be engine sound, if null then no engine sound.
  184.         audioSource = (AudioSource) GetComponent(typeof(AudioSource));
  185.         if (audioSource == null) {
  186.             Debug.Log("No audio source, add one to the car with looping engine noise (but can be turned off");
  187.         }
  188.  
  189.     }
  190.  
  191.     void Update() {
  192.         if (Input.GetKeyDown("page up")) {
  193.             ShiftUp();
  194.         }
  195.         if (Input.GetKeyDown("page down")) {
  196.             ShiftDown();
  197.         }
  198.     }
  199.  
  200.     float shiftDelay = 0.0f;
  201.  
  202.     // handle shifting a gear up
  203.     public void ShiftUp() {
  204.         float now = Time.timeSinceLevelLoad;
  205.  
  206.         // check if we have waited long enough to shift
  207.         if (now < shiftDelay) return;
  208.  
  209.         // check if we can shift up
  210.         if (currentGear < gears.Length - 1) {
  211.             currentGear ++;
  212.  
  213.             // we delay the next shift with 1s. (sorry, hardcoded)
  214.             shiftDelay = now + 1.0f;
  215.         }
  216.     }
  217.  
  218.     // handle shifting a gear down
  219.     public void ShiftDown() {
  220.         float now = Time.timeSinceLevelLoad;
  221.  
  222.         // check if we have waited long enough to shift
  223.         if (now < shiftDelay) return;
  224.  
  225.         // check if we can shift down (note gear 0 is reverse)
  226.         if (currentGear > 0) {
  227.             currentGear --;
  228.  
  229.             // we delay the next shift with 1/10s. (sorry, hardcoded)
  230.             shiftDelay = now + 0.1f;
  231.         }
  232.     }
  233.  
  234.     float wantedRPM = 0.0f; // rpm the engine tries to reach
  235.     float motorRPM = 0.0f;
  236.     float killEngine = 0.0f;
  237.  
  238.     // handle the physics of the engine
  239.     void LateUpdate ()
  240.     {
  241.                 float delta = Time.fixedDeltaTime;
  242.          
  243.                 float steer = 0; // steering -1.0 .. 1.0
  244.                 float accel = 0; // accelerating -1.0 .. 1.0
  245.                 bool brake = false; // braking (true is brake)
  246.          
  247.                 if ((checkForActive == null) || checkForActive.active) {
  248.                     // we only look at input when the object we monitor is
  249.                     // active (or we aren't monitoring an object).
  250.                     steer = Input.GetAxis("Horizontal");
  251.                     accel = Input.GetAxis("Vertical");
  252.                     brake = Input.GetButton("Jump");
  253.                 }
  254.          
  255.                 // handle automatic shifting
  256.                 if (automatic && (currentGear == 1) && (accel < 0.0f)) {
  257.                     ShiftDown(); // reverse
  258.                 }
  259.                 else if (automatic && (currentGear == 0) && (accel > 0.0f)) {
  260.                     ShiftUp(); // go from reverse to first gear
  261.                 }
  262.                 else if (automatic && (motorRPM > shiftUpRPM) && (accel > 0.0f)) {
  263.                     ShiftUp(); // shift up
  264.                 }
  265.                 else if (automatic && (motorRPM < shiftDownRPM) && (currentGear > 1)) {
  266.                     ShiftDown(); // shift down
  267.                 }
  268.                 if (automatic && (currentGear == 0)) {
  269.                     accel = - accel; // in automatic mode we need to hold arrow down for reverse
  270.                 }
  271.                 if (accel < 0.0f) {
  272.                     // if we try to decelerate we brake.
  273.                     brake = true;
  274.                     accel = 0.0f;
  275.                     wantedRPM = 0.0f;
  276.                 }
  277.          
  278.                 // the RPM we try to achieve.
  279.                 wantedRPM = (5500.0f * accel) * 0.1f + wantedRPM * 0.9f;
  280.          
  281.                 float rpm = 0.0f;
  282.                 int motorizedWheels = 0;
  283.                 bool floorContact = false;
  284.          
  285.                 // calc rpm from current wheel speed and do some updating
  286.                 foreach (WheelData w in wheels) {
  287.                     WheelHit hit;
  288.                     WheelCollider col = w.col;
  289.          
  290.                     // only calculate rpm on wheels that are connected to engine
  291.                     if (w.motor) {
  292.                         rpm += col.rpm;
  293.                         motorizedWheels++;
  294.                     }
  295.          
  296.                     // calculate the local rotation of the wheels from the delta time and rpm
  297.                     // then set the local rotation accordingly (also adjust for steering)
  298.                     w.rotation = Mathf.Repeat(w.rotation + delta * col.rpm * 360.0f / 60.0f, 360.0f);
  299.                     w.transform.localRotation = Quaternion.Euler(w.rotation, col.steerAngle, 0.0f);
  300.          
  301.                     // let the wheels contact the ground, if no groundhit extend max suspension distance
  302.                     lp = w.transform.localPosition;
  303.                     if (col.GetGroundHit(out hit)) {
  304.                         lp.y -= Vector3.Dot(w.transform.position - hit.point, transform.up) - col.radius;
  305.                         floorContact = floorContact || (w.motor);
  306.                     }
  307.                     else {
  308.                         lp.y = w.startPos.y - suspensionDistance;
  309.                     }
  310.                                
  311.                                 w.transform.localPosition = lp;
  312.                 }
  313.                        
  314.                 // calculate the actual motor rpm from the wheels connected to the engine
  315.                 // note we haven't corrected for gear yet.
  316.                 if (motorizedWheels > 1) {
  317.                     rpm = rpm / motorizedWheels;
  318.                 }
  319.          
  320.                 // we do some delay of the change (should take delta instead of just 95% of
  321.                 // previous rpm, and also adjust or gears.
  322.                 motorRPM = 0.95f * motorRPM + 0.05f * Mathf.Abs(rpm * gears[currentGear]);
  323.                 if (motorRPM > 5500.0f) motorRPM = 5500.0f;
  324.          
  325.                 // calculate the 'efficiency' (low or high rpm have lower efficiency then the
  326.                 // ideal efficiency, say 2000RPM, see table
  327.                 int index = (int) (motorRPM / efficiencyTableStep);
  328.                 if (index >= efficiencyTable.Length) index = efficiencyTable.Length - 1;
  329.                 if (index < 0) index = 0;
  330.          
  331.                 // calculate torque using gears and efficiency table
  332.                 float newTorque = torque * gears[currentGear] * efficiencyTable[index];
  333.          
  334.                 // go set torque to the wheels
  335.                 foreach (WheelData w in wheels) {
  336.                     WheelCollider col = w.col;
  337.          
  338.                     // of course, only the wheels connected to the engine can get engine torque
  339.                     if (w.motor) {
  340.                         // only set torque if wheel goes slower than the expected speed
  341.                         if (Mathf.Abs(col.rpm) > Mathf.Abs(wantedRPM)) {
  342.                             // wheel goes too fast, set torque to 0
  343.                             col.motorTorque = 0;
  344.                         }
  345.                         else {
  346.                             //
  347.                             float curTorque = col.motorTorque;
  348.                             col.motorTorque = curTorque * 0.9f + newTorque * 0.1f;
  349.                         }
  350.                     }
  351.                     // check if we have to brake
  352.                     col.brakeTorque = (brake)?brakeTorque:0.0f;
  353.          
  354.                     // set steering angle
  355.                     col.steerAngle = steer * w.maxSteer;
  356.                 }
  357.          
  358.                 // if we have an audiosource (motorsound) adjust pitch using rpm        
  359.                 if (audioSource != null) {
  360.                     // calculate pitch (keep it within reasonable bounds)
  361.                     float pitch = Mathf.Clamp(1.0f + ((motorRPM - idleRPM) / (shiftUpRPM - idleRPM) * 2.5f), 1.0f, 10.0f);
  362.                     audioSource.pitch = pitch;
  363.          
  364.                     if (motorRPM > 100) {
  365.                         // turn on sound if it's not playing yet and RPM is > 100.
  366.                         if (!audioSource.isPlaying) {
  367.                             audioSource.Play();
  368.                         }
  369.                         // how long we should wait with engine RPM <= 100 before killing engine sound
  370.                         killEngine = Time.time + killEngineSoundTimeout;
  371.                     }
  372.                     else if ((audioSource.isPlaying) && (Time.time > killEngine)) {
  373.                         // standing still, kill engine sound.
  374.                         audioSource.Stop();
  375.                     }
  376.                 }
  377.     }
  378.  
  379.     public void OnGUI() {
  380.         if (checkForActive.active) {
  381.             // calculate actual speed in Km/H (SI metrics rule, so no inch, yard, foot,
  382.             // stone, or other stupid length measure!)
  383.             float speed = rigidbody.velocity.magnitude * 3.6f;
  384.  
  385.             // message to display
  386.             string msg = "Speed " + speed.ToString("f0") + "Km/H, " + motorRPM.ToString("f0") + "RPM, gear " + currentGear; //  + " torque " + newTorque.ToString("f2") + ", efficiency " + table[index].ToString("f2");
  387.  
  388.             GUILayout.BeginArea(new Rect(Screen.width -250 - 32, 32, 250, 40), GUI.skin.window);
  389.             GUILayout.Label(msg);
  390.             GUILayout.EndArea();
  391.         }
  392.     }
  393. }

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Multi car testing and some error
« Reply #1 on: July 19, 2013, 10:20:25 AM »
You don't check tno.isMine in your Update() function, so you basically end up controlling both cars at the same time.

You must wrap all your input behaviour logic in:
  1. if (tno.isMine) { ... }
I also don't recommend you use flat-out rigidbody sync here. I would suggest synchronizing your joystick/input values instead, and then sync your rigidbody every so often, or when the car collides with something else.

I did something very similar in the Multi-Purpose Game Starter Kit. The tank there is actually just a car driving script that has support for tank-like turning mechanics. I synchronize the input values, and every so often -- auto-sync the rigidbody.

ilanb

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 19
    • View Profile
Re: Multi car testing and some error
« Reply #2 on: July 19, 2013, 11:46:26 AM »
Thanks ArenMook !!!  :-*

The problem always lies between the chair and the keyboard  ;D

Thx for the tip's too :

Quote
I also don't recommend you use flat-out rigidbody sync here. I would suggest synchronizing your joystick/input values instead, and then sync your rigidbody every so often, or when the car collides with something else.