public StateChangeInfo(StateChangeInfo src) { this.objState = src.objState; this.mount = src.mount; this.offsetPos = src.offsetPos; this.offsetRot = src.offsetRot; this.velocity = src.velocity; this.force = src.force; }
public override void OnAwake() { base.OnAwake(); syncTransform = GetComponent <SyncTransform>(); respawnStateInfo = new StateChangeInfo( respawnState, transform.parent ? transform.parent.GetComponent <Mount>() : null, transform.localPosition, transform.localEulerAngles, null, true); transform.GetNestedComponentsInChildren(onStateChangeCallbacks); transform.GetComponents(onTeleportCallbacks); mountsLookup = netObj.GetComponent <MountsLookup>(); }
/// <summary> /// Apply the vectors (offset, pos, rot, velocity) in StateChangeInfo to the syncState object. Returns true if teleport is required for change. /// </summary> public static void ApplyVectors(this SyncState syncState, StateChangeInfo stateChangeInfo, Transform prevParent, List <IOnTeleport> callbacks) { Transform transform = syncState.transform; /// For respawns just the pos/rot values are NET relative to he old parent. //if (stateChangeInfo.respawn) //{ // var mount = stateChangeInfo.mount; // var localPos = stateChangeInfo.offsetPos; // var localRot = stateChangeInfo.offsetRot; // int cnt = callbacks.Count; // for (int i = 0; i < cnt; i++) // callbacks[i].OnTeleport(); // transform.parent = (mount) ? mount.transform : null; // if (localPos.HasValue) // transform.localPosition = localPos.Value; // if (localRot.HasValue) // transform.localEulerAngles = localRot.Value; // return; //} //else //{ //if (stateChangeInfo.offsetPos.HasValue) //{ // { // var parRot = prevParent ? prevParent.rotation : transform.rotation; // /// TODO: offset and vel likely should be part of the ChangeState itself // /// Apply offset before changing state // var localOffset = stateChangeInfo.offsetPos; // //Debug.Log(Time.time + " " + transform.name + " Dequeue " + transform.position + " " + transform.position + prevParent.rotation * localOffset); // //transform.position = transform.position + prevParent.rotation * localOffset.Value; // Vector3? pos = localOffset.HasValue ? (transform.position + parRot * localOffset.Value) : (Vector3?)null; // Vector3? rot = stateChangeInfo.offsetRot; // //int cnt = callbacks.Count; // //for (int i = 0; i < cnt; i++) // // callbacks[i].OnTeleport(); // transform.parent = null; // if (pos.HasValue) // transform.position = pos.Value; // if (rot.HasValue) // transform.eulerAngles = rot.Value; // } //} //} if (stateChangeInfo.velocity.HasValue) { var rb = syncState.Rb; if (rb) { if (!rb.isKinematic) { rb.velocity = ((prevParent) ? prevParent.rotation : rb.rotation) * stateChangeInfo.velocity.Value; } } else { var rb2d = syncState.Rb2d; if (rb2d) { if (!rb2d.isKinematic) { rb2d.velocity = stateChangeInfo.velocity.Value; } } } } }
/// <summary> /// Call this method to change the state of this object. This state will be synced over the network, /// and callbacks will trigger locally and remotely. Typically it is preferred to call QueueStateChange(), /// which will defer the ChangeState application until the appropriate timing. /// </summary> protected virtual void ChangeState(StateChangeInfo stateChangeInfo) { if (!gameObject) { Debug.LogWarning(name + " has been destroyed. Will not try to change state."); return; } //if (IsMine) // //if (GetComponent<SyncVitals>()) // { // if (stateChangeInfo.objState == ObjState.Visible) // Debug.Log(Time.time + " " + stateChangeInfo); // else // Debug.Log(Time.time + " <b>" + stateChangeInfo + "</b>"); // } var oldState = currentState.state; var oldMount = currentMount; var newState = stateChangeInfo.objState; var newMount = stateChangeInfo.mount; bool respawn; /// Assuming first Visible after a despawn is a Respawn - this is here to handle lost teleport packets if (autoReset && oldState == ObjState.Despawned && newState != ObjState.Despawned) { stateChangeInfo = new StateChangeInfo(respawnStateInfo) { objState = stateChangeInfo.objState }; respawn = true; } else { respawn = false; } var force = stateChangeInfo.force; bool stateChanged = newState != oldState; bool mountChanged = oldMount != newMount; var prevParent = transform.parent; /// Test nothing has changed if (!force && !stateChanged && !mountChanged) { return; } bool nowAttached = (newState & ObjState.Attached) != 0; /// Handling for attached without a valid Mount if (nowAttached && !newMount) { //Debug.LogError(name + " Attached with a null mount! " + newState); InvalidMountHandler(newState, newMount, force); return; } if (IsMine) { if (mountChanged || respawn) { ////Debug.LogError("TELEPORT"); //for (int i = 0; i < onTeleportCallbacks.Count; ++i) // onTeleportCallbacks[i].OnTeleport(); } } /// The State is attached /*else*/ if (mountChanged) { /// Attaching to a mount // If Attached bit is true if (nowAttached) { //Debug.Log(Time.time + " " + name + " ATTACH " + newMount.name + " "); currentState.attachedToNetId = newMount.NetObjId; currentState.attachedToMountTypeId = newMount.mountType.id; transform.parent = newMount.transform; bool nowMounted = (newState & ObjState.Mounted) != 0; // If Mounted bit is true if (nowMounted) { //Debug.Log(name + " Hard Mounting Origin"); transform.localPosition = new Vector3(); transform.localRotation = new Quaternion(); } } /// Detaching from a mount else { //Debug.Log(Time.time + " " + name + " DEATTACH "); currentState.attachedToNetId = null; currentState.attachedToMountTypeId = null; transform.parent = null; } Mount.ChangeMounting(this, newMount); } var pos = stateChangeInfo.offsetPos; var rot = stateChangeInfo.offsetRot; var vel = stateChangeInfo.velocity; if (rot.HasValue) { //Debug.Log(Time.time + " " + name + " STATE ROT APPLY " + rot.Value); transform.localEulerAngles = rot.Value; } if (pos.HasValue) { if (respawn) { transform.localPosition = pos.Value; } else { var parRot = prevParent ? prevParent.rotation : transform.rotation; transform.position = transform.position + parRot * pos.Value; } } if (vel.HasValue) { var rb = syncState.Rb; if (rb) { if (!rb.isKinematic) { rb.velocity = ((prevParent) ? prevParent.rotation : rb.rotation) * vel.Value; } } else { var rb2d = syncState.Rb2d; if (rb2d) { if (!rb2d.isKinematic) { rb2d.velocity = stateChangeInfo.velocity.Value; } } } } currentState.state = newState; currentMount = newMount; ///// Apply the vector values //this.ApplyVectors(stateChangeInfo, prevParent, onTeleportCallbacks); /// Send out callbacks for (int i = 0; i < onStateChangeCallbacks.Count; ++i) { onStateChangeCallbacks[i].OnStateChange(newState, transform, currentMount, netObjIsReady); } }