/// <summary>
 /// Sends and sets the local transform for this object for all users
 /// </summary>
 /// <param name="_localPosition">The new local position for this object</param>
 /// <example><code>
 /// void SomeFunction()
 /// {
 ///     gameobject.GetComponent&lt;ASL.ASLObject&gt;().SendAndSetClaim(() =>
 ///     {
 ///         gameobject.GetComponent&lt;ASL.ASLObject&gt;().SendAndSetLocalPosition(new Vector3(1, 2, 5));
 ///     });
 /// }
 /// </code></example>
 public void SendAndSetLocalPosition(Vector3?_localPosition)
 {
     if (m_Mine) //Can only send a transform if we own the object
     {
         if (_localPosition.HasValue)
         {
             using (RTData data = RTData.Get())
             {
                 data.SetString((int)GameController.DataCode.Id, m_Id);
                 data.SetVector3((int)GameController.DataCode.LocalPosition, new Vector3(_localPosition.Value.x, _localPosition.Value.y, _localPosition.Value.z));
                 GameSparksManager.Instance().GetRTSession().SendData((int)GameSparksManager.OpCode.LocalTransformUpdate, GameSparksRT.DeliveryIntent.RELIABLE, data);
             }
         }
         else //Send my position as is, not a new position as there was no new position passed in.
         {
             using (RTData data = RTData.Get())
             {
                 data.SetString((int)GameController.DataCode.Id, m_Id);
                 data.SetVector3((int)GameController.DataCode.LocalPosition, new Vector3(transform.localPosition.x, transform.localPosition.y, transform.localPosition.z));
                 GameSparksManager.Instance().GetRTSession().SendData((int)GameSparksManager.OpCode.LocalTransformUpdate, GameSparksRT.DeliveryIntent.RELIABLE, data);
             }
         }
     }
 }
Exemplo n.º 2
0
        /// <summary>
        /// Triggers when a match is found either through hosting or through selecting a match. Sets the lobby screen variables
        /// </summary>
        /// <param name="_message">The message from the GameSparks API</param>
        private void OnMatchFound(GameSparks.Api.Messages.MatchFoundMessage _message)
        {
            //If we don't have ourselves as an ID yet, then we can't find a match (though from a GameSparks perspective we can)
            if (!GameSparksManager.m_PlayerIds.ContainsValue(true))
            {
                return;
            }

            //Get matchGroup
            string matchGroup = _message.MatchGroup;

            if (string.IsNullOrEmpty(matchGroup))
            {
                matchGroup = "";
            }
            GameSparksManager.Instance().SetMatchGroup(matchGroup);

            //Don't transition to the lobby screen if just looking for a match
            if (!m_hosting && (!m_QuickConnect || m_SwitchedToManualMatchMaking))
            {
                m_JoinMatchButton.GetComponent <Button>().interactable = false;
                m_JoinMatchButtonInteractable = false;
                //Disconnect from match instance so we can join the match we want to join (since we're looking at matches)
                new LogEventRequest().SetEventKey("Disconnect").SetEventAttribute("MatchShortCode", _message.MatchShortCode).
                SetEventAttribute("MatchGroup", matchGroup).Send((_disconnectResponse) =>
                {
                    m_JoinMatchButtonInteractable = true;
                    foreach (GameObject _potentialMatch in GameObject.FindGameObjectsWithTag("PotentialMatchButton"))
                    {
                        _potentialMatch.GetComponent <Button>().interactable = true;
                    }
                    m_SearchMatchErrorText.GetComponent <Text>().text = "";
                    m_SearchMatchErrorText.SetActive(false);
                });

                return;
            }

            DisplayPanel(PanelSelection.LobbyScreen);
            GameSparksManager.Instance().m_MyMatchId = _message.MatchId;
            m_TempRTSessionInfo = new RTSessionInfo(_message); // we'll store the match data until we need to create an RT session instance

            //Trigger Cloud event to gather max player count for this match and also grab the match name, placing these variables on the lobby screen.
            new LogEventRequest()
            .SetEventKey("GetFoundMatchInfo")
            .SetEventAttribute("MatchShortCode", _message.MatchShortCode)
            .Send((_nameResponse) =>
            {
                var matchInfo = JsonUtility.FromJson <JSONFoundMatchInfoConverter>(_nameResponse.ScriptData.JSON);
                StringBuilder matchDetails = new StringBuilder();
                m_MaxPlayerCount           = matchInfo.m_MaxPlayerCount.ToString();
                m_PlayerCountText.GetComponent <Text>().text       = _message.Participants.Count() + "/" + m_MaxPlayerCount;
                m_MatchNameText.GetComponent <Text>().text         = _message.MatchShortCode + ": " + _message.MatchData.GetString("m_cleanRoomName");
                m_ReadyButton.GetComponent <Button>().interactable = true;    //Allow user to ready up
            });

            //Add player name to the player list
            StringBuilder playerList = new StringBuilder();

            foreach (GameSparks.Api.Messages.MatchFoundMessage._Participant player in _message.Participants)
            {
                playerList.AppendLine(player.DisplayName); //Add the player number and display name to the list
                if (!GameSparksManager.m_PlayerIds.ContainsKey(player.Id))
                {
                    GameSparksManager.m_PlayerIds.Add(player.Id, false);
                }
            }
            m_PlayerListText.GetComponent <Text>().text = playerList.ToString(); //Display the users in the room
        }
