public void DrawActorDebugGUI(VoosActor actor) { using (new Util.GUILayoutFrobArea(actor.transform.position, 100, 500)) { PhotonView photonView = PhotonView.Get(actor); if (photonView == null) { return; } PlayerBody playerBody = actor.GetPlayerBody(); //string pbodyInfo = playerBody == null ? "" : $"Claimed? {playerBody.IsClaimed()} ..play mode? {playerBody.GetIsClaimerPlaying()}"; string color = photonView.isMine ? "yellow" : "grey"; string hash = actor.GetName().Substring(0, 9); bool locked = actor.IsLockedByAnother() || actor.IsLockWantedLocally(); string lockingString = locked ? " LOCKED" : ""; string lastPos = actor.unrel == null ? "" : actor.unrel.lastPosition.x.ToFourDecimalPlaces(); GUILayout.Label($@"<color={color}>{actor.GetDisplayName()} rot: {actor.GetRotation().ToFourDecimalPlaces()} last unrel: {actor.lastUnreliableUpdateTime} lastPX: {lastPos}</color>".Trim()); GUILayout.Toggle(actor.GetReplicantCatchUpMode(), "Catchup?"); actor.debug = GUILayout.Toggle(actor.debug, "Debug"); // owner: {photonView.ownerId}{lockingString} // {hash} view {actor.reliablePhotonView.viewID} // X: {actor.transform.position.x.ToFourDecimalPlaces()} // lastRBMPX: {actor.lastRBMovedPos.x.ToFourDecimalPlaces()} } }
// Tries to migrate the user to the target actor. // If targetActor == null, the user will be actorless. public void MigrateUserTo(VoosActor targetActor) { PlayMain pm = playMain.GetComponent <PlayMain>(); PlayerBody targetPlayerBody = targetActor?.GetPlayerBody(); if (targetActor != null && (!targetActor.GetIsPlayerControllable() || null == targetPlayerBody)) { targetActor.SetIsPlayerControllable(true); targetPlayerBody = targetActor.GetPlayerBody(); Debug.Assert(targetPlayerBody != null, "MigrateUserTo could not add a PlayerBody to target actor."); } pm.SetPlayerBody(targetPlayerBody); // If we are in play mode, we need to reparent the user body. // Otherwise this will be done later, when we enter play mode. if (!InEditMode()) { userBody.transform.SetParent(playMain.bodyParent); userBody.transform.localPosition = Vector3.zero; userBody.transform.localRotation = Quaternion.identity; } if (targetActor != null) { targetActor.RequestOwnership(); } VoosActor playMainActor = pm.GetPlayerActor(); Debug.Assert(targetActor == playMainActor, "MigrateUserTo didn't succeed, we wanted targetActor to be " + targetActor + " but PlayMain still has " + playMain); }
// Ownership on collision logic. We only request ownership when the local // player's body hits another actor. Before, the logic was when *any* local // actor (ie. actor owned by us) hit another actor, we infected ownership. But // this resulted in excessive RPCs (ownership requests), like in the "ball of // pugs" example. private void OnCollisionEnter(Collision collision) { bool isLocalPlayerBody = photonView != null && photonView.isMine && this.actor.GetPlayerBody() != null; if (!isLocalPlayerBody) { return; } // Of course, only worry about other actors. VoosActor otherActor = collision.gameObject.GetComponent <VoosActor>(); if (otherActor == null) { return; } // Record otherActor.realTimeOfLastCollisionWithLocalPlayer = Time.realtimeSinceStartup; // Also, never take over other player bodies. PlayerBody otherPlayerBody = otherActor.GetPlayerBody(); if (otherPlayerBody != null) { return; } // Try to request ownership, since it's better for the player to own objects // it's colliding with, like a soccer ball. But if it's locked by another, // then don't bother. if (!otherActor.IsLocallyOwned()) { otherActor.RequestOwnership(VoosEngine.OwnRequestReason.Collision); } }