2017-09-13 18 views
0

私は、プレイヤーが車をコントロールしているUnityのゲームを作っています。私はこのゲームをマルチプレイヤーにします。私は車にStandard Assets 'Vehiculeパッケージを使用しています。Unity Multiplayer Car:ネットワーキングのパーティクルとサウンド

コントロールのデフォルトカープレハブの構造は、ユーザー入力を処理する「ユーザーコントロール」スクリプトと、物理(動き、加速、回転、ステアリングなど)を処理する「カーコントローラー」の間で分けられます。

これらの2つのスクリプトのソースは以下のとおりです。ネットワーク用にCarUserControl.csを変更しました。

ネットワークの位置は問題ではなく、うまくいきます(NetworkTransformコンポーネントを車に、NetworkTransformChildを車輪に接続するだけです)。

車のステアリング(煙が発生し、ステアリングトラックが表示されます)と音(加速、ステアリング、スキッド)が発生したときに、Car Controllerスクリプトもパーティクルエフェクトを処理します。ネットワークその...

今私はマルチプレイカーの動きがありますが、ローカルの車だけがステアリング/スキッドトラック、スモーク、サウンドを生成します。

どうすればいいですか?

出典:

修正CarUserInput.csは:NetworkBehaviorの代わりMonoBehaviorを追加し、isLocalPlayerチェック

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; // the car controller we want to use 


     private void Awake() 
     { 
      // get the car controller 
      m_Car = GetComponent<CarController>(); 
     } 


     private void FixedUpdate() 
     { 
      if (!isLocalPlayer) 
       return; 

      // pass the input to the 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 
     } 
    } 
} 

デフォルト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 is raw physics , 1 the car will grip in the direction it is facing 
     [Range(0, 1)] [SerializeField] private float m_TractionControl; // 0 is no traction control, 1 is 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{ get { return m_SteerAngle; }} 
     public float CurrentSpeed{ get { 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 this for initialization 
     private void Start() 
     { 
      m_WheelMeshLocalRotations = new Quaternion[4]; 
      for (int i = 0; i < 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 to add a curved bias towards 1 for a value in the 0-1 range 
     private static float CurveFactor(float factor) 
     { 
      return 1 - (1 - factor)*(1 - factor); 
     } 


     // unclamped version of Lerp, to allow value to exceed the 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 is a normalised representation of the current speed within the current gear's range of speeds. 
      // We smooth towards the 'target' gear factor, so that revs don't instantly snap up 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 is done in retrospect - revs are 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) 
     { 
      for (int i = 0; i < 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 the steer on the front wheels. 
      //Assuming that wheels 0 and 1 are the 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 the handbrake. 
      //Assuming that wheels 2 and 3 are the 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); 
        for (int i = 0; i < 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; 

      } 

      for (int i = 0; i < 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() 
     { 
      for (int i = 0; i < 4; i++) 
      { 
       WheelHit wheelhit; 
       m_WheelColliders[i].GetGroundHit(out wheelhit); 
       if (wheelhit.normal == Vector3.zero) 
        return; // wheels arent on the ground so dont realign the rigidbody velocity 
      } 

      // this if is needed to avoid gimbal lock problems that will make the car suddenly 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; 
     } 


     // this is used to add more grip in relation to speed 
     private void AddDownForce() 
     { 
      m_WheelColliders[0].attachedRigidbody.AddForce(-transform.up*m_Downforce* 
                 m_WheelColliders[0].attachedRigidbody.velocity.magnitude); 
     } 


     // checks if the wheels are spinning and is so does three things 
     // 1) emits particles 
     // 2) plays tiure skidding sounds 
     // 3) leaves skidmarks on the ground 
     // these effects are controlled through the WheelEffects class 
     private void CheckForWheelSpin() 
     { 
      // loop through all wheels 
      for (int i = 0; i < 4; i++) 
      { 
       WheelHit wheelHit; 
       m_WheelColliders[i].GetGroundHit(out wheelHit); 

       // is the tire slipping above the given threshhold 
       if (Mathf.Abs(wheelHit.forwardSlip) >= m_SlipLimit || Mathf.Abs(wheelHit.sidewaysSlip) >= m_SlipLimit) 
       { 
        m_WheelEffects[i].EmitTyreSmoke(); 

        // avoiding all four tires screeching at the same time 
        // if they do it can lead to some strange audio artefacts 
        if (!AnySkidSoundPlaying()) 
        { 
         m_WheelEffects[i].PlayAudio(); 
        } 
        continue; 
       } 

       // if it wasnt slipping stop all the audio 
       if (m_WheelEffects[i].PlayingAudio) 
       { 
        m_WheelEffects[i].StopAudio(); 
       } 
       // end the trail generation 
       m_WheelEffects[i].EndSkidTrail(); 
      } 
     } 

     // crude traction control that reduces the power to wheel if the car is wheel spinning too much 
     private void TractionControl() 
     { 
      WheelHit wheelHit; 
      switch (m_CarDriveType) 
      { 
       case CarDriveType.FourWheelDrive: 
        // loop through all wheels 
        for (int i = 0; i < 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() 
     { 
      for (int i = 0; i < 4; i++) 
      { 
       if (m_WheelEffects[i].PlayingAudio) 
       { 
        return true; 
       } 
      } 
      return false; 
     } 
    } 
} 

答えて

1

することができますが全同期状態あなたのサーバーとクライアント。あなたのUpdateループで

[SyncVar] 
bool smokeOn; 

:あなたのCarUserControlスクリプト内

、フィールドを追加

if (!isServer) 
{ 
    //Clients play their smoke locally depending on the synced variable 
    if(smokeOn) 
    particleSystem.Play(); 
    else 
    particleSystem.Stop(); 
} 
else 
{ 
    smokeOn = particleSystem.isPlaying; 
} 

あなたはあなたの音に同じ推論を適用することができます - の種類を表す変数を同期サウンドが再生され、クライアントは同期された変数に応じてローカルでサウンドを再生します。

+0

事は実際に、煙がCarUserControlで活性化されていないということです。

次のチュートリアルが良い参照することができ そして、パーティクルエフェクトは「 - - スポーン情報Registerd SpawnableプレハブのNetworkManager」に追加する必要があります車輪に取り付けられた別のスクリプトから粒子をトリガーするCarControllerで行われる複雑な計算に依存します(これは標準アセットの車のプレハブで設計されています)。しかし、実際に私に非常に良いアイデアを与えたこの答えをありがとう、私はそれを試してみよう! –

1

通常、私はこのように行います、マルチプレイヤーゲームでパーティクルエフェクトを生成するには:あなたがローカルでこのメソッドを呼び出すことができますが、サーバ上で実行されることを意味し

[Command] 
public void CmdSpell(int index, float time){ 

    var m_Spell = SpellGroup [index]; 
    GameObject spell = (GameObject)Instantiate (m_Spell, SpellCastPosition.position, SpellCastPosition.rotation); 
    NetworkServer.Spawn (spell); 
    Destroy (spell,time); 
} 

。このようにして、パーティクルエフェクトはサーバー上で生成されます。 https://unity3d.com/learn/tutorials/topics/multiplayer-networking

+0

ありがとうございます。私はすでにあなたが言及したネットワーキングの法律に従った。だから、弾丸のように煙が出るように提案する。私は煙がどこで行われたかを見つけるためにCarControllerスクリプトをもっと調べなければなりません –

関連する問題