How to transfer a VR button ownership using Photon2? - unity3d

I am currently working on a project and I want to use several buttons in my multiplayer game.
Unfortunately the button can only be pushed locally and it's not synced over the network.
For some reasons the game doesn't trigger the script that should transfer the ownership to the player
I don't really know what's going on and why this isn't triggered ...
I already tried to ad photon tranform views on the moving part and the button itself but without results
private void OnTriggerEnter(Collider other)
{
if(other.name == "LHand" || other.name == "RHand")
{
ChangeOwnership(other);
}
print("trigger entered but not a hand");
}
public void ChangeOwnership(Collider col)
{
if (GetComponent<PhotonView>().Owner != col.GetComponent<PhotonView>().Owner)
{
GetComponent<PhotonView>().TransferOwnership(col.GetComponent<PhotonView>().Owner);
print("changed ownership to: " + col.GetComponent<PhotonView>().Owner);
}
}
If the trigger is actually entered this should show the player as the owner and not the scene...
So if someone has a clue about this I'll take it ...

Related

After pause menu score doesn't work anymore

does anyone know how to fix this? In my unity game when I go to pause menu and then continue playing, my scoreboard stops updating. I have two scoreboards, one in game and one in pause menu. The one in pause menu works well and updates but the one in game freezes after once visited in pause menu.
Here is my pausecodes and codes to add money (score):
public void PauseGame()
{
Time.timeScale = 0;
}
public void UnPauseGame()
{
Time.timeScale = 1;
}
}
if (collision.gameObject.tag == "Respawn") // When player lifts fish up
{
Destroy(this.gameObject);
// TODO: Player gets money (points) when this happens
textManager.instance.AddMoney();
Debug.Log("Add money");
}
public class textManager : MonoBehaviour
{
public static textManager instance;
public Text moneyText;
public int money;
private void Awake()
{
instance = this;
}
// Start is called before the first frame update
void Start()
{
Data data = SaveSystem.LoadData();
money = data.balance;
moneyText.text = "Balance: " + money.ToString() + " $";
}
public void AddMoney()
{
money = money + 10;
moneyText.text = "Balance: " + money.ToString() + " $";
SaveSystem.SaveData(this);
}
public int findMoney()
{
return money;
}
}
Please ask more info if needed.
I have tried to delete the one scoreboard in pause menu and after that the in-game pause menu started working right, but I would like to have still that other scoreboard too.
if (collision.gameObject.tag == "Respawn") // When player lifts fish up
{
// TODO: Player gets money (points) when this happens
textManager.instance.AddMoney();
Debug.Log("Add money");
Destroy(this.gameObject);
}
As I said this is the fix for what you posted as for the pause unpause problem you have to post the actual code where you do the pause unpause behavior so can people help you out my friend. As for what you posted what you've been doing is destroying the script just before excuting the call to textManager.instance.AddMoney(); and this will never run in the order you set in your code.
The scope of a static field is global, this means there can only be one.
Your textManager (side note: a classes first letter has to be upper case) is certainly attached to multiple GameObjects, once to the object displaying the score in the scene UI and once to a UI element in the pause menu.
As soon as you pause your game the first time, the TextManager attached to the object in the pause menu will run Awake() and the instance (please capitalise your properties as well) will be overriden and the reference to the ingame TextManager gets discarded.
The sloppy fix is re-initializing the ingame TextManager when you unpause the game, assigning it to be the Instance again. I'd not recommend doing that though.
The better solution is to implement an event on the player that gets triggered when the score changes and making the player instance a Singleton object since there will be only one player in all circumstances.
The UI elements displaying the score can then subscribe to this event in OnEnable() and unsubscribe in OnDisable() (do not forget to unsubscribe from events).
Addendum: You should not destroy your object before all code has been executed. Your code will still work because of how things are managed on the C++ layer of Unity, but it is definitely bad practice.

Unity - Mirror Networking : Player client disconnect after scene changed

I'm currently using Mirror Networking to make a multiplayer game. I have a scene when players are all connected, they can choose their characters and set the ready. If all players are ready, I change current scene to arena scene using MyNetworkManager.ServerChangeScene(arenaSceneName). This method sets all player clients as not ready. But After the scene was loaded, my player client is no longer connected to my host and I don't know why.
Can you help me please ?
Thanks a lot for answers.
Clients that connect to this server will automatically switch to this scene. This is called automatically if onlineScene or offlineScene are set, but it can be called from user code to switch scenes again while the game is in progress. This automatically sets clients to be not-ready. The clients must call NetworkClient.Ready again to participate in the new scene."
if its not solve problem can you give more information about your project
Are you using MatchInterestManager ? This can be lead some problems like yours
Edit 1 -
Maybe the problem was host
can you run your code on server not host
Edit 2 -
i belive your command function runs on client not server because you miss "Cmd" prefix on your command function change it CmdOnAllPlayersReady()
public class ReadyPlayerChecker : NetworkBehaviour
{
public List<PlayerBehaviour> activePlayers;
public List<PlayerBehaviour> GetActivePlayers()
{
return activePlayers;
}
// Start is called before the first frame update
void Start()
{
activePlayers = new List<PlayerBehaviour>();
}
// Update is called once per frame
void Update()
{
foreach (PlayerBehaviour player in FindObjectsOfType<PlayerBehaviour>
(true))
{
if(!activePlayers.Contains(player))
{
activePlayers.Add(player);
}
}
bool allPlayersReady = true;
foreach (PlayerBehaviour player in activePlayers)
{
if (!player.IsReady())
{
allPlayersReady = false;
}
}
if (allPlayersReady && activePlayers.Count > 0)
{
OnAllPLayersReady();
}
}
[Command]
public void OnAllPLayersReady()
{
GameObject.Find("SceneManager").GetComponent<SceneChanger>
().LoadScene("SimpleArena");
}
}
This is my Network Manager settings :
I succeed to make the playerclient connected when the scene change. Now, the player prefab for my client is in host view but not in the corresponding client view. Do someone can tell me why ?

How do I call OnTriggerEnter multiple times in unity?

I have to push a button (inside a medical patient) multiple times, with OnCollisionEnter(); the problem is that it collides with the patient's mesh and the animations are always triggered, which is not good for me. With OnTriggerEnter(), it works fine as it is a trigger and does not collide with the medical patient's mesh, only with my avatar, which uses hand tracking. I want to call OnTriggerEnter() multiple times. I thought about instantiating the asset again, then destroying the first asset, but I have not gotten any luck. Please help! The following code is attached to my buttons inside the patient, which is to be palpated. How can I trigger OnTriggerEnter multiple times?
private void OnTriggerEnter(Collider other)
{
if (palpation_patient.animation_selection == 6 && palpation_patient.pain_level == 1)
{
palpation_patient.animator.SetLayerWeight(1, 1);
}
if (palpation_patient.animation_selection == 6 && palpation_patient.pain_level == 2)
{
palpation_patient.animator.SetLayerWeight(2, 1);
}
if (palpation_patient.animation_selection == 6 && palpation_patient.pain_level == 3)
{
palpation_patient.animator.SetLayerWeight(3, 1);
}
}

Unity inactive object destroyed

So after my player hits 0 HP, the player object (in my case a rocket ship) is set to false and the Game Over UI is set to true. Then the player has two options: either to restart or resume the game. Only resuming the game plays an ad, but after the ad is done playing the game doesn't continue and I get the error saying "The object of type 'GameObject'(The Game Over UI) has been destroyed but you are still trying to access it". Now I know that this happens when I specifically destroy an object, but not when I set the object to inactive.
Game Over function
private void GameOver()
{
Time.timeScale = 0f;
GameOverUI.SetActive(true);
finalScore.text = score.ToString() + " Meters";
PlayerPrefs.SetFloat("Score", 0);
totalCash.text = PlayerPrefs.GetFloat("Cash", 0).ToString() + " Cash";
highScoreTracker.text = PlayerPrefs.GetFloat("HighScore", 0).ToString() + " Meters";
}
Resume function called from Ads Manager after ad is played
public void ResumeGame()
{
GameOverUI.SetActive(false);
this.gameObject.SetActive(true);
PlayerPrefs.SetFloat("Score", score);
Time.timeScale = 1.0f;
}
Ads Manager function
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
{
if (activeScene == "InitialEarth" || activeScene == "Earth" || activeScene == "Space" && showResult == ShowResult.Finished)
{
player.ResumeGame();
timesWatched++;
if (timesWatched >= 2)
{
adButton.interactable = false;
}
}
}
The error is pointing to the lines "GameOverUI.SetActive(false)" and "player.ResumeGame()".
I've tried keeping the player object active when its game over but same error. I have a similar function, like my Pause UI, where it's inactive initially and with a button click, its set to active and then inactive again and that works fine.
I'm not sure what's wrong or where to look. Is there another way to deactivate and active object? Why would an inactive object give a destroyed error, since its still in the game hierarchy? Any help or pointers would be much appreciated. If more info is needed, please let me know. Thanks.

Can't get RunTransaction with Firebase in Unity to work

I'm working on a game in Unity, using Firebase for user and game data.
Everything is fine saving the game to Unity, but in Multiplayer I have the challenge to pair an open game to a unique player 2.
The flow is:
1. You look for a game with a state of "open"
2. If no game is found within X seconds, a new one is created with the state of "open"
I have a query that returns open games (those with state "open")
This query is added a Firebase eventhandler
public void OnButtonLookForOpenMPGames()
{
this.OpenFirebaseGamesAsHost = this.LiveGamereference.OrderByChild("State").EqualTo(WYMSettings.MP_GAME_STATE_OPEN_TO_PLAYER2)
.LimitToFirst(3);
this.OpenFirebaseGamesAsHost.ChildAdded += this.OnOpenMPGameFound;
}
This fires fine in the handler:
private void OnOpenMPGameFound(object sender, ChildChangedEventArgs args)
{
Debug.Log("Looking for open games");
if (args.DatabaseError != null)
{
// handle errors
}
else
{
Debug.Log("Open game found (it may be my own)");
// remove event listener because we got a hit
// it will fire as many times as it's true!
this.OpenFirebaseGamesAsHost.ChildAdded -= this.OnOpenMPGameFound;
if (args.Snapshot.Child("HostId").Value.ToString() != FirebaseAuth.DefaultInstance.CurrentUser.UserId)
{
Debug.Log("Other game than mine found open");
// this.AddDelayedUpdateAction(() =>
// {
// this.MPGameLockInTransaction(args.Snapshot.Reference);
// });
this.MPGameLockInTransaction(args.Snapshot.Reference);
}
}
}
The problem: The handler passes this on to the transaction function, but it fails with an inner exception (Internal Task Faulted) - I've tried many different variations, but can't figure this one out from the official Firebase example.
Problem code:
What I want to achieve is to lock only that game to those two players, the host and the players 2 in this example querying for open games. The State is an int, but here a string for clarity.
private void MPGameLockInTransaction(DatabaseReference mpreference)
{
mpreference.RunTransaction(mutableData =>
{
MultiPlayerGame transactionMPG = mutableData.Value as MultiPlayerGame;
if (transactionMPG == null)
{
return TransactionResult.Abort();
}
if (transactionMPG.State != "open")
{
// game is taken, abort
Debug.Log("transaction aborted");
return TransactionResult.Abort();
}
transactionMPG.State = "game started";
mutableData.Value = transactionMPG;
return TransactionResult.Success(mutableData);
}).ContinueWith(task =>
{
if (task.Exception != null)
{
Debug.Log("Transactionlock to game failed" + task.Exception.ToString());
// Look over again
// not implemented yet
}
else
{
Debug.Log("starting game immediately");
this.AddDelayedUpdateAction(() => this.StartMPGameImmediatelyFromSearch());
}
});
}
This is just a guess but it might be related to threading.
In newer .Net version ContinueWith might end on a thread where most of the Unity API may not be called (including Debug.Log).
Instead you could try and use ContinueWithOnMainThread from the extensions instead which was created exactly for this reason.
With the .NET 4.x runtime, continuations may often execute in the background, whilst this extension method pushes them onto the main thread.
The .NET 3.x runtime didn't have this issue as continuations were contained within the Parse library, which did this implicitly.