Главная » Статьи » Unity3D Multiplayer

Урок 4 Мультиплеер в StarTrooper.Интеграция объектов и сцены

Теперь мы должны написать скрипт, который будет транслировать в сеть все твердые тела (Rigidbody).

Первым делом вы должны создать две папки под названием NetworkFIles для новых скриптов, и Plugins для C# скриптов.

Создайте C# скрипт и назовите его NetworkRigidbody.

Переместите NetworkRigidbody в папку Plugins. Вы можете использовать данный скрипт и в других своих проектах, так что лучше не удаляйте его. А теперь откройте его и введите туда:

  1. using UnityEngine;
  2. using System.Collections;
  3. public class NetworkRigidbody : MonoBehaviour {
  4. public double m_InterpolationBackTime = 0.1;
  5. public double m_ExtrapolationLimit = 0.5;
  6. internal struct State
  7. {
  8. internal double timestamp;
  9. internal Vector3 pos;
  10. internal Vector3 velocity;
  11. internal Quaternion rot;
  12. internal Vector3 angularVelocity;
  13. }
  14. // We store twenty states with "playback" information
  15. State[] m_BufferedState = new State[20];
  16. // Keep track of what slots are used
  17. int m_TimestampCount;
  18. void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info) {
  19. // Send data to server
  20. if (stream.isWriting)
  21. {
  22. Vector3 pos = rigidbody.position;
  23. Quaternion rot = rigidbody.rotation;
  24. Vector3 velocity = rigidbody.velocity;
  25. Vector3 angularVelocity = rigidbody.angularVelocity;
  26. stream.Serialize(ref pos);
  27. stream.Serialize(ref velocity);
  28. stream.Serialize(ref rot);
  29. stream.Serialize(ref angularVelocity);
  30. }
  31. // Read data from remote client
  32. else
  33. {
  34. Vector3 pos = Vector3.zero;
  35. Vector3 velocity = Vector3.zero;
  36. Quaternion rot = Quaternion.identity;
  37. Vector3 angularVelocity = Vector3.zero;
  38. stream.Serialize(ref pos);
  39. stream.Serialize(ref velocity);
  40. stream.Serialize(ref rot);
  41. stream.Serialize(ref angularVelocity);
  42. // Shift the buffer sideways, deleting state 20
  43. for (int i=m_BufferedState.Length-1;i>=1;i--)
  44. {
  45. m_BufferedState[i] = m_BufferedState[i-1];
  46. }
  47. // Record current state in slot 0
  48. State state;
  49. state.timestamp = info.timestamp;
  50. state.pos = pos;
  51. state.velocity = velocity;
  52. state.rot = rot;
  53. state.angularVelocity = angularVelocity;
  54. m_BufferedState[0] = state;
  55. // Update used slot count, however never exceed the buffer size
  56. // Slots aren't actually freed so this just makes sure the buffer is
  57. // filled up and that uninitalized slots aren't used.
  58. m_TimestampCount = Mathf.Min(m_TimestampCount + 1,
  59. m_BufferedState.Length);
  60. // Check if states are in order, if it is inconsistent you could reshuffel or
  61. // drop the out-of-order state. Nothing is done here
  62. for (int i=0;i<m_TimestampCount-1;i++)
  63. {
  64. if (m_BufferedState[i].timestamp < m_BufferedState[i+1].timestamp)
  65. Debug.Log("State inconsistent");
  66. }
  67. }
  68. }
  69. // We have a window of interpolationBackTime where we basically play
  70. // By having interpolationBackTime the average ping, you will usually use
  71. interpolation.
  72. // And only if no more data arrives we will use extra polation
  73. void Update () {
  74. // This is the target playback time of the rigid body
  75. double interpolationTime = Network.time - m_InterpolationBackTime;
  76. // Use interpolation if the target playback time is present in the buffer
  77. if (m_BufferedState[0].timestamp > interpolationTime)
  78. {
  79. // Go through buffer and find correct state to play back
  80. for (int i=0;i<m_TimestampCount;i++)
  81. {
  82. if (m_BufferedState[i].timestamp <= interpolationTime || i ==
  83. m_TimestampCount-1)
  84. {
  85. // The state one slot newer (<100ms) than the best playback state
  86. State rhs = m_BufferedState[Mathf.Max(i-1, 0)];
  87. // The best playback state (closest to 100 ms old (default time))
  88. State lhs = m_BufferedState[i];
  89. // Use the time between the two slots to determine if interpolation is
  90. necessary
  91. double length = rhs.timestamp - lhs.timestamp;
  92. float t = 0.0F;
  93. // As the time difference gets closer to 100 ms t gets closer to 1 in
  94. // which case rhs is only used
  95. // Example:
  96. // Time is 10.000, so sampleTime is 9.900
  97. // lhs.time is 9.910 rhs.time is 9.980 length is 0.070
  98. // t is 9.900 - 9.910 / 0.070 = 0.14. So it uses 14% of rhs, 86% of
  99. lhs
  100. if (length > 0.0001)
  101. t = (float)((interpolationTime - lhs.timestamp) / length);
  102. // if t=0 => lhs is used directly
  103. transform.localPosition = Vector3.Lerp(lhs.pos, rhs.pos, t);
  104. transform.localRotation = Quaternion.Slerp(lhs.rot, rhs.rot, t);
  105. return;
  106. }
  107. }
  108. }
  109. // Use extrapolation
  110. else
  111. {
  112. State latest = m_BufferedState[0];
  113. float extrapolationLength = (float)(interpolationTime - latest.timestamp);
  114. // Don't extrapolation for more than 500 ms, you would need to do that
  115. carefully
  116. if (extrapolationLength < m_ExtrapolationLimit)
  117. {
  118. float axisLength = extrapolationLength * latest.angularVelocity.magnitude
  119. * Mathf.Rad2Deg;
  120. Quaternion angularRotation = Quaternion.AngleAxis(axisLength,
  121. latest.angularVelocity);
  122. rigidbody.position = latest.pos + latest.velocity * extrapolationLength;
  123. rigidbody.rotation = angularRotation * latest.rot;
  124. rigidbody.velocity = latest.velocity;
  125. rigidbody.angularVelocity = latest.angularVelocity;
  126. }
  127. }
  128. }
  129. }