Exemplo n.º 3
0
        /// <summary>Start is called before the first frame update</summary>
        void Start()
        {
            #region Initialize needed UI elements

            m_InfoTextPanel        = GameObject.Find("InfoTextPanel");
            m_UserNameText         = GameObject.Find("UsernameText");
            m_ConnectionStatusText = GameObject.Find("ConnectionStatusText");

            m_MainMenuPanel  = GameObject.Find("MainMenuPanel");
            m_UsernameInput  = GameObject.Find("UsernameInputField");
            m_ConnectButton  = GameObject.Find("ConnectButton");
            m_LoginErrorText = GameObject.Find("LoginErrorText");

            m_ConnectionMenuPanel = GameObject.Find("ConnectionMenuPanel");
            m_HostButton          = GameObject.Find("HostSessionButton");
            m_FindButton          = GameObject.Find("FindSessionButton");

            m_HostMenuPanel         = GameObject.Find("HostMenuPanel");
            m_HostSelectionDropDown = GameObject.Find("MatchNamesDropDown");
            m_RoomNameInputField    = GameObject.Find("RoomNameInputField");
            m_StartHostingButton    = GameObject.Find("StartHostingButton");
            m_HostErrorText         = GameObject.Find("HostErrorText");

            m_RoomViewPanel        = GameObject.Find("RoomViewPanel");
            m_RefreshButton        = GameObject.Find("RefreshButton");
            m_JoinMatchButton      = GameObject.Find("JoinMatchButton");
            m_SearchMatchErrorText = GameObject.Find("SearchMatchErrorText");
            m_JoinMatchErrorText   = GameObject.Find("JoinMatchErrorText");

            m_LobbyScreen     = GameObject.Find("LobbyScreenPanel");
            m_MatchNameText   = GameObject.Find("MatchNameText");
            m_PlayerCountText = GameObject.Find("PlayerCountText");
            m_PlayerListText  = GameObject.Find("PlayerListText");
            m_ReadyButton     = GameObject.Find("ReadyButton");

            m_SetupPanel = GameObject.Find("SetupPanel");

            m_BackButton = GameObject.Find("BackButton");

            m_MatchButtonPrefab = (GameObject)Resources.Load("ASL_Prefabs/AvailableMatchButtons", typeof(GameObject));

            #endregion

            #region Debug.Assert statements
            Debug.Assert(m_InfoTextPanel != null, "The Info Text Panel was null - attach it to this script");
            Debug.Assert(m_MainMenuPanel != null, "The Main Menu Panel was null - attach it to this script");
            Debug.Assert(m_ConnectionMenuPanel != null, "The Connection Menu Panel was null - attach it to this script");
            Debug.Assert(m_HostMenuPanel != null, "Info Host Menu Panel was null - attach it to this script");
            Debug.Assert(m_RoomViewPanel != null, "Info Room View Panel was null - attach it to this script");
            Debug.Assert(m_UserNameText != null, "Username text object under the Info Text Panel was null - attach it to this script");
            Debug.Assert(m_ConnectionStatusText != null, "Connection Status text object under the Info Text Panel was null - attach it to this script");
            Debug.Assert(m_UsernameInput != null, "Username Input Field under the Main Menu Panel was null - attach it to this script");
            Debug.Assert(m_ConnectButton != null, "Connect button under the Main Menu Panel was null - attach it to this script");
            Debug.Assert(m_HostButton != null, "Host Session button under the Connection Menu Panel was null - attach it to this script");
            Debug.Assert(m_FindButton != null, "Find button under the Connection Menu Panel was null - attach it to this script");
            Debug.Assert(m_HostSelectionDropDown != null, "Host dropdown selection under the Host Menu Panel was null - attach it to this script");
            Debug.Assert(m_StartHostingButton != null, "Start hosting button under the Host Menu Panel was null - attach it to this script");
            Debug.Assert(m_LobbyScreen != null, "The Lobby Screen panel was null - attach it to this script");
            Debug.Assert(m_ReadyButton != null, "Ready button under the Lobby Screen panel was null - attach it to this script");
            Debug.Assert(m_PlayerListText != null, "Players text under PlayerHolder in Lobby Screen panel was null - attach it to this script");
            Debug.Assert(m_PlayerCountText != null, "Player Count text under MatchDetails in Lobby Screen panel was null - attach it to this script");
            Debug.Assert(m_MatchNameText != null, "Match Name text under MatchDetails in Lobby Screen panel was null - attach it to this script");
            Debug.Assert(m_HostErrorText != null, "Host Error Text text in Host Menu panel was null - attach it to this script");
            Debug.Assert(m_SearchMatchErrorText != null, "Search Match Text text in Room Find panel was null - attach it to this script");
            Debug.Assert(m_BackButton != null, "Back button was null - attach it to this script");
            Debug.Assert(m_RefreshButton != null, "Refresh button in Room View panel was null - attach it to this script");
            Debug.Assert(m_JoinMatchButton != null, "Join button in Room View panel was null - attach it to this script");
            Debug.Assert(m_MatchButtonPrefab != null, "Join button in Room View panel was null - attach it to this script");
            Debug.Assert(m_RoomNameInputField != null, "User Defined Room Name Input Field in the Host Menu panel was null - attach it to this script");
            Debug.Assert(m_JoinMatchErrorText != null, "Join Match Error text in the Room View panel was null - attach it to this script");
            Debug.Assert(m_LoginErrorText != null, "Login Error text in the Main Menu Panel was null - attach it to this script");

            #endregion

            //Set match button to starting position - will increment whenever we add a new match
            m_OldMatchButtonPosition = m_MatchButtonPrefab.transform.localPosition;
            m_QuickConnect           = QuickConnect.m_StaticQuickStart;
            m_RoomName = QuickConnect.m_StaticRoomName;
            m_ConnectionStatusText.GetComponent <Text>().text = "No Connection..."; //Let the user know they aren't connected yet.
            m_SearchMatchErrorText.SetActive(false);
            m_HostErrorText.SetActive(false);
            m_JoinMatchErrorText.SetActive(false);
            m_ReadyButton.GetComponent <Button>().interactable = false;
            //Set Main Menu to be the current panel showing
            DisplayPanel(PanelSelection.MainMenu);
            m_StaticStartingScene = m_StartingScene;
            m_ConnectButton.GetComponent <Button>().interactable   = false;
            m_JoinMatchButton.GetComponent <Button>().interactable = false;
            m_HostButton.GetComponent <Button>().interactable      = false;
            m_FindButton.GetComponent <Button>().interactable      = false;
            //Button Click Listeners
            #region GUI Listeners

            m_BackButton.GetComponent <Button>().onClick.AddListener(() =>
            {
                m_HostButton.GetComponent <Button>().interactable      = false;
                m_FindButton.GetComponent <Button>().interactable      = false;
                m_JoinMatchButton.GetComponent <Button>().interactable = false;
                m_JoinMatchButtonInteractable = false;
                //Disconnect from anything we may be connected to via the lobby screen (just 1 match)
                if (m_LobbyScreen.activeSelf)
                {
                    if (m_ChosenMatch.shortCode == "QS")
                    {
                        Disconnect(m_ChosenMatch.shortCode, m_cleanRoomName, true);
                    }
                    else
                    {
                        Disconnect(m_ChosenMatch.shortCode, "", true);
                    }
                }
                //Disconnect from pending matches we created (this will destroy the match as we are the only ones in them)
                if (m_RoomViewPanel.activeSelf)
                {
                    foreach (string match in m_MatchShortCodes)
                    {
                        Disconnect(match, "");
                    }
                }
                DisplayPanel(PanelSelection.ConnectionMenu);
                if (m_MatchShortCodes == null || m_MatchShortCodes?.Count == 0) //If we haven't generated short codes yet
                {
                    GetMatchShortCodes();
                }
                m_SwitchedToManualMatchMaking = true;
            });

            m_ConnectButton.GetComponent <Button>().onClick.AddListener(() =>
            {
                // string.empty is passed in for a password because we don't require users have to a password but the GameSparks API does
                GameSparksManager.Instance().AuthenticateUser(m_UsernameInput.GetComponentsInChildren <Text>()[1].text, string.Empty, OnRegistration, OnAuthentication);
                m_LoginErrorText.GetComponent <Text>().text = string.Empty;
            });

            m_HostButton.GetComponent <Button>().onClick.AddListener(() =>
            {
                m_StartHostingButton.GetComponent <Button>().interactable = false;
                //Bring up the Host Menu Panel
                DisplayPanel(PanelSelection.HostMenu);
                SetupHostDropDownMatchOptions();
            });

            m_StartHostingButton.GetComponent <Button>().onClick.AddListener(() =>
            {
                //Setting up match screen:
                DisplayPanel(PanelSelection.Setup);
                //Start the match making process
                HostRoom();
            });

            m_FindButton.GetComponent <Button>().onClick.AddListener(() =>
            {
                //Bring up the Room Find Panel
                DisplayPanel(PanelSelection.RoomView);
                //Search for rooms
                SearchForHostedRooms();
            });

            m_JoinMatchButton.GetComponent <Button>().onClick.AddListener(() =>
            {
                //Join the selected match
                JoinMatch();
            });

            //This is a listener for the Ready Button. On click, we will pass the stored RTSessionInfo to the GameSparksManager to create a new RT session
            m_ReadyButton.GetComponent <Button>().onClick.AddListener(() =>
            {
                GameSparksManager.Instance().StartNewRTSession(m_TempRTSessionInfo);
            });

            //Search for rooms again
            m_RefreshButton.GetComponent <Button>().onClick.AddListener(() =>
            {
                m_JoinMatchErrorText.SetActive(false);
                m_SearchMatchErrorText.SetActive(false);
                SearchForHostedRooms();
            });

            #endregion

            #region GameSpark API Listeners
            //This listener will update the text in the match details field if no match was found
            GameSparks.Api.Messages.MatchNotFoundMessage.Listener = (message) =>
            {
                m_HostErrorText.SetActive(true);
                m_HostErrorText.GetComponent <Text>().text = "Failed to host match: \"" + message.JSONString + "\"";
                m_BackButton.gameObject.SetActive(true);
                DisplayPanel(PanelSelection.HostMenu);
            };

            //This listener will inform players they found a match
            GameSparks.Api.Messages.MatchFoundMessage.Listener += OnMatchFound;
            //This listener will inform players an update has occurred in their match (like a new player joining or leaving)
            GameSparks.Api.Messages.MatchUpdatedMessage.Listener += OnMatchUpdate;
            #endregion
        }
