c# - Unity Multiplayer Car : networking particles and sound -


i making unity game player controlling car , want game multiplayer. using standard assets' vehicule package car.

the structure of default car prefab controls separated between "user control" script handles user inputs, , "car controller" handles physics ( movements, acceleration, turning, steering etc).

you can find below sources of 2 scripts, modified carusercontrol.cs networking.

networking position not problem , works fine (i attached networktransform component car , networktransformchild wheels).

the thing car controller script handles particle effects when car steering (smoke generated , steering track appears), , sounds (acceleration, steering, skidding), , have absolutely no idea on how network that...

so right have multiplayer car movement, local car generates steering/skidding tracks, smoke, , sounds.

any idea on how it?

sources:

modified caruserinput.cs : added networkbehavior instead of monobehavior , added islocalplayer check

using system; using unityengine; using unitystandardassets.crossplatforminput; using unityengine.networking;  namespace unitystandardassets.vehicles.car {     [requirecomponent(typeof (carcontroller))]     public class carusercontrol : networkbehaviour     {         private carcontroller m_car; // car controller want use           private void awake()         {             // car controller             m_car = getcomponent<carcontroller>();         }           private void fixedupdate()         {             if (!islocalplayer)                 return;              // pass input car!             float h = crossplatforminputmanager.getaxis("horizontal");             float v = crossplatforminputmanager.getaxis("vertical"); #if !mobile_input             float handbrake = crossplatforminputmanager.getaxis("jump");             m_car.move(h, v, v, handbrake); #else             m_car.move(h, v, v, 0f); #endif         }     } } 

default carcontroller.cs:

using system; using unityengine;  namespace unitystandardassets.vehicles.car {     internal enum cardrivetype     {         frontwheeldrive,         rearwheeldrive,         fourwheeldrive     }      internal enum speedtype     {         mph,         kph     }      public class carcontroller : monobehaviour     {         [serializefield] private cardrivetype m_cardrivetype = cardrivetype.fourwheeldrive;         [serializefield] private wheelcollider[] m_wheelcolliders = new wheelcollider[4];         [serializefield] private gameobject[] m_wheelmeshes = new gameobject[4];         [serializefield] private wheeleffects[] m_wheeleffects = new wheeleffects[4];         [serializefield] private vector3 m_centreofmassoffset;         [serializefield] private float m_maximumsteerangle;         [range(0, 1)] [serializefield] private float m_steerhelper; // 0 raw physics , 1 car grip in direction facing         [range(0, 1)] [serializefield] private float m_tractioncontrol; // 0 no traction control, 1 full interference         [serializefield] private float m_fulltorqueoverallwheels;         [serializefield] private float m_reversetorque;         [serializefield] private float m_maxhandbraketorque;         [serializefield] private float m_downforce = 100f;         [serializefield] private speedtype m_speedtype;         [serializefield] private float m_topspeed = 200;         [serializefield] private static int noofgears = 5;         [serializefield] private float m_revrangeboundary = 1f;         [serializefield] private float m_sliplimit;         [serializefield] private float m_braketorque;          private quaternion[] m_wheelmeshlocalrotations;         private vector3 m_prevpos, m_pos;         private float m_steerangle;         private int m_gearnum;         private float m_gearfactor;         private float m_oldrotation;         private float m_currenttorque;         private rigidbody m_rigidbody;         private const float k_reversingthreshold = 0.01f;          public bool skidding { get; private set; }         public float brakeinput { get; private set; }         public float currentsteerangle{ { return m_steerangle; }}         public float currentspeed{ { return m_rigidbody.velocity.magnitude*2.23693629f; }}         public float maxspeed{get { return m_topspeed; }}         public float revs { get; private set; }         public float accelinput { get; private set; }          // use initialization         private void start()         {             m_wheelmeshlocalrotations = new quaternion[4];             (int = 0; < 4; i++)             {                 m_wheelmeshlocalrotations[i] = m_wheelmeshes[i].transform.localrotation;             }             m_wheelcolliders[0].attachedrigidbody.centerofmass = m_centreofmassoffset;              m_maxhandbraketorque = float.maxvalue;              m_rigidbody = getcomponent<rigidbody>();             m_currenttorque = m_fulltorqueoverallwheels - (m_tractioncontrol*m_fulltorqueoverallwheels);         }           private void gearchanging()         {             float f = mathf.abs(currentspeed/maxspeed);             float upgearlimit = (1/(float) noofgears)*(m_gearnum + 1);             float downgearlimit = (1/(float) noofgears)*m_gearnum;              if (m_gearnum > 0 && f < downgearlimit)             {                 m_gearnum--;             }              if (f > upgearlimit && (m_gearnum < (noofgears - 1)))             {                 m_gearnum++;             }         }           // simple function add curved bias towards 1 value in 0-1 range         private static float curvefactor(float factor)         {             return 1 - (1 - factor)*(1 - factor);         }           // unclamped version of lerp, allow value exceed from-to range         private static float ulerp(float from, float to, float value)         {             return (1.0f - value)*from + value*to;         }           private void calculategearfactor()         {             float f = (1/(float) noofgears);             // gear factor normalised representation of current speed within current gear's range of speeds.             // smooth towards 'target' gear factor, revs don't instantly snap or down when changing gear.             var targetgearfactor = mathf.inverselerp(f*m_gearnum, f*(m_gearnum + 1), mathf.abs(currentspeed/maxspeed));             m_gearfactor = mathf.lerp(m_gearfactor, targetgearfactor, time.deltatime*5f);         }           private void calculaterevs()         {             // calculate engine revs (for display / sound)             // (this done in retrospect - revs not used in force/power calculations)             calculategearfactor();             var gearnumfactor = m_gearnum/(float) noofgears;             var revsrangemin = ulerp(0f, m_revrangeboundary, curvefactor(gearnumfactor));             var revsrangemax = ulerp(m_revrangeboundary, 1f, gearnumfactor);             revs = ulerp(revsrangemin, revsrangemax, m_gearfactor);         }           public void move(float steering, float accel, float footbrake, float handbrake)         {             (int = 0; < 4; i++)             {                 quaternion quat;                 vector3 position;                 m_wheelcolliders[i].getworldpose(out position, out quat);                 m_wheelmeshes[i].transform.position = position;                 m_wheelmeshes[i].transform.rotation = quat;             }              //clamp input values             steering = mathf.clamp(steering, -1, 1);             accelinput = accel = mathf.clamp(accel, 0, 1);             brakeinput = footbrake = -1*mathf.clamp(footbrake, -1, 0);             handbrake = mathf.clamp(handbrake, 0, 1);              //set steer on front wheels.             //assuming wheels 0 , 1 front wheels.             m_steerangle = steering*m_maximumsteerangle;             m_wheelcolliders[0].steerangle = m_steerangle;             m_wheelcolliders[1].steerangle = m_steerangle;              steerhelper();             applydrive(accel, footbrake);             capspeed();              //set handbrake.             //assuming wheels 2 , 3 rear wheels.             if (handbrake > 0f)             {                 var hbtorque = handbrake*m_maxhandbraketorque;                 m_wheelcolliders[2].braketorque = hbtorque;                 m_wheelcolliders[3].braketorque = hbtorque;             }               calculaterevs();             gearchanging();              adddownforce();             checkforwheelspin();             tractioncontrol();         }           private void capspeed()         {             float speed = m_rigidbody.velocity.magnitude;             switch (m_speedtype)             {                 case speedtype.mph:                      speed *= 2.23693629f;                     if (speed > m_topspeed)                         m_rigidbody.velocity = (m_topspeed/2.23693629f) * m_rigidbody.velocity.normalized;                     break;                  case speedtype.kph:                     speed *= 3.6f;                     if (speed > m_topspeed)                         m_rigidbody.velocity = (m_topspeed/3.6f) * m_rigidbody.velocity.normalized;                     break;             }         }           private void applydrive(float accel, float footbrake)         {              float thrusttorque;             switch (m_cardrivetype)             {                 case cardrivetype.fourwheeldrive:                     thrusttorque = accel * (m_currenttorque / 4f);                     (int = 0; < 4; i++)                     {                         m_wheelcolliders[i].motortorque = thrusttorque;                     }                     break;                  case cardrivetype.frontwheeldrive:                     thrusttorque = accel * (m_currenttorque / 2f);                     m_wheelcolliders[0].motortorque = m_wheelcolliders[1].motortorque = thrusttorque;                     break;                  case cardrivetype.rearwheeldrive:                     thrusttorque = accel * (m_currenttorque / 2f);                     m_wheelcolliders[2].motortorque = m_wheelcolliders[3].motortorque = thrusttorque;                     break;              }              (int = 0; < 4; i++)             {                 if (currentspeed > 5 && vector3.angle(transform.forward, m_rigidbody.velocity) < 50f)                 {                     m_wheelcolliders[i].braketorque = m_braketorque*footbrake;                 }                 else if (footbrake > 0)                 {                     m_wheelcolliders[i].braketorque = 0f;                     m_wheelcolliders[i].motortorque = -m_reversetorque*footbrake;                 }             }         }           private void steerhelper()         {             (int = 0; < 4; i++)             {                 wheelhit wheelhit;                 m_wheelcolliders[i].getgroundhit(out wheelhit);                 if (wheelhit.normal == vector3.zero)                     return; // wheels arent on ground dont realign rigidbody velocity             }              // if needed avoid gimbal lock problems make car shift direction             if (mathf.abs(m_oldrotation - transform.eulerangles.y) < 10f)             {                 var turnadjust = (transform.eulerangles.y - m_oldrotation) * m_steerhelper;                 quaternion velrotation = quaternion.angleaxis(turnadjust, vector3.up);                 m_rigidbody.velocity = velrotation * m_rigidbody.velocity;             }             m_oldrotation = transform.eulerangles.y;         }           // used add more grip in relation speed         private void adddownforce()         {             m_wheelcolliders[0].attachedrigidbody.addforce(-transform.up*m_downforce*                                                          m_wheelcolliders[0].attachedrigidbody.velocity.magnitude);         }           // checks if wheels spinning , 3 things         // 1) emits particles         // 2) plays tiure skidding sounds         // 3) leaves skidmarks on ground         // these effects controlled through wheeleffects class         private void checkforwheelspin()         {             // loop through wheels             (int = 0; < 4; i++)             {                 wheelhit wheelhit;                 m_wheelcolliders[i].getgroundhit(out wheelhit);                  // tire slipping above given threshhold                 if (mathf.abs(wheelhit.forwardslip) >= m_sliplimit || mathf.abs(wheelhit.sidewaysslip) >= m_sliplimit)                 {                     m_wheeleffects[i].emittyresmoke();                      // avoiding 4 tires screeching @ same time                     // if can lead strange audio artefacts                     if (!anyskidsoundplaying())                     {                         m_wheeleffects[i].playaudio();                     }                     continue;                 }                  // if wasnt slipping stop audio                 if (m_wheeleffects[i].playingaudio)                 {                     m_wheeleffects[i].stopaudio();                 }                 // end trail generation                 m_wheeleffects[i].endskidtrail();             }         }          // crude traction control reduces power wheel if car wheel spinning         private void tractioncontrol()         {             wheelhit wheelhit;             switch (m_cardrivetype)             {                 case cardrivetype.fourwheeldrive:                     // loop through wheels                     (int = 0; < 4; i++)                     {                         m_wheelcolliders[i].getgroundhit(out wheelhit);                          adjusttorque(wheelhit.forwardslip);                     }                     break;                  case cardrivetype.rearwheeldrive:                     m_wheelcolliders[2].getgroundhit(out wheelhit);                     adjusttorque(wheelhit.forwardslip);                      m_wheelcolliders[3].getgroundhit(out wheelhit);                     adjusttorque(wheelhit.forwardslip);                     break;                  case cardrivetype.frontwheeldrive:                     m_wheelcolliders[0].getgroundhit(out wheelhit);                     adjusttorque(wheelhit.forwardslip);                      m_wheelcolliders[1].getgroundhit(out wheelhit);                     adjusttorque(wheelhit.forwardslip);                     break;             }         }           private void adjusttorque(float forwardslip)         {             if (forwardslip >= m_sliplimit && m_currenttorque >= 0)             {                 m_currenttorque -= 10 * m_tractioncontrol;             }             else             {                 m_currenttorque += 10 * m_tractioncontrol;                 if (m_currenttorque > m_fulltorqueoverallwheels)                 {                     m_currenttorque = m_fulltorqueoverallwheels;                 }             }         }           private bool anyskidsoundplaying()         {             (int = 0; < 4; i++)             {                 if (m_wheeleffects[i].playingaudio)                 {                     return true;                 }             }             return false;         }     } } 

you can sync states across server , clients.

inside carusercontrol script, add field:

[syncvar] bool smokeon; 

in update loop:

if (!isserver) {   //clients play smoke locally depending on synced variable   if(smokeon)     particlesystem.play();   else     particlesystem.stop(); } else  {   smokeon = particlesystem.isplaying; } 

you can apply same reasoning sounds - sync variable represents type of sound played, , clients play sounds locally depending on synced variable.


Comments

Popular posts from this blog

ios - MKAnnotationView layer is not of expected type: MKLayer -

ZeroMQ on Windows, with Qt Creator -

unity3d - Unity SceneManager.LoadScene quits application -