public override void OnStart() { /// TEST - this code fixed startup rendering, but not fully tested. Likely needs to stay here. ChangeState(new StateChangeInfo(initialState, transform.parent ? transform.parent.GetComponent <Mount>() : null, true)); base.OnStart(); respawnStateInfo = new StateChangeInfo( respawnState, transform.parent ? transform.parent.GetComponent <Mount>() : null, transform.localPosition, transform.localRotation, null, true); /// Cache values for mountType serialization. We get the total possible mount options from this objects SyncState var mountableToCount = (mountableTo.mask).CountTrueBits(out indexToMountTypeId, MountSettings.mountTypeCount); bitsForMountType = mountableToCount.GetBitsForMaxValue(); for (int i = 0; i < mountableToCount; ++i) { #if UNITY_EDITOR || DEVELOPMENT_BUILD if (mountTypeIdToIndex.ContainsKey(indexToMountTypeId[i])) { Debug.LogError(name + " " + photonView.OwnerActorNr + " Mount Key Exists: " + indexToMountTypeId[i] + " i:" + i + " count: " + mountableToCount); } #endif mountTypeIdToIndex.Add(indexToMountTypeId[i], i); } }
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; }
/// <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 (photonView.IsMine && iSpawnController != null && iSpawnController.SupressStateMask != ~ObjState.Despawned) //{ // Debug.Log("<color=red>Suppressing State change due to spawn timer</color>"); // stateChangeInfo.objState &= iSpawnController.SupressStateMask; //} //if (GetComponent<SyncPickup>()) // Debug.LogError(Time.time + " " + name + " <b>ChangeState " + stateChangeInfo + "</b> par: " + currentMount + " tr: " + transform.position + " rb: " + Rb.position); 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 && (newState & ObjState.Anchored) == 0) { 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) { //if (GetComponent<SyncPickup>()) // Debug.LogError("NO CHANGE"); return; } currentState.state = newState; var prevMount = currentMount; currentMount = newMount; //if (GetComponent<SyncPickup>()) // Debug.LogError("<b>ChangeState </b>" + currentState + " par: " + currentMount); bool nowMounted = (newState & ObjState.Mounted) != 0; bool mountInfoWasCulled = nowMounted && ReferenceEquals(newMount, null); // TODO: Might not be needed. /// Handling for attached without a valid Mount - Test for if we have a reference to a Mount, but it is null (Unity destroyed). Sets to hard null and reruns this method. if (nowMounted && !mountInfoWasCulled && newMount == null) { Debug.LogError("Invalid Mount!"); InvalidMountHandler(newState, newMount, force); return; } if (IsMine) { if (mountChanged || respawn) { //Debug.LogError("TELEPORT"); for (int i = 0; i < flagTeleportCallbacks.Count; ++i) { flagTeleportCallbacks[i].FlagTeleport(); } } } /// The State is mounted /*else*/ if (mountChanged) { /// Attaching to a mount // If Attached bit is true if (nowMounted) { #if PUN_2_OR_NEWER //if (GetComponent<SyncPickup>() /*&& newState == (ObjState)(15)*/) // Debug.LogError(Time.time + " " + name + " " + newState + " ATTACH " + newMount.name + " "); currentState.mountToViewID = newMount.ViewID; currentState.mountTypeId = newMount.mountType.id; #endif transform.parent = newMount.transform; // If anchor bit is true if ((newState & ObjState.AnchoredPosition) != 0) { transform.localPosition = new Vector3(); //Debug.LogError("<b>Anchor Pos</b> " + transform.parent.name + " " + transform.localPosition); } // If anchor bit is true if ((newState & ObjState.AnchoredRotation) != 0) { transform.localRotation = new Quaternion(); //Debug.Log("<b>Anchor Rot</b>"); } } /// Detaching from a mount else { //if (GetComponent<SyncPickup>() /*&& newState == (ObjState)(15)*/) // Debug.Log(Time.time + " " + name + " " + newState + " DETTACH " + (newMount ? newMount.name : " null")); currentState.mountToViewID = null; currentState.mountTypeId = null; transform.parent = null; } // TODO: Add handling for dismounting returning ownership to scene? // Ownership changes are deferred, to let the current tick finish processing before changing Owner/Controller. if (autoOwnerChange && newMount && !ReferenceEquals(oldMount, newMount)) { ChangeOwnerToParentMountsOwner(); } Mount.ChangeMounting(this, prevMount, newMount); } var pos = stateChangeInfo.offsetPos; var rot = stateChangeInfo.offsetRot; var vel = stateChangeInfo.velocity; if (rot.HasValue) { //if (GetComponent<SyncPickup>()) // Debug.Log(Time.time + " " + name + " STATE ROT APPLY " + rot.Value); transform.rotation = rot.Value; } // TODO: Move pos/rot handling to virtual method if (pos.HasValue) { //if (GetComponent<SyncPickup>()) // Debug.Log(Time.time + " " + name + " STATE POS APPLY " + pos.Value); transform.position = pos.Value; } if (vel.HasValue) { var rb = netObj.Rb; if (rb) { rb.velocity = vel.Value; } else { var rb2d = netObj.Rb2D; if (rb2d) { rb2d.velocity = vel.Value; } } } ///// Apply the vector values //this.ApplyVectors(stateChangeInfo, prevParent, onTeleportCallbacks); //Debug.Log(Time.time + " " + stateChangeInfo + " mountisactive? " + (currentMount ? currentMount.isActiveAndEnabled.ToString() : "null")); if (mountChanged || stateChanged || force) { //if (GetComponent<SyncPickup>()) // Debug.Log(Time.time + " " + name + " " + photonView.OwnerActorNr + " <b>NEW STATE: " + newState + "</b> ready? " + netObj.AllObjsAreReady); /// Send out callbacks for (int i = 0; i < onStateChangeCallbacks.Count; ++i) { onStateChangeCallbacks[i].OnStateChange(newState, oldState, transform, currentMount, netObjIsReady); } } }