Exemplo n.º 4
0
        /// <summary>
        /// Creates an ARCore Cloud Anchor at the location the user tapped and passed into it. This function can be used to set the world origin or just a normal cloud anchor.
        /// It is advisable to only have 1 user in your application set cloud anchors.
        /// </summary>
        /// <param name="_hitResults">Holds information about where the user tapped on the screen. This variable should be created using the ARWorldOriginHelper Raycast method </param>
        /// <param name="_anchorObjectPrefab">The ASL object you want to have located at the cloud anchor. If you don't want any object to be located at the cloud anchor, you can pass in null.
        /// Doing so will create an empty gameobject - thus making it invisible to users</param>
        /// <param name="_myPostCreateCloudAnchorFunction">This is the function you want to call after a cloud anchor has successfully been created. Only the user that called this function
        /// will execute this function - it is not sent to other users. This is a good way to move or create objects after a cloud anchor has been created.</param>
        /// <param name="_waitForAllUsersToResolve">This determines if users should wait to setup (and if they are the caller of this function, to execute the _myPostCreateCloudAnchorFunction)
        /// the cloud anchor once they receive and find it, or if they should wait for all users to receive and find it first before executing anything. The default is to wait for all users
        /// and is the suggested value as not waiting as the potential to cause synchronization problems.</param>
        /// <param name="_setWorldOrigin">This determines if this cloud anchor should be used to set the world origin for all users or not. If you are setting the world origin, you should do
        /// so right away in your app and as the first (if you have more than 1) cloud anchor created. You should never set the world origin more than once.</param>
        public static void CreateARCoreCloudAnchor(TrackableHit _hitResults, ASLObject _anchorObjectPrefab = null, ASLObject.PostCreateCloudAnchorFunction _myPostCreateCloudAnchorFunction = null,
                                                   bool _waitForAllUsersToResolve = true, bool _setWorldOrigin = true)
        {
            if (_anchorObjectPrefab != null)
            {
                if (!_anchorObjectPrefab.m_Mine)
                {
                    Debug.LogError("You must claim the ASL object before setting it as an anchor");
                }
                return;
            }
            //Create local anchor at hit location
            Anchor localAnchor = _hitResults.Trackable.CreateAnchor(_hitResults.Pose);

            localAnchor.name = "Local anchor created when creating cloud anchor";

            //Create CLoud anchor
            XPSession.CreateCloudAnchor(localAnchor).ThenAction(result =>
            {
                //If failed to host
                if (result.Response != CloudServiceResponse.Success)
                {
                    Debug.LogError("Failed to host Cloud Anchor: " + result.Response);
                    return; //Break out
                }
                //Successful:
                Debug.Log("Successfully created and saved Cloud Anchor: " + result.Anchor.CloudId);

                if (_anchorObjectPrefab == null)
                {
                    //Uncomment the line below to aid in visual debugging (helps display the cloud anchor)
                    //_anchorObjectPrefab = GameObject.CreatePrimitive(PrimitiveType.Cube).AddComponent<ASLObject>(); //if null, then create empty game object
                    _anchorObjectPrefab = new GameObject().AddComponent <ASLObject>();
                    _anchorObjectPrefab._LocallySetAnchorID(result.Anchor.CloudId); //Add ASLObject component to this anchor and set its anchor id variable
                    _anchorObjectPrefab._LocallySetID(result.Anchor.CloudId);       //Locally set the id of this object to be that of the anchor id (which is unique)

                    //Add this anchor object to our ASL dictionary using the anchor id as its key. All users will do this once they resolve this cloud anchor to ensure they still in sync.
                    m_ASLObjects.Add(result.Anchor.CloudId, _anchorObjectPrefab.GetComponent <ASLObject>());
                    //_anchorObjectPrefab.GetComponent<Material>().color = Color.magenta;
                    _anchorObjectPrefab.transform.localScale = new Vector3(0.04f, 0.04f, 0.04f); //Set scale to be 4 cm
                }
                else
                {
                    _anchorObjectPrefab.GetComponent <ASLObject>()._LocallySetAnchorID(result.Anchor.CloudId); //Set anchor id variable
                    _anchorObjectPrefab.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f);               //Set scale to be 5 cm
                }

                //Send Resolve packet using _anchorObjectPrefab
                _anchorObjectPrefab.GetComponent <ASLObject>().SendCloudAnchorToResolve(_setWorldOrigin, _waitForAllUsersToResolve);

                if (_waitForAllUsersToResolve)
                {
                    //Send packet to relay server letting it know this user is ready
                    using (RTData data = RTData.Get())
                    {
                        data.SetString((int)GameController.DataCode.Id, _anchorObjectPrefab.m_Id);
                        GameSparksManager.Instance().GetRTSession().SendData((int)GameSparksManager.OpCode.ResolvedCloudAnchor, GameSparksRT.DeliveryIntent.RELIABLE, data);
                    }
                    _anchorObjectPrefab.StartWaitForAllUsersToResolveCloudAnchor(result, _setWorldOrigin, _myPostCreateCloudAnchorFunction, _hitResults);
                }
                else //Don't wait for users to know about this cloud anchor
                {
                    _anchorObjectPrefab.GetComponent <ASLObject>()._LocallySetCloudAnchorResolved(true);
                    _anchorObjectPrefab.StartWaitForAllUsersToResolveCloudAnchor(result, _setWorldOrigin, _myPostCreateCloudAnchorFunction, _hitResults);
                }
            });
        }