SyncTranform.cs 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Netcode;
  4. using UnityEngine;
  5. //用插值的方式进行同步位置
  6. [DisallowMultipleComponent]
  7. [DefaultExecutionOrder(100000)]
  8. public class SyncTranform : NetworkBehaviour
  9. {
  10. //位置信息变化阈值,当单次变化大于该值,就会进行同步
  11. public const float PositionThresholdDefault = 0.001f;
  12. public const float RotAngleThresholdDefault = 0.01f;
  13. public const float ScaleThresholdDefault = 0.01f;
  14. //客户端变化请求
  15. public delegate (Vector3 pos, Quaternion rotOut, Vector3 scale) OnClientRequestChangeDelegate(Vector3 pos, Quaternion rot, Vector3 scale);
  16. //服务端收到客户端位置同步信息,回调
  17. /// <summary>
  18. /// The handler that gets invoked when server receives a change from a client.
  19. /// This handler would be useful for server to modify pos/rot/scale before applying client's request.
  20. /// </summary>
  21. public OnClientRequestChangeDelegate OnClientRequestChange;
  22. //位置信息同步
  23. internal struct NetworkTransformState : INetworkSerializable
  24. {
  25. private const int k_InLocalSpaceBit = 0;
  26. private const int k_PositionXBit = 1;
  27. private const int k_PositionYBit = 2;
  28. private const int k_PositionZBit = 3;
  29. private const int k_RotAngleXBit = 4;
  30. private const int k_RotAngleYBit = 5;
  31. private const int k_RotAngleZBit = 6;
  32. private const int k_ScaleXBit = 7;
  33. private const int k_ScaleYBit = 8;
  34. private const int k_ScaleZBit = 9;
  35. private const int k_TeleportingBit = 10;
  36. //是否局部空间的位置
  37. private ushort m_Bitset;
  38. internal bool InLocalSpace
  39. {
  40. get => (m_Bitset & (1 << k_InLocalSpaceBit)) != 0;
  41. set
  42. {
  43. if(value)
  44. {
  45. m_Bitset = (ushort)(m_Bitset | (1 << k_InLocalSpaceBit));
  46. }
  47. else
  48. {
  49. m_Bitset = (ushort)(m_Bitset & ~(1 << k_InLocalSpaceBit));
  50. }
  51. }
  52. }
  53. //处理位置
  54. internal bool HasPositionX
  55. {
  56. get => (m_Bitset & (1 << k_PositionXBit)) != 0;
  57. set
  58. {
  59. if(value)
  60. {
  61. m_Bitset = (ushort)(m_Bitset | (1 << k_PositionXBit));
  62. }
  63. else
  64. {
  65. m_Bitset = (ushort)(m_Bitset & ~(1 << k_PositionXBit));
  66. }
  67. }
  68. }
  69. internal bool HasPositionY
  70. {
  71. get => (m_Bitset & (1 << k_PositionYBit)) != 0;
  72. set
  73. {
  74. if(value)
  75. {
  76. m_Bitset = (ushort)(m_Bitset | (1 << k_PositionYBit));
  77. }
  78. else
  79. {
  80. m_Bitset = (ushort)(m_Bitset & ~(1 << k_PositionYBit));
  81. }
  82. }
  83. }
  84. internal bool HasPositionZ
  85. {
  86. get => (m_Bitset & (1 << k_PositionZBit)) != 0;
  87. set
  88. {
  89. if(value)
  90. {
  91. m_Bitset = (ushort)(m_Bitset | (1 << k_PositionZBit));
  92. }
  93. else
  94. {
  95. m_Bitset = (ushort)(m_Bitset & ~(1 << k_PositionZBit));
  96. }
  97. }
  98. }
  99. internal bool HasPositionChange
  100. {
  101. get
  102. {
  103. return HasPositionX | HasPositionY | HasPositionZ;
  104. }
  105. }
  106. //处理旋转
  107. internal bool HasRotAngleX
  108. {
  109. get => (m_Bitset & (1 << k_RotAngleXBit)) != 0;
  110. set
  111. {
  112. if(value)
  113. {
  114. m_Bitset = (ushort)(m_Bitset | (1 << k_RotAngleXBit));
  115. }
  116. else
  117. {
  118. m_Bitset = (ushort)(m_Bitset & ~(1 << k_RotAngleXBit));
  119. }
  120. }
  121. }
  122. internal bool HasRotAngleY
  123. {
  124. get => (m_Bitset & (1 << k_RotAngleYBit)) != 0;
  125. set
  126. {
  127. if(value)
  128. {
  129. m_Bitset = (ushort)(m_Bitset | (1 << k_RotAngleYBit));
  130. }
  131. else
  132. {
  133. m_Bitset = (ushort)(m_Bitset & ~(1 << k_RotAngleYBit));
  134. }
  135. }
  136. }
  137. internal bool HasRotAngleZ
  138. {
  139. get => (m_Bitset & (1 << k_RotAngleZBit)) != 0;
  140. set
  141. {
  142. if(value)
  143. {
  144. m_Bitset = (ushort)(m_Bitset | (1 << k_RotAngleZBit));
  145. }
  146. else
  147. {
  148. m_Bitset = (ushort)(m_Bitset & ~(1 << k_RotAngleZBit));
  149. }
  150. }
  151. }
  152. internal bool HasRotAngleChange
  153. {
  154. get
  155. {
  156. return HasRotAngleX | HasRotAngleY | HasRotAngleZ;
  157. }
  158. }
  159. // 处理缩放
  160. internal bool HasScaleX
  161. {
  162. get => (m_Bitset & (1 << k_ScaleXBit)) != 0;
  163. set
  164. {
  165. if(value)
  166. {
  167. m_Bitset = (ushort)(m_Bitset | (1 << k_ScaleXBit));
  168. }
  169. else
  170. {
  171. m_Bitset = (ushort)(m_Bitset & ~(1 << k_ScaleXBit));
  172. }
  173. }
  174. }
  175. internal bool HasScaleY
  176. {
  177. get => (m_Bitset & (1 << k_ScaleYBit)) != 0;
  178. set
  179. {
  180. if(value)
  181. {
  182. m_Bitset = (ushort)(m_Bitset | (1 << k_ScaleYBit));
  183. }
  184. else
  185. {
  186. m_Bitset = (ushort)(m_Bitset & ~(1 << k_ScaleYBit));
  187. }
  188. }
  189. }
  190. internal bool HasScaleZ
  191. {
  192. get => (m_Bitset & (1 << k_ScaleZBit)) != 0;
  193. set
  194. {
  195. if(value)
  196. {
  197. m_Bitset = (ushort)(m_Bitset | (1 << k_ScaleZBit));
  198. }
  199. else
  200. {
  201. m_Bitset = (ushort)(m_Bitset & ~(1 << k_ScaleZBit));
  202. }
  203. }
  204. }
  205. internal bool HasScaleChange
  206. {
  207. get
  208. {
  209. return HasScaleX | HasScaleY | HasScaleZ;
  210. }
  211. }
  212. internal bool IsTeleportingNextFrame
  213. {
  214. get => (m_Bitset & (1 << k_TeleportingBit)) != 0;
  215. set
  216. {
  217. if(value)
  218. {
  219. m_Bitset = (ushort)(m_Bitset | (1 << k_TeleportingBit));
  220. }
  221. else
  222. {
  223. m_Bitset = (ushort)(m_Bitset & ~(1 << k_TeleportingBit));
  224. }
  225. }
  226. }
  227. internal float PositionX, PositionY, PositionZ;
  228. internal float RotAngleX, RotAngleY, RotAngleZ;
  229. internal float ScaleX, ScaleY, ScaleZ;
  230. internal double SentTime;
  231. //数据有更新
  232. internal bool IsDirty;
  233. //用于结束外插值
  234. internal int EndExtrapolationTick;
  235. //重置BitSet
  236. internal void ClearBitSetForNextTick()
  237. {
  238. //保存局部空间设置
  239. m_Bitset &= (ushort)(m_Bitset & (1 << k_InLocalSpaceBit));
  240. IsDirty = false;
  241. }
  242. public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
  243. {
  244. serializer.SerializeValue(ref SentTime);
  245. serializer.SerializeValue(ref m_Bitset);
  246. if(HasPositionX)
  247. {
  248. serializer.SerializeValue(ref PositionX);
  249. }
  250. if(HasPositionY)
  251. {
  252. serializer.SerializeValue(ref PositionY);
  253. }
  254. if(HasPositionZ)
  255. {
  256. serializer.SerializeValue(ref PositionZ);
  257. }
  258. if(HasRotAngleX)
  259. {
  260. serializer.SerializeValue(ref RotAngleX);
  261. }
  262. if(HasRotAngleY)
  263. {
  264. serializer.SerializeValue(ref RotAngleY);
  265. }
  266. if(HasRotAngleZ)
  267. {
  268. serializer.SerializeValue(ref RotAngleZ);
  269. }
  270. if(HasScaleX)
  271. {
  272. serializer.SerializeValue(ref ScaleX);
  273. }
  274. if(HasScaleY)
  275. {
  276. serializer.SerializeValue(ref ScaleY);
  277. }
  278. if(HasScaleZ)
  279. {
  280. serializer.SerializeValue(ref ScaleZ);
  281. }
  282. //收到数据
  283. if(serializer.IsReader)
  284. {
  285. //详见TryCommitTransformToServer方法
  286. if(HasPositionChange || HasRotAngleChange || HasScaleChange)
  287. {
  288. IsDirty = true;
  289. }
  290. else
  291. {
  292. IsDirty = false;
  293. }
  294. }
  295. }
  296. }
  297. //是否同步Position
  298. public bool SyncPositionX = true;
  299. public bool SyncPositionY = true;
  300. public bool SyncPositionZ = true;
  301. private bool SynchronizePosition
  302. {
  303. get
  304. {
  305. return SyncPositionX || SyncPositionY || SyncPositionZ;
  306. }
  307. }
  308. //是否同步Rotaion
  309. public bool SyncRotAngleX = true;
  310. public bool SyncRotAngleY = true;
  311. public bool SyncRotAngleZ = true;
  312. private bool SynchronizeRotation
  313. {
  314. get
  315. {
  316. return SyncRotAngleX || SyncRotAngleY || SyncRotAngleZ;
  317. }
  318. }
  319. //是否同步Scale
  320. public bool SyncScaleX = true;
  321. public bool SyncScaleY = true;
  322. public bool SyncScaleZ = true;
  323. private bool SynchronizeScale
  324. {
  325. get
  326. {
  327. return SyncScaleX || SyncScaleY || SyncScaleZ;
  328. }
  329. }
  330. //各个阈值
  331. public float PositionThreshold = PositionThresholdDefault;
  332. [Range(0.001f, 360.0f)]
  333. public float RotAngleThreshold = RotAngleThresholdDefault;
  334. public float ScaleThreshold = ScaleThresholdDefault;
  335. [Tooltip("Sets whether this transform should sync in local space or in world space")]
  336. public bool InLocalSpace = false;
  337. //是否开启插值
  338. public bool Interpolate = true;
  339. public bool UseRelativeTransform;
  340. //是否应用坐标变化
  341. /// <summary>
  342. /// Used to determine who can write to this transform. Server only for this transform.
  343. /// Changing this value alone in a child implementation will not allow you to create a NetworkTransform which can be written to by clients. See the ClientNetworkTransform Sample
  344. /// in the package samples for how to implement a NetworkTransform with client write support.
  345. /// If using different values, please use RPCs to write to the server. Netcode doesn't support client side network variable writing
  346. /// </summary>
  347. public bool CanCommitToTransform
  348. {
  349. get; protected set;
  350. }
  351. /// <summary>
  352. /// Internally used by <see cref="NetworkTransform"/> to keep track of whether this <see cref="NetworkBehaviour"/> derived class instance
  353. /// was instantiated on the server side or not.
  354. /// </summary>
  355. protected bool m_CachedIsServer;
  356. /// <summary>
  357. /// Internally used by <see cref="NetworkTransform"/> to keep track of the <see cref="NetworkManager"/> instance assigned to this
  358. /// this <see cref="NetworkBehaviour"/> derived class instance.
  359. /// </summary>
  360. protected NetworkManager m_CachedNetworkManager;
  361. /// <summary>
  362. /// We have two internal NetworkVariables.
  363. /// One for server authoritative and one for "client/owner" authoritative.
  364. /// </summary>
  365. private readonly NetworkVariable<NetworkTransformState> m_ReplicatedNetworkStateServer = new NetworkVariable<NetworkTransformState>(new NetworkTransformState(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server);
  366. private readonly NetworkVariable<NetworkTransformState> m_ReplicatedNetworkStateOwner = new NetworkVariable<NetworkTransformState>(new NetworkTransformState(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
  367. internal NetworkVariable<NetworkTransformState> ReplicatedNetworkState
  368. {
  369. get
  370. {
  371. if(!IsServerAuthoritative())
  372. {
  373. return m_ReplicatedNetworkStateOwner;
  374. }
  375. return m_ReplicatedNetworkStateServer;
  376. }
  377. }
  378. // Used by both authoritative and non-authoritative instances.
  379. // This represents the most recent local authoritative state.
  380. private NetworkTransformState m_LocalAuthoritativeNetworkState;
  381. private ClientRpcParams m_ClientRpcParams = new ClientRpcParams() { Send = new ClientRpcSendParams() };
  382. private List<ulong> m_ClientIds = new List<ulong>() { 0 };
  383. private BufferedLinearInterpolator<float> m_PositionXInterpolator;
  384. private BufferedLinearInterpolator<float> m_PositionYInterpolator;
  385. private BufferedLinearInterpolator<float> m_PositionZInterpolator;
  386. private BufferedLinearInterpolator<Quaternion> m_RotationInterpolator; // rotation is a single Quaternion since each Euler axis will affect the quaternion's final value
  387. private BufferedLinearInterpolator<float> m_ScaleXInterpolator;
  388. private BufferedLinearInterpolator<float> m_ScaleYInterpolator;
  389. private BufferedLinearInterpolator<float> m_ScaleZInterpolator;
  390. private readonly List<BufferedLinearInterpolator<float>> m_AllFloatInterpolators = new List<BufferedLinearInterpolator<float>>(6);
  391. private NetworkTransformState m_LastSentState;
  392. internal NetworkTransformState GetLastSentState()
  393. {
  394. return m_LastSentState;
  395. }
  396. /// <summary>
  397. /// Calculated when spawned, this is used to offset a newly received non-authority side state by 1 tick duration
  398. /// in order to end the extrapolation for that state's values.
  399. /// </summary>
  400. /// <remarks>
  401. /// Example:
  402. /// NetworkState-A is received, processed, and measurements added
  403. /// NetworkState-A is duplicated (NetworkState-A-Post) and its sent time is offset by the tick frequency
  404. /// One tick later, NetworkState-A-Post is applied to end that delta's extrapolation.
  405. /// <see cref="OnNetworkStateChanged"/> to see how NetworkState-A-Post doesn't get excluded/missed
  406. /// </remarks>
  407. private double m_TickFrequency;
  408. /// <summary>
  409. /// This will try to send/commit the current transform delta states (if any)
  410. /// </summary>
  411. /// <remarks>
  412. /// Only client owners or the server should invoke this method
  413. /// </remarks>
  414. /// <param name="transformToCommit">the transform to be committed</param>
  415. /// <param name="dirtyTime">time it was marked dirty</param>
  416. protected void TryCommitTransformToServer(Transform transformToCommit, double dirtyTime)
  417. {
  418. // Only client owners or the server should invoke this method
  419. if(!IsOwner && !m_CachedIsServer)
  420. {
  421. NetworkLog.LogError($"Non-owner instance, {name}, is trying to commit a transform!");
  422. return;
  423. }
  424. // If we are authority, update the authoritative state
  425. if(CanCommitToTransform)
  426. {
  427. UpdateAuthoritativeState(transform);
  428. }
  429. else // Non-Authority
  430. {
  431. // We are an owner requesting to update our state
  432. if(!m_CachedIsServer)
  433. {
  434. SetStateServerRpc(transformToCommit.position, transformToCommit.rotation, transformToCommit.localScale, false);
  435. }
  436. else // Server is always authoritative (including owner authoritative)
  437. {
  438. SetStateClientRpc(transformToCommit.position, transformToCommit.rotation, transformToCommit.localScale, false);
  439. }
  440. }
  441. }
  442. /// <summary>
  443. /// Authoritative side only
  444. /// If there are any transform delta states, this method will synchronize the
  445. /// state with all non-authority instances.
  446. /// </summary>
  447. private void TryCommitTransform(Transform transformToCommit, double dirtyTime)
  448. {
  449. if(!CanCommitToTransform && !IsOwner)
  450. {
  451. NetworkLog.LogError($"[{name}] is trying to commit the transform without authority!");
  452. return;
  453. }
  454. // If the transform has deltas (returns dirty) then...
  455. if(ApplyTransformToNetworkState(ref m_LocalAuthoritativeNetworkState, dirtyTime, transformToCommit))
  456. {
  457. // ...commit the state
  458. ReplicatedNetworkState.Value = m_LocalAuthoritativeNetworkState;
  459. }
  460. }
  461. private void ResetInterpolatedStateToCurrentAuthoritativeState()
  462. {
  463. var serverTime = NetworkManager.ServerTime.Time;
  464. // TODO: Look into a better way to communicate the entire state for late joining clients.
  465. // Since the replicated network state will just be the most recent deltas and not the entire state.
  466. //m_PositionXInterpolator.ResetTo(m_LocalAuthoritativeNetworkState.PositionX, serverTime);
  467. //m_PositionYInterpolator.ResetTo(m_LocalAuthoritativeNetworkState.PositionY, serverTime);
  468. //m_PositionZInterpolator.ResetTo(m_LocalAuthoritativeNetworkState.PositionZ, serverTime);
  469. //m_RotationInterpolator.ResetTo(Quaternion.Euler(m_LocalAuthoritativeNetworkState.RotAngleX, m_LocalAuthoritativeNetworkState.RotAngleY, m_LocalAuthoritativeNetworkState.RotAngleZ), serverTime);
  470. //m_ScaleXInterpolator.ResetTo(m_LocalAuthoritativeNetworkState.ScaleX, serverTime);
  471. //m_ScaleYInterpolator.ResetTo(m_LocalAuthoritativeNetworkState.ScaleY, serverTime);
  472. //m_ScaleZInterpolator.ResetTo(m_LocalAuthoritativeNetworkState.ScaleZ, serverTime);
  473. // NOTE ABOUT THIS CHANGE:
  474. // !!! This will exclude any scale changes because we currently do not spawn network objects with scale !!!
  475. // Regarding Scale: It will be the same scale as the default scale for the object being spawned.
  476. var position = InLocalSpace ? transform.localPosition : transform.position;
  477. m_PositionXInterpolator.ResetTo(position.x, serverTime);
  478. m_PositionYInterpolator.ResetTo(position.y, serverTime);
  479. m_PositionZInterpolator.ResetTo(position.z, serverTime);
  480. var rotation = InLocalSpace ? transform.localRotation : transform.rotation;
  481. m_RotationInterpolator.ResetTo(rotation, serverTime);
  482. // TODO: (Create Jira Ticket) Synchronize local scale during NetworkObject synchronization
  483. // (We will probably want to byte pack TransformData to offset the 3 float addition)
  484. m_ScaleXInterpolator.ResetTo(transform.localScale.x, serverTime);
  485. m_ScaleYInterpolator.ResetTo(transform.localScale.y, serverTime);
  486. m_ScaleZInterpolator.ResetTo(transform.localScale.z, serverTime);
  487. }
  488. /// <summary>
  489. /// Used for integration testing:
  490. /// Will apply the transform to the LocalAuthoritativeNetworkState and get detailed dirty information returned
  491. /// in the <see cref="NetworkTransformState"/> returned.
  492. /// </summary>
  493. /// <param name="transform">transform to apply</param>
  494. /// <returns>NetworkTransformState</returns>
  495. internal NetworkTransformState ApplyLocalNetworkState(Transform transform)
  496. {
  497. // Since we never commit these changes, we need to simulate that any changes were committed previously and the bitset
  498. // value would already be reset prior to having the state applied
  499. m_LocalAuthoritativeNetworkState.ClearBitSetForNextTick();
  500. // Now check the transform for any threshold value changes
  501. ApplyTransformToNetworkStateWithInfo(ref m_LocalAuthoritativeNetworkState, m_CachedNetworkManager.LocalTime.Time, transform);
  502. // Return the entire state to be used by the integration test
  503. return m_LocalAuthoritativeNetworkState;
  504. }
  505. /// <summary>
  506. /// Used for integration testing
  507. /// </summary>
  508. internal bool ApplyTransformToNetworkState(ref NetworkTransformState networkState, double dirtyTime, Transform transformToUse)
  509. {
  510. return ApplyTransformToNetworkStateWithInfo(ref networkState, dirtyTime, transformToUse);
  511. }
  512. /// <summary>
  513. /// Applies the transform to the <see cref="NetworkTransformState"/> specified.
  514. /// </summary>
  515. private bool ApplyTransformToNetworkStateWithInfo(ref NetworkTransformState networkState, double dirtyTime, Transform transformToUse)
  516. {
  517. var isDirty = false;
  518. var isPositionDirty = false;
  519. var isRotationDirty = false;
  520. var isScaleDirty = false;
  521. var position = InLocalSpace ? transformToUse.localPosition : transformToUse.position;
  522. var rotAngles = InLocalSpace ? transformToUse.localEulerAngles : transformToUse.eulerAngles;
  523. var scale = transformToUse.localScale;
  524. if(InLocalSpace != networkState.InLocalSpace)
  525. {
  526. networkState.InLocalSpace = InLocalSpace;
  527. isDirty = true;
  528. }
  529. if(SyncPositionX && Mathf.Abs(networkState.PositionX - position.x) >= PositionThreshold || networkState.IsTeleportingNextFrame)
  530. {
  531. networkState.PositionX = position.x;
  532. networkState.HasPositionX = true;
  533. isPositionDirty = true;
  534. }
  535. if(SyncPositionY && Mathf.Abs(networkState.PositionY - position.y) >= PositionThreshold || networkState.IsTeleportingNextFrame)
  536. {
  537. networkState.PositionY = position.y;
  538. networkState.HasPositionY = true;
  539. isPositionDirty = true;
  540. }
  541. if(SyncPositionZ && Mathf.Abs(networkState.PositionZ - position.z) >= PositionThreshold || networkState.IsTeleportingNextFrame)
  542. {
  543. networkState.PositionZ = position.z;
  544. networkState.HasPositionZ = true;
  545. isPositionDirty = true;
  546. }
  547. if(SyncRotAngleX && Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleX, rotAngles.x)) >= RotAngleThreshold || networkState.IsTeleportingNextFrame)
  548. {
  549. networkState.RotAngleX = rotAngles.x;
  550. networkState.HasRotAngleX = true;
  551. isRotationDirty = true;
  552. }
  553. if(SyncRotAngleY && Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleY, rotAngles.y)) >= RotAngleThreshold || networkState.IsTeleportingNextFrame)
  554. {
  555. networkState.RotAngleY = rotAngles.y;
  556. networkState.HasRotAngleY = true;
  557. isRotationDirty = true;
  558. }
  559. if(SyncRotAngleZ && Mathf.Abs(Mathf.DeltaAngle(networkState.RotAngleZ, rotAngles.z)) >= RotAngleThreshold || networkState.IsTeleportingNextFrame)
  560. {
  561. networkState.RotAngleZ = rotAngles.z;
  562. networkState.HasRotAngleZ = true;
  563. isRotationDirty = true;
  564. }
  565. if(SyncScaleX && Mathf.Abs(networkState.ScaleX - scale.x) >= ScaleThreshold || networkState.IsTeleportingNextFrame)
  566. {
  567. networkState.ScaleX = scale.x;
  568. networkState.HasScaleX = true;
  569. isScaleDirty = true;
  570. }
  571. if(SyncScaleY && Mathf.Abs(networkState.ScaleY - scale.y) >= ScaleThreshold || networkState.IsTeleportingNextFrame)
  572. {
  573. networkState.ScaleY = scale.y;
  574. networkState.HasScaleY = true;
  575. isScaleDirty = true;
  576. }
  577. if(SyncScaleZ && Mathf.Abs(networkState.ScaleZ - scale.z) >= ScaleThreshold || networkState.IsTeleportingNextFrame)
  578. {
  579. networkState.ScaleZ = scale.z;
  580. networkState.HasScaleZ = true;
  581. isScaleDirty = true;
  582. }
  583. isDirty |= isPositionDirty || isRotationDirty || isScaleDirty;
  584. if(isDirty)
  585. {
  586. networkState.SentTime = dirtyTime;
  587. }
  588. /// We need to set this in order to know when we can reset our local authority state <see cref="Update"/>
  589. /// If our state is already dirty or we just found deltas (i.e. isDirty == true)
  590. networkState.IsDirty |= isDirty;
  591. return isDirty;
  592. }
  593. //Update,将authoritative state修改位置
  594. private void ApplyAuthoritativeState()
  595. {
  596. //
  597. var networkState = ReplicatedNetworkState.Value;
  598. var adjustedPosition = networkState.InLocalSpace ? transform.localPosition : transform.position;
  599. var adjustedRotAngles = networkState.InLocalSpace ? transform.localEulerAngles : transform.eulerAngles;
  600. var adjustedScale = transform.localScale;
  601. InLocalSpace = networkState.InLocalSpace;
  602. //插值
  603. // NOTE ABOUT INTERPOLATING AND THE CODE BELOW:
  604. // We always apply the interpolated state for any axis we are synchronizing even when the state has no deltas
  605. // to assure we fully interpolate to our target even after we stop extrapolating 1 tick later.
  606. var useInterpolatedValue = !networkState.IsTeleportingNextFrame && Interpolate;
  607. if(useInterpolatedValue)
  608. {
  609. if(SyncPositionX)
  610. {
  611. adjustedPosition.x = m_PositionXInterpolator.GetInterpolatedValue();
  612. }
  613. if(SyncPositionY)
  614. {
  615. adjustedPosition.y = m_PositionYInterpolator.GetInterpolatedValue();
  616. }
  617. if(SyncPositionZ)
  618. {
  619. adjustedPosition.z = m_PositionZInterpolator.GetInterpolatedValue();
  620. }
  621. if(SyncScaleX)
  622. {
  623. adjustedScale.x = m_ScaleXInterpolator.GetInterpolatedValue();
  624. }
  625. if(SyncScaleY)
  626. {
  627. adjustedScale.y = m_ScaleYInterpolator.GetInterpolatedValue();
  628. }
  629. if(SyncScaleZ)
  630. {
  631. adjustedScale.z = m_ScaleZInterpolator.GetInterpolatedValue();
  632. }
  633. if(SynchronizeRotation)
  634. {
  635. var interpolatedEulerAngles = m_RotationInterpolator.GetInterpolatedValue().eulerAngles;
  636. if(SyncRotAngleX)
  637. {
  638. adjustedRotAngles.x = interpolatedEulerAngles.x;
  639. }
  640. if(SyncRotAngleY)
  641. {
  642. adjustedRotAngles.y = interpolatedEulerAngles.y;
  643. }
  644. if(SyncRotAngleZ)
  645. {
  646. adjustedRotAngles.z = interpolatedEulerAngles.z;
  647. }
  648. }
  649. }
  650. else
  651. {
  652. if(networkState.HasPositionX)
  653. {
  654. adjustedPosition.x = networkState.PositionX;
  655. }
  656. if(networkState.HasPositionY)
  657. {
  658. adjustedPosition.y = networkState.PositionY;
  659. }
  660. if(networkState.HasPositionZ)
  661. {
  662. adjustedPosition.z = networkState.PositionZ;
  663. }
  664. if(networkState.HasScaleX)
  665. {
  666. adjustedScale.x = networkState.ScaleX;
  667. }
  668. if(networkState.HasScaleY)
  669. {
  670. adjustedScale.y = networkState.ScaleY;
  671. }
  672. if(networkState.HasScaleZ)
  673. {
  674. adjustedScale.z = networkState.ScaleZ;
  675. }
  676. if(networkState.HasRotAngleX)
  677. {
  678. adjustedRotAngles.x = networkState.RotAngleX;
  679. }
  680. if(networkState.HasRotAngleY)
  681. {
  682. adjustedRotAngles.y = networkState.RotAngleY;
  683. }
  684. if(networkState.HasRotAngleZ)
  685. {
  686. adjustedRotAngles.z = networkState.RotAngleZ;
  687. }
  688. }
  689. // NOTE: The below conditional checks for applying axial values are required in order to
  690. // prevent the non-authoritative side from making adjustments when interpolation is off.
  691. // TODO: Determine if we want to enforce, frame by frame, the non-authoritative transform values.
  692. // We would want save the position, rotation, and scale (each individually) after applying each
  693. // authoritative transform state received. Otherwise, the non-authoritative side could make
  694. // changes to an axial value (if interpolation is turned off) until authority sends an update for
  695. // that same axial value. When interpolation is on, the state's values being synchronized are
  696. // always applied each frame.
  697. //位置有变化。或者正在插值和同步位置
  698. if(networkState.HasPositionChange || (useInterpolatedValue && SynchronizePosition))
  699. {
  700. if(InLocalSpace)
  701. {
  702. transform.localPosition = adjustedPosition;
  703. }
  704. else
  705. {
  706. if(UseRelativeTransform)
  707. {
  708. transform.position = adjustedPosition;
  709. }
  710. }
  711. }
  712. // Apply the new rotation if it has changed or we are interpolating and synchronizing rotation
  713. if(networkState.HasRotAngleChange || (useInterpolatedValue && SynchronizeRotation))
  714. {
  715. if(InLocalSpace)
  716. {
  717. transform.localRotation = Quaternion.Euler(adjustedRotAngles);
  718. }
  719. else
  720. {
  721. if(UseRelativeTransform)
  722. {
  723. transform.rotation = Quaternion.Euler(adjustedRotAngles);
  724. }
  725. }
  726. }
  727. // Apply the new scale if it has changed or we are interpolating and synchronizing scale
  728. if(networkState.HasScaleChange || (useInterpolatedValue && SynchronizeScale))
  729. {
  730. transform.localScale = adjustedScale;
  731. }
  732. }
  733. //修改位置
  734. /// <summary>
  735. /// Only non-authoritative instances should invoke this
  736. /// </summary>
  737. private void AddInterpolatedState(NetworkTransformState newState)
  738. {
  739. var sentTime = newState.SentTime;
  740. var currentPosition = newState.InLocalSpace ? transform.localPosition : transform.position;
  741. var currentRotation = newState.InLocalSpace ? transform.localRotation : transform.rotation;
  742. var currentEulerAngles = currentRotation.eulerAngles;
  743. // When there is a change in interpolation or if teleporting, we reset
  744. if((newState.InLocalSpace != InLocalSpace) || newState.IsTeleportingNextFrame)
  745. {
  746. InLocalSpace = newState.InLocalSpace;
  747. var currentScale = transform.localScale;
  748. // we should clear our float interpolators
  749. foreach(var interpolator in m_AllFloatInterpolators)
  750. {
  751. interpolator.Clear();
  752. }
  753. // we should clear our quaternion interpolator
  754. m_RotationInterpolator.Clear();
  755. // Adjust based on which axis changed
  756. if(newState.HasPositionX)
  757. {
  758. m_PositionXInterpolator.ResetTo(newState.PositionX, sentTime);
  759. currentPosition.x = newState.PositionX;
  760. }
  761. if(newState.HasPositionY)
  762. {
  763. m_PositionYInterpolator.ResetTo(newState.PositionY, sentTime);
  764. currentPosition.y = newState.PositionY;
  765. }
  766. if(newState.HasPositionZ)
  767. {
  768. m_PositionZInterpolator.ResetTo(newState.PositionZ, sentTime);
  769. currentPosition.z = newState.PositionZ;
  770. }
  771. // Apply the position
  772. if(newState.InLocalSpace)
  773. {
  774. transform.localPosition = currentPosition;
  775. }
  776. else
  777. {
  778. transform.position = currentPosition;
  779. }
  780. // Adjust based on which axis changed
  781. if(newState.HasScaleX)
  782. {
  783. m_ScaleXInterpolator.ResetTo(newState.ScaleX, sentTime);
  784. currentScale.x = newState.ScaleX;
  785. }
  786. if(newState.HasScaleY)
  787. {
  788. m_ScaleYInterpolator.ResetTo(newState.ScaleY, sentTime);
  789. currentScale.y = newState.ScaleY;
  790. }
  791. if(newState.HasScaleZ)
  792. {
  793. m_ScaleZInterpolator.ResetTo(newState.ScaleZ, sentTime);
  794. currentScale.z = newState.ScaleZ;
  795. }
  796. // Apply the adjusted scale
  797. transform.localScale = currentScale;
  798. // Adjust based on which axis changed
  799. if(newState.HasRotAngleX)
  800. {
  801. currentEulerAngles.x = newState.RotAngleX;
  802. }
  803. if(newState.HasRotAngleY)
  804. {
  805. currentEulerAngles.y = newState.RotAngleY;
  806. }
  807. if(newState.HasRotAngleZ)
  808. {
  809. currentEulerAngles.z = newState.RotAngleZ;
  810. }
  811. // Apply the rotation
  812. currentRotation.eulerAngles = currentEulerAngles;
  813. transform.rotation = currentRotation;
  814. // Reset the rotation interpolator
  815. m_RotationInterpolator.ResetTo(currentRotation, sentTime);
  816. return;
  817. }
  818. // Apply axial changes from the new state
  819. if(newState.HasPositionX)
  820. {
  821. m_PositionXInterpolator.AddMeasurement(newState.PositionX, sentTime);
  822. }
  823. if(newState.HasPositionY)
  824. {
  825. m_PositionYInterpolator.AddMeasurement(newState.PositionY, sentTime);
  826. }
  827. if(newState.HasPositionZ)
  828. {
  829. m_PositionZInterpolator.AddMeasurement(newState.PositionZ, sentTime);
  830. }
  831. if(newState.HasScaleX)
  832. {
  833. m_ScaleXInterpolator.AddMeasurement(newState.ScaleX, sentTime);
  834. }
  835. if(newState.HasScaleY)
  836. {
  837. m_ScaleYInterpolator.AddMeasurement(newState.ScaleY, sentTime);
  838. }
  839. if(newState.HasScaleZ)
  840. {
  841. m_ScaleZInterpolator.AddMeasurement(newState.ScaleZ, sentTime);
  842. }
  843. // With rotation, we check if there are any changes first and
  844. // if so then apply the changes to the current Euler rotation
  845. // values.
  846. if(newState.HasRotAngleChange)
  847. {
  848. if(newState.HasRotAngleX)
  849. {
  850. currentEulerAngles.x = newState.RotAngleX;
  851. }
  852. if(newState.HasRotAngleY)
  853. {
  854. currentEulerAngles.y = newState.RotAngleY;
  855. }
  856. if(newState.HasRotAngleZ)
  857. {
  858. currentEulerAngles.z = newState.RotAngleZ;
  859. }
  860. currentRotation.eulerAngles = currentEulerAngles;
  861. m_RotationInterpolator.AddMeasurement(currentRotation, sentTime);
  862. }
  863. }
  864. /// <summary>
  865. /// Only non-authoritative instances should invoke this method
  866. /// </summary>
  867. private void OnNetworkStateChanged(NetworkTransformState oldState, NetworkTransformState newState)
  868. {
  869. if(!NetworkObject.IsSpawned)
  870. {
  871. return;
  872. }
  873. if(CanCommitToTransform)
  874. {
  875. // we're the authority, we ignore incoming changes
  876. return;
  877. }
  878. if(Interpolate)
  879. {
  880. // Add measurements for the new state's deltas
  881. AddInterpolatedState(newState);
  882. }
  883. }
  884. /// <summary>
  885. /// Will set the maximum interpolation boundary for the interpolators of this <see cref="NetworkTransform"/> instance.
  886. /// This value roughly translates to the maximum value of 't' in <see cref="Mathf.Lerp(float, float, float)"/> and
  887. /// <see cref="Mathf.LerpUnclamped(float, float, float)"/> for all transform elements being monitored by
  888. /// <see cref="NetworkTransform"/> (i.e. Position, Rotation, and Scale)
  889. /// </summary>
  890. /// <param name="maxInterpolationBound">Maximum time boundary that can be used in a frame when interpolating between two values</param>
  891. public void SetMaxInterpolationBound(float maxInterpolationBound)
  892. {
  893. //m_PositionXInterpolator.MaxInterpolationBound = maxInterpolationBound;
  894. //m_PositionYInterpolator.MaxInterpolationBound = maxInterpolationBound;
  895. //m_PositionZInterpolator.MaxInterpolationBound = maxInterpolationBound;
  896. //m_RotationInterpolator.MaxInterpolationBound = maxInterpolationBound;
  897. //m_ScaleXInterpolator.MaxInterpolationBound = maxInterpolationBound;
  898. //m_ScaleYInterpolator.MaxInterpolationBound = maxInterpolationBound;
  899. //m_ScaleZInterpolator.MaxInterpolationBound = maxInterpolationBound;
  900. }
  901. /// <summary>
  902. /// Create interpolators when first instantiated to avoid memory allocations if the
  903. /// associated NetworkObject persists (i.e. despawned but not destroyed or pools)
  904. /// </summary>
  905. private void Awake()
  906. {
  907. // Rotation is a single Quaternion since each Euler axis will affect the quaternion's final value
  908. m_RotationInterpolator = new BufferedLinearInterpolatorQuaternion();
  909. // All other interpolators are BufferedLinearInterpolatorFloats
  910. m_PositionXInterpolator = new BufferedLinearInterpolatorFloat();
  911. m_PositionYInterpolator = new BufferedLinearInterpolatorFloat();
  912. m_PositionZInterpolator = new BufferedLinearInterpolatorFloat();
  913. m_ScaleXInterpolator = new BufferedLinearInterpolatorFloat();
  914. m_ScaleYInterpolator = new BufferedLinearInterpolatorFloat();
  915. m_ScaleZInterpolator = new BufferedLinearInterpolatorFloat();
  916. // Used to quickly iteration over the BufferedLinearInterpolatorFloat
  917. // instances
  918. if(m_AllFloatInterpolators.Count == 0)
  919. {
  920. m_AllFloatInterpolators.Add(m_PositionXInterpolator);
  921. m_AllFloatInterpolators.Add(m_PositionYInterpolator);
  922. m_AllFloatInterpolators.Add(m_PositionZInterpolator);
  923. m_AllFloatInterpolators.Add(m_ScaleXInterpolator);
  924. m_AllFloatInterpolators.Add(m_ScaleYInterpolator);
  925. m_AllFloatInterpolators.Add(m_ScaleZInterpolator);
  926. }
  927. }
  928. /// <inheritdoc/>
  929. public override void OnNetworkSpawn()
  930. {
  931. m_CachedIsServer = IsServer;
  932. m_CachedNetworkManager = NetworkManager;
  933. m_TickFrequency = 1.0 / NetworkManager.NetworkConfig.TickRate;
  934. Initialize();
  935. // This assures the initial spawning of the object synchronizes all connected clients
  936. // with the current transform values. This should not be placed within Initialize since
  937. // that can be invoked when ownership changes.
  938. if(CanCommitToTransform)
  939. {
  940. var currentPosition = InLocalSpace ? transform.localPosition : transform.position;
  941. var currentRotation = InLocalSpace ? transform.localRotation : transform.rotation;
  942. // Teleport to current position
  943. SetStateInternal(currentPosition, currentRotation, transform.localScale, true);
  944. // Force the state update to be sent
  945. TryCommitTransform(transform, m_CachedNetworkManager.LocalTime.Time);
  946. }
  947. }
  948. /// <inheritdoc/>
  949. public override void OnNetworkDespawn()
  950. {
  951. ReplicatedNetworkState.OnValueChanged -= OnNetworkStateChanged;
  952. }
  953. /// <inheritdoc/>
  954. public override void OnDestroy()
  955. {
  956. base.OnDestroy();
  957. m_ReplicatedNetworkStateServer.Dispose();
  958. m_ReplicatedNetworkStateOwner.Dispose();
  959. }
  960. /// <inheritdoc/>
  961. public override void OnGainedOwnership()
  962. {
  963. Initialize();
  964. }
  965. /// <inheritdoc/>
  966. public override void OnLostOwnership()
  967. {
  968. Initialize();
  969. }
  970. /// <summary>
  971. /// Initializes NetworkTransform when spawned and ownership changes.
  972. /// </summary>
  973. private void Initialize()
  974. {
  975. if(!IsSpawned)
  976. {
  977. return;
  978. }
  979. CanCommitToTransform = IsServerAuthoritative() ? IsServer : IsOwner;
  980. var replicatedState = ReplicatedNetworkState;
  981. m_LocalAuthoritativeNetworkState = replicatedState.Value;
  982. if(CanCommitToTransform)
  983. {
  984. replicatedState.OnValueChanged -= OnNetworkStateChanged;
  985. }
  986. else
  987. {
  988. replicatedState.OnValueChanged += OnNetworkStateChanged;
  989. // In case we are late joining
  990. ResetInterpolatedStateToCurrentAuthoritativeState();
  991. }
  992. }
  993. /// <summary>
  994. /// Directly sets a state on the authoritative transform.
  995. /// Owner clients can directly set the state on a server authoritative transform
  996. /// This will override any changes made previously to the transform
  997. /// This isn't resistant to network jitter. Server side changes due to this method won't be interpolated.
  998. /// The parameters are broken up into pos / rot / scale on purpose so that the caller can perturb
  999. /// just the desired one(s)
  1000. /// </summary>
  1001. /// <param name="posIn"></param> new position to move to. Can be null
  1002. /// <param name="rotIn"></param> new rotation to rotate to. Can be null
  1003. /// <param name="scaleIn">new scale to scale to. Can be null</param>
  1004. /// <param name="shouldGhostsInterpolate">Should other clients interpolate this change or not. True by default</param>
  1005. /// new scale to scale to. Can be null
  1006. /// <exception cref="Exception"></exception>
  1007. public void SetState(Vector3? posIn = null, Quaternion? rotIn = null, Vector3? scaleIn = null, bool shouldGhostsInterpolate = true)
  1008. {
  1009. if(!IsSpawned)
  1010. {
  1011. return;
  1012. }
  1013. // Only the server or owner can invoke this method
  1014. if(!IsOwner && !m_CachedIsServer)
  1015. {
  1016. throw new Exception("Non-owner client instance cannot set the state of the NetworkTransform!");
  1017. }
  1018. Vector3 pos = posIn == null ? InLocalSpace ? transform.localPosition : transform.position : posIn.Value;
  1019. Quaternion rot = rotIn == null ? InLocalSpace ? transform.localRotation : transform.rotation : rotIn.Value;
  1020. Vector3 scale = scaleIn == null ? transform.localScale : scaleIn.Value;
  1021. if(!CanCommitToTransform)
  1022. {
  1023. // Preserving the ability for owner authoritative mode to accept state changes from server
  1024. if(m_CachedIsServer)
  1025. {
  1026. m_ClientIds[0] = OwnerClientId;
  1027. m_ClientRpcParams.Send.TargetClientIds = m_ClientIds;
  1028. SetStateClientRpc(pos, rot, scale, !shouldGhostsInterpolate, m_ClientRpcParams);
  1029. }
  1030. else // Preserving the ability for server authoritative mode to accept state changes from owner
  1031. {
  1032. SetStateServerRpc(pos, rot, scale, !shouldGhostsInterpolate);
  1033. }
  1034. return;
  1035. }
  1036. SetStateInternal(pos, rot, scale, !shouldGhostsInterpolate);
  1037. }
  1038. //修改位置
  1039. /// <summary>
  1040. /// Authoritative only method
  1041. /// Sets the internal state (teleporting or just set state) of the authoritative
  1042. /// transform directly.
  1043. /// </summary>
  1044. private void SetStateInternal(Vector3 pos, Quaternion rot, Vector3 scale, bool shouldTeleport)
  1045. {
  1046. if(InLocalSpace)
  1047. {
  1048. transform.localPosition = pos;
  1049. transform.localRotation = rot;
  1050. }
  1051. else
  1052. {
  1053. transform.position = pos;
  1054. transform.rotation = rot;
  1055. }
  1056. transform.localScale = scale;
  1057. m_LocalAuthoritativeNetworkState.IsTeleportingNextFrame = shouldTeleport;
  1058. TryCommitTransform(transform, m_CachedNetworkManager.LocalTime.Time);
  1059. }
  1060. //修改位置
  1061. /// <summary>
  1062. /// Invoked by <see cref="SetState"/>, allows a non-owner server to update the transform state
  1063. /// </summary>
  1064. /// <remarks>
  1065. /// Continued support for client-driven server authority model
  1066. /// </remarks>
  1067. [ClientRpc]
  1068. private void SetStateClientRpc(Vector3 pos, Quaternion rot, Vector3 scale, bool shouldTeleport, ClientRpcParams clientRpcParams = default)
  1069. {
  1070. // Server dictated state is always applied
  1071. transform.position = pos;
  1072. transform.rotation = rot;
  1073. transform.localScale = scale;
  1074. m_LocalAuthoritativeNetworkState.IsTeleportingNextFrame = shouldTeleport;
  1075. TryCommitTransform(transform, m_CachedNetworkManager.LocalTime.Time);
  1076. }
  1077. //修改位置
  1078. /// <summary>
  1079. /// Invoked by <see cref="SetState"/>, allows an owner-client update the transform state
  1080. /// </summary>
  1081. /// <remarks>
  1082. /// Continued support for client-driven server authority model
  1083. /// </remarks>
  1084. [ServerRpc]
  1085. private void SetStateServerRpc(Vector3 pos, Quaternion rot, Vector3 scale, bool shouldTeleport)
  1086. {
  1087. // server has received this RPC request to move change transform. give the server a chance to modify or even reject the move
  1088. if(OnClientRequestChange != null)
  1089. {
  1090. (pos, rot, scale) = OnClientRequestChange(pos, rot, scale);
  1091. }
  1092. transform.position = pos;
  1093. transform.rotation = rot;
  1094. transform.localScale = scale;
  1095. m_LocalAuthoritativeNetworkState.IsTeleportingNextFrame = shouldTeleport;
  1096. TryCommitTransform(transform, m_CachedNetworkManager.LocalTime.Time);
  1097. }
  1098. /// <summary>
  1099. /// Will update the authoritative transform state if any deltas are detected.
  1100. /// This will also reset the m_LocalAuthoritativeNetworkState if it is still dirty
  1101. /// but the replicated network state is not.
  1102. /// </summary>
  1103. /// <param name="transformSource">transform to be updated</param>
  1104. private void UpdateAuthoritativeState(Transform transformSource)
  1105. {
  1106. // If our replicated state is not dirty and our local authority state is dirty, clear it.
  1107. if(!ReplicatedNetworkState.IsDirty() && m_LocalAuthoritativeNetworkState.IsDirty)
  1108. {
  1109. m_LastSentState = m_LocalAuthoritativeNetworkState;
  1110. // Now clear our bitset and prepare for next network tick state update
  1111. m_LocalAuthoritativeNetworkState.ClearBitSetForNextTick();
  1112. }
  1113. TryCommitTransform(transformSource, m_CachedNetworkManager.LocalTime.Time);
  1114. }
  1115. /// <inheritdoc/>
  1116. /// <remarks>
  1117. /// If you override this method, be sure that:
  1118. /// - Non-owners always invoke this base class method when using interpolation.
  1119. /// - Authority can opt to use <see cref="TryCommitTransformToServer"/> in place of invoking this base class method.
  1120. /// - Non-authority owners can use <see cref="TryCommitTransformToServer"/> but should still invoke the this base class method when using interpolation.
  1121. /// </remarks>
  1122. protected virtual void Update()
  1123. {
  1124. if(!IsSpawned)
  1125. {
  1126. return;
  1127. }
  1128. // If we are authority, update the authoritative state
  1129. if(CanCommitToTransform)
  1130. {
  1131. UpdateAuthoritativeState(transform);
  1132. }
  1133. else // Non-Authority
  1134. {
  1135. if(Interpolate)
  1136. {
  1137. var serverTime = NetworkManager.ServerTime;
  1138. var cachedDeltaTime = Time.deltaTime;
  1139. var cachedServerTime = serverTime.Time;
  1140. var cachedRenderTime = serverTime.TimeTicksAgo(1).Time;
  1141. foreach(var interpolator in m_AllFloatInterpolators)
  1142. {
  1143. interpolator.Update(cachedDeltaTime, cachedRenderTime, cachedServerTime);
  1144. }
  1145. m_RotationInterpolator.Update(cachedDeltaTime, cachedRenderTime, cachedServerTime);
  1146. }
  1147. ApplyAuthoritativeState();
  1148. }
  1149. }
  1150. /// <summary>
  1151. /// Teleport the transform to the given values without interpolating
  1152. /// </summary>
  1153. /// <param name="newPosition"></param> new position to move to.
  1154. /// <param name="newRotation"></param> new rotation to rotate to.
  1155. /// <param name="newScale">new scale to scale to.</param>
  1156. /// <exception cref="Exception"></exception>
  1157. public void Teleport(Vector3 newPosition, Quaternion newRotation, Vector3 newScale)
  1158. {
  1159. if(!CanCommitToTransform)
  1160. {
  1161. throw new Exception("Teleporting on non-authoritative side is not allowed!");
  1162. }
  1163. // Teleporting now is as simple as setting the internal state and passing the teleport flag
  1164. SetStateInternal(newPosition, newRotation, newScale, true);
  1165. }
  1166. /// <summary>
  1167. /// Override this method and return false to switch to owner authoritative mode
  1168. /// </summary>
  1169. /// <returns>(<see cref="true"/> or <see cref="false"/>) where when false it runs as owner-client authoritative</returns>
  1170. protected virtual bool OnIsServerAuthoritative()
  1171. {
  1172. return true;
  1173. }
  1174. /// <summary>
  1175. /// Used by <see cref="NetworkRigidbody"/> to determines if this is server or owner authoritative.
  1176. /// </summary>
  1177. internal bool IsServerAuthoritative()
  1178. {
  1179. return OnIsServerAuthoritative();
  1180. }
  1181. }