Выберите SpaceCraftFBX в иерархии, НЕ В ФАЙЛАХ ПРОЕКТА, и перетащите в него скрипт NetworkRigidbody. И отключите его в самом объекте(просто убрать галочку с компонента).

В компоненте NetworkView измените параметр Observed с SpaceCraftFBX (Transform) на SpaceCraftFBX (NetworkRigidbody).

Создайте новый джаваскрипт скрипт и назовите его RigidAssign, откройте его и введите туда:

  1. function OnNetworkInstantiate (msg : NetworkMessageInfo) {
  2. if (networkView.isMine)
  3. {
  4. var _NetworkRigidbody : NetworkRigidbody =
  5. GetComponent("NetworkRigidbody");
  6. _NetworkRigidbody.enabled = false;
  7. }
  8. else
  9. {
  10. name += "Remote";
  11. var _NetworkRigidbody2 : NetworkRigidbody =
  12. GetComponent("NetworkRigidbody");
  13. _NetworkRigidbody2.enabled = true;
  14. }
  15. }

Создайте новый префаб и назовите его SpaceCraft, переместите его в папку Prefabs. Дальше перетащите SpaceCraftFBX в иерархии в префаб SpaceCraft и удалите модель (SpaceCraftFBX) со сцены. Теперь создайте тег «SpaceCraft»: Edit -> Project Settings-> Tags.

Выделите префаб и кликните по полю "Untagged”, выйдет выпадающее окно в котором нужно выбрать «SpaceSraft».


Категория: Unity3D Multiplayer | Добавил: Шаке (20.03.2012)
Просмотров: 2501 | Комментарии: 3 | Теги: MasterServer, Мультиплеер, direct connect, Miscellaneous, gameobject, startrooper, udp broadcast, UDP, networkview
Всего комментариев: 3
3 Illigarium  
0
Не могу выложить. Комментарии в скрипте просто корявые

2 Illigarium  
0
Доработанная версия скрипта:


1 SomeFun  
0
Ошибка в первом скрипте

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
/>meta http-equiv=