Hello. I am using Photon Unity Network to create a four player multiplayer online mode so players can play with or against each other online. I have been successful in getting our menu screens to sync with other clients and even have our character select screen show other players highlight characters based upon those player;s inputs with a mouse on a different computer. The problem I am having is getting a game controller (Xbox controller) to do the same thing.
One of the things I noticed when using Photon is that the even triggers do not work correctly for a controller. So I created a custom joystick navigation class for the game to listen to each player’s controller input for the menu like so:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class JoystickNav : Photon.PunBehaviour {
[SerializeField] private List<PhotonView> PVObjects;
[SerializeField] private List<Button> characterButtons;
[SerializeField] private EventSystem ES;
private bool ctrlActive;
private int playerNum;
private enum CtrlState { Gizmo, Clip, Bit, Mack, Carmine, Random };
private CtrlState state;
// Use this for initialization
void Start () {
playerNum = PlayerClass_MP.playerClass.GetPlayerNumber(PhotonNetwork.player);
enabled = photonView.isMine;
state = CtrlState.Gizmo;
}
// Update is called once per frame
void Update () {
Debug.Log("Player " + playerNum + " is in control.");
ControllerInput();
}
private void ControllerInput()
{
if (Input.GetAxis("MenuVertical_P1") == 0 && Input.GetAxis("MenuHorizontal_P1") == 0 && ctrlActive == true)
{
ctrlActive = false;
}
if (Input.GetAxis("MenuVertical_P1") > 0.5f && ctrlActive == false)
{
ctrlActive = true;
Up();
}
if (Input.GetAxis("MenuVertical_P1") < -0.5f && ctrlActive == false)
{
ctrlActive = true;
Down();
}
if (Input.GetAxis("MenuHorizontal_P1") < -0.5f && ctrlActive == false)
{
ctrlActive = true;
Left();
}
if (Input.GetAxis("MenuHorizontal_P1") > 0.5f && ctrlActive == false)
{
ctrlActive = true;
Right();
}
}
private void Up()
{
if (state == CtrlState.Random)
{
state = CtrlState.Gizmo;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[0].gameObject);
PVObjects[5].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[0].RPC("JoystickHover", PhotonTargets.All, playerNum);
}
}
private void Down()
{
if (state == CtrlState.Gizmo)
{
state = CtrlState.Random;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[5].gameObject);
PVObjects[0].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[5].RPC("JoystickHover", PhotonTargets.All, playerNum);
}
}
private void Left()
{
switch (state)
{
case CtrlState.Gizmo:
state = CtrlState.Clip;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[1].gameObject);
PVObjects[0].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[1].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
case CtrlState.Random:
state = CtrlState.Clip;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[1].gameObject);
PVObjects[5].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[1].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
case CtrlState.Clip:
state = CtrlState.Mack;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[3].gameObject);
PVObjects[1].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[3].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
case CtrlState.Bit:
state = CtrlState.Gizmo;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[0].gameObject);
PVObjects[2].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[0].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
case CtrlState.Carmine:
state = CtrlState.Bit;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[2].gameObject);
PVObjects[4].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[2].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
}
}
private void Right()
{
switch (state)
{
case CtrlState.Gizmo:
state = CtrlState.Bit;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[2].gameObject);
PVObjects[0].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[2].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
case CtrlState.Random:
state = CtrlState.Bit;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[2].gameObject);
PVObjects[5].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[2].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
case CtrlState.Clip:
state = CtrlState.Gizmo;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[0].gameObject);
PVObjects[1].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[0].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
case CtrlState.Bit:
state = CtrlState.Carmine;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[4].gameObject);
PVObjects[2].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[4].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
case CtrlState.Mack:
state = CtrlState.Clip;
ES.SetSelectedGameObject(null);
ES.SetSelectedGameObject(characterButtons[1].gameObject);
PVObjects[3].RPC("JoystickLeave", PhotonTargets.All, playerNum);
PVObjects[1].RPC("JoystickHover", PhotonTargets.All, playerNum);
break;
}
}
}
What this does is that it checks to see what button is currently highlighted and then if the controller sends input, it switches which button is selected and what graphic to show when it is highlighted based upon the previous state. While it works for one player, when I have two players on two different computers, player two breaks and the previous graphic never turns off. I tried using photonView.isMine for the input method but it made no difference with the behavior.
After some debugging, I discovered that an RPC call never even fires if it is player two providing input. It is for the call to the JoystickLeave() method. For some reason this is never called for player two but the line after that is which is the JoystickHover() method. There is no conditional fro that method so it should run as soon as it is called. There is also a photon view component attached to that object and plugged into the corresponding slot in the inspector (if it wasn’t, even player one’s calls wouldn’t work).
TL;DR: my question would be why would a lien of code be skipped for one player and not the other and how do I force it to execute that method call?
PS: Here are the methods in question that I am trying to call:
[PunRPC]
public void JoystickHover(int pNum)
{
playerIcons[pNum].photonView.RPC("SwitchOnOff", PhotonTargets.All, true);
}
[PunRPC]
public void JoystickLeave(int pNum)
{
Debug.Log("Player " + (playerNum + 1) + " is stepping in...");
playerIcons[pNum].photonView.RPC("SwitchOnOff", PhotonTargets.All, false);
}
Thanks for any suggestions and assistance.