im attempting to create crossplatform play with oculus and pc using PUN 2 but i cant connect to the server and im stuck on the loading screen
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UnityEngine.SceneManagement;
public class ServerLoader : MonoBehaviourPunCallbacks
{
void Start()
{
Debug.Log("attempting to connect");
PhotonNetwork.ConnectUsingSettings();
Debug.Log("Connected once");
}
public override void OnConnectedToMaster()
{
Debug.Log("Connected twice");
if(Application.platform == RuntimePlatform.WindowsPlayer)
{
Debug.Log("attempting join lobby");
PhotonNetwork.JoinLobby();
Debug.Log("Joining lobby");
}
else if(Application.platform == RuntimePlatform.Android)
PhotonNetwork.CreateRoom(RandomStringGenerator(6));
Debug.Log("Joining game");
}
public override void OnJoinedRoom()
{
PhotonNetwork.LoadLevel("Game");
}
public override void OnJoinedLobby()
{
SceneManager.LoadScene("Lobby");
}
string RandomStringGenerator(int length)
{
string characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
string generated_string = "";
for(int i = 0; i < length; i++)
generated_string += characters[Random.Range(0, length)];
return generated_string;
}
}
the only logs that get printed in the output are "attempting to connect" and "connected once"
i tried running the game and got stuck on the loading screen i expected to be loaded into the lobby as i was running this isntance of the game on my pc
Related
So I have been debugging for hours at this point to no avail. I call my function in another class and it keeps returning 0 I have tried logging everything to see if there is an error with it, and I can't find one. The target device prints out as UnityEngine.XR.InputDevice and nothing errors or warns. please if anyone has any insight. here's how I call it
Debug.Log(RightHand.AButtonDown());
and here is my code for the functions
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public static class RightHand
{
private static InputDevice targetDevice;
static RightHand()
{
TryInitialize();
}
private static void TryInitialize()
{
Debug.Log("ran inital");
List<InputDevice> devices = new List<InputDevice>();
InputDeviceCharacteristics rightControllerCharacteristics = InputDeviceCharacteristics.Right | InputDeviceCharacteristics.Controller;
InputDevices.GetDevicesWithCharacteristics(rightControllerCharacteristics, devices);
foreach (var item in devices)
{
Debug.Log("ran log");
Debug.Log(item.name + item.characteristics);
}
Debug.Log("right controler characteristics" + rightControllerCharacteristics);
if (devices.Count > 0)
{
targetDevice = devices[0];
}
Debug.Log(targetDevice);
}
public static bool AButtonDown()
{
targetDevice.TryGetFeatureValue(CommonUsages.primaryButton, out bool primaryButtonOut);
if (primaryButtonOut)
{
return true;
}
else
{
return false;
}
}
}
My best guess is the list of devices needs to be updated each time a device value is accessed. The method I use uses Unity's XR Toolkit and had the same problem as yours until I moved InputDevice assignment into Update.
using UnityEngine.XR;
public class InputDeviceSample : MonoBehaviour
{
InputDevice left;
InputDevice right;
void Start()
{
}
void Update()
{
// needs to be in Update
right = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
// left = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
// more https://docs.unity3d.com/ScriptReference/XR.XRNode.html
// assigns button value to out variable, if expecting Vector3 replace bool
right.TryGetFeatureValue(CommonUsages.triggerButton, out bool isPressed);
Debug.Log(isPressed);
}
}
CommonUsages is the list of input actions you can read in, here's a list with brief descriptions:
https://docs.unity3d.com/ScriptReference/XR.CommonUsages.html
I'm new to Unity and AR app development, i am trying to create a small app to constantly get current location of the device, but the location is never getting updated no matter how much i try
This is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GPS1 : MonoBehaviour
{
public static GPS1 Instance { set; get; }
public double lat,lon;
private void Start()
{
Instance=this;
DontDestroyOnLoad(gameObject);
StartCoroutine(StartLocationService());
}
private IEnumerator StartLocationService()
{
if(!Input.location.isEnabledByUser)
{
Debug.Log("User has not enabled the GPS");
yield break;
}
Input.location.Start();
Input.compass.enabled=true;
int maxWait=20;
while(Input.location.status==LocationServiceStatus.Initializing && maxWait > 0)
{
yield return new WaitForSeconds(1);
maxWait--;
}
if (maxWait<=0)
{
Debug.Log("Timed Out");
yield break;
}
if(Input.location.status==LocationServiceStatus.Failed)
{
Debug.Log("Unable to determine");
yield break;
}
lat=Input.location.lastData.latitude;
lon=Input.location.lastData.longitude;
yield break;
}
}
[on play][1]
[1]: https://i.stack.imgur.com/KPqSf.png
Please help me with this if possible i tried everything and it isn't working yet.
I'm trying to build an audio player that gets the mp3 files from an external source along with logic for Play, Stop, Next and Prev buttons but I haven't figured out how to do it.
http://localhost:8383/Unity3d/Audio/BT - Paul Van Dyk - Namistai.mp3"
http://localhost:8383/Unity3d/Audio/Stevie Wonder - Skeletons.mp3
And then with C#, I'm opening a UnityWebRequest for the URI, save it into an AudioClip variable and then to an AudioSource variable but I'm then finding issues with using the length property/saving into some sort of Audio clip array.
Here's my code below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
using UnityEngine.UI;
[RequireComponent(typeof(AudioSource))]
public class AudioManager : MonoBehaviour
{
public AudioClip[] musicClips;
private int currentTrack;
private AudioSource source;
public List<string> externalAudio;
IEnumerator GetAudioClip()
{
externalAudio.Add("http://localhost:8383/Unity3d/Audio/Stevie%20Wonder%20-%20Skeletons.mp3");
externalAudio.Add("http://localhost:8383/Unity3d/Audio/York%20-%20On%20The%20Beach.mp3");
externalAudio.Add("http://localhost:8383/Unity3d/Audio/BT%20-%20Paul%20Van%20Dyk%20-%20Namistai.mp3");
externalAudio.Add("http://localhost:8383/Unity3d/Audio/S.O.S.%20BAND-JUST%20BE%20GOOD%20TO%20ME%20(SINGLE).mp3");
externalAudio.Add("http://localhost:8383/Unity3d/Audio/Michael%20Jackson%20-%20Beat%20It%20(Official%20Video).mp3");
Debug.Log("Hello World");
Debug.Log(UnityWebRequestMultimedia.GetAudioClip("http://localhost:8383/Unity3d/Audio/Stevie%20Wonder%20-%20Skeletons.mp3", AudioType.MPEG));
foreach (var audioClip in externalAudio)
{
Debug.Log(audioClip);
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(audioClip, AudioType.MPEG))
{
UnityWebRequest request = new UnityWebRequest();
yield return www.SendWebRequest();
if (request.result == UnityWebRequest.Result.ConnectionError)
{
Debug.Log(www.error);
}
else
{
musicClips = DownloadHandlerAudioClip.GetContent(www);
source.clip = musicClips;
Debug.Log("Audio is playing.");
}
}
}
}
// Start is called before the first frame update
void Start()
{
source = GetComponent<AudioSource>();
//PLAY MUSIC
PlayMusic();
}
public void PlayMusic()
{
if (source.isPlaying)
{
return;
}
GetAudioClip();
currentTrack--;
if (currentTrack < 0)
{
currentTrack = 0;
}
StartCoroutine(WaitForMusicEnd());
}
IEnumerator WaitForMusicEnd()
{
while (source.isPlaying)
{
yield return null;
}
NextTitle();
}
public void NextTitle()
{
source.Stop();
currentTrack++;
if (currentTrack > musicClips.Length - 1)
{
currentTrack = 0;
}
source.clip = musicClips[currentTrack];
source.Play();
//Show title
StartCoroutine("WaitForMusicEnd");
}
public void PreviousTitle()
{
source.Stop();
currentTrack--;
if (currentTrack < 0)
{
currentTrack = musicClips.Length - 1;
}
source.clip = musicClips[currentTrack];
source.Play();
//Show title
StartCoroutine("WaitForMusicEnd");
}
public void StopMusic()
{
StopCoroutine("WaitForMusicEnd");
source.Stop();
}
}
How can I save the external audio into an AudioClip list and then use them on the play/stop functions logic?
So this is a little bit broad but here is what I would probably do.
As said let your server provide a list of URLs for the downloads. This way you don't have to hardcode them into your client.
So with the previous point, the first thing you do is one single normal GET request to receive that list of URLs, e.g. simply separated by \n (line breaks)
So the first string message you receive could look like e.g.
http://localhost:8383/Moonbeam%20Challenge/Audio/Stevie%20Wonder%20-%20Skeletons.mp3
http://localhost:8383/Moonbeam%20Challenge/Audio/York%20-%20On%20The%20Beach.mp3
http://localhost:8383/Moonbeam%20Challenge/Audio/BT%20-%20Paul%20Van%20Dyk%20-%20Namistai.mp3
http://localhost:8383/Moonbeam%20Challenge/Audio/S.O.S.%20BAND-JUST%20BE%20GOOD%20TO%20ME%20(SINGLE).mp3
http://localhost:8383/Moonbeam%20Challenge/Audio/Michael%20Jackson%20-%20Beat%20It%20(Official%20Video).mp3
This received list you Split into the individual URLs
var urls = urlList.Split('\n');
For these you start your individual GetAudioClip requests.
The results you store in an array/a list as elements. You don't assign the entire musicClips. I would rather use a
List<AudioClip> musicClips = new List<AudioClip>();
and then from your downloads do
musicClips.Add(DownloadHandlerAudioClip.GetContent(www));
you also don't want to assign and play each downloaded clip to the AudioSource as soon as it is downloaded but rather wait until all of them are downloaded (or at least the first one, depending on your needs)
So this might look somewhat like
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Linq;
[RequireComponent(typeof(AudioSource))]
public class AudioManager : MonoBehaviour
{
[Header("References")]
[SerializeField]
private AudioSource source;
[Header("Settings")]
[SerializeField] private string baseURL;
[SerializeField] private string[] externalAudio;
[SerializeField] private bool autoStartPlayAfterDownloads = true;
[Header("Debugging")]
[SerializeField] private List<AudioClip> musicClips = new List<AudioClip>();
[SerializeField] private int currentTrack;
[SerializeField] private bool isInitialized;
private Coroutine currentPlayTrack;
// Yes, if you make Start return IEnumerator then Units
// automatically runs it as a Coroutine
private IEnumerator Start()
{
// block input from the outside until this controller is finished with the downloads
isInitialized = false;
if (!source) source = GetComponent<AudioSource>();
// Here either use the approach with first receiving a list from the server
yield return GetAudioClipsInfo();
// OR if you already have the clip urls assigned via the Inspector use one of
yield return GetAudioClipsSequencial();
// OR
yield return GetAudioClipsParallel();
// allow to do things from this point on
isInitialized = true;
if(autoStartPlayAfterDownloads) PlayFirstTitle();
}
// This is the routine that downloads the URL list from the server
// then it starts the individual downloads
private IEnumerator GetAudioClipsInfo()
{
// Make the first request for receiving the list of URLs from the server
// If not using this but already assigning the urls
// via Inspector then simply directly use the "GetAudioClips" below
using (var request = UnityWebRequest.Get(baseURL))
{
yield return request.SendWebRequest();
switch (request.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
case UnityWebRequest.Result.ProtocolError:
Debug.LogError($"Could not get list of clips! Error: {request.error}", this);
yield break;
}
var urlList = request.downloadHandler.text;
externalAudio = urlList.Split('\n');
// Here you can either go for the sequencial downloads
yield return GetAudioClipsSequencial();
// OR run them all parallel
yield return GetAudioClipsParallel();
}
}
// This version starts one download at a time, waits until it is done
// then starts the next
private IEnumerator GetAudioClipsSequencial()
{
musicClips.Clear();
foreach (var url in externalAudio)
{
Debug.Log(url);
using (var www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG))
{
yield return www.SendWebRequest();
switch (www.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
case UnityWebRequest.Result.ProtocolError:
Debug.LogError($"Could not get clip from \"{url}\"! Error: {www.error}", this);
continue;
}
musicClips.Add(DownloadHandlerAudioClip.GetContent(www));
}
}
}
// This version starts all downloads at once and waits until they are all done
// probably faster than the sequencial version
private IEnumerator GetAudioClipsParallel()
{
musicClips.Clear();
var requests = new List<UnityWebRequest>();
foreach (var url in externalAudio)
{
Debug.Log(url);
var www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG);
// Start the request without waiting
www.SendWebRequest();
requests.Add(www);
}
// Wait for all requests to finish
yield return new WaitWhile(() => requests.Any(r => !r.isDone));
// Now examine and use all results
foreach (var www in requests)
{
switch (www.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
case UnityWebRequest.Result.ProtocolError:
Debug.LogError($"Could not get clip from \"{www.url}\"! Error: {www.error}", this);
continue;
}
musicClips.Add(DownloadHandlerAudioClip.GetContent(www));
www.Dispose();
}
}
public void PlayFirstTitle()
{
if (!isInitialized) return;
if (source.isPlaying) return;
if (currentPlayTrack != null)
{
StopCoroutine(currentPlayTrack);
}
currentPlayTrack = StartCoroutine(PlayTrack(0));
}
private IEnumerator PlayTrack(int index)
{
// Make sure the index is within the given clips range
index = Mathf.Clamp(index, 0, musicClips.Count);
// update the current track to make next and previous work
currentTrack = index;
// get clip by index
var clip = musicClips[currentTrack];
// Assign and play
source.clip = clip;
source.Play();
// wait for clip end
while (source.isPlaying)
{
yield return null;
}
NextTitle();
}
public void NextTitle()
{
if (!isInitialized) return;
if (currentPlayTrack != null)
{
StopCoroutine(currentPlayTrack);
}
source.Stop();
currentTrack = (currentTrack + 1) % musicClips.Count;
currentPlayTrack = StartCoroutine(PlayTrack(currentTrack));
}
public void PreviousTitle()
{
if (!isInitialized) return;
if (currentPlayTrack != null)
{
StopCoroutine(currentPlayTrack);
}
source.Stop();
currentTrack--;
if (currentTrack < 0)
{
currentTrack = musicClips.Count - 1;
}
currentPlayTrack = StartCoroutine(PlayTrack(currentTrack));
}
public void StopMusic()
{
if (!isInitialized) return;
if (currentPlayTrack != null)
{
StopCoroutine(currentPlayTrack);
}
source.Stop();
}
}
I really need help, when I put Invoke in C#, I have this error:
The local function 'RestartGame' is declared but never used Assembly-CSharp
I really don't know why it is happening, but here is the code:
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
bool gameHasEnded = false;
public float restartDelay = 2f;
public void EndGame()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("GAME OVER");
Invoke("RestartGame", restartDelay);
}
void RestartGame ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
}
unity manual: For better performance and maintability, use Coroutines instead.
https://docs.unity3d.com/ScriptReference/MonoBehaviour.Invoke.html
Try someting like this:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
bool gameHasEnded = false;
public float restartDelay = 2f;
private IEnumerator coroutine;
public void EndGame()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("GAME OVER");
coroutine = RestartDelayed(restartDelay);
StartCoroutine(coroutine);
}
void RestartGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
IEnumerator RestartDelayed(float delay)
{
yield return new WaitForSeconds(delay);
RestartGame();
}
}
}
https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html
I upvoted flyingchris answer but just to explain your error message, I'm assuming its a yellow warning message, is that you are never calling the method RestartGame() directly anywhere in your code, you are invoking it however. Invoking is typically used for UnityEvents and coroutines are typically used for delaying a method.
i have make a simple lan multiplayer game in unity (just for learn).
this is the main code (for connection):
using UnityEngine;
using System.Collections;
public class StartServer : MonoBehaviour {
public Transform Makan;
public Transform CubeOBJ;
public string SSS;
void OnGUI () {
GUILayout.Box (Network.player.ipAddress);
if (Network.peerType == NetworkPeerType.Disconnected)
{
SSS = GUILayout.TextField (SSS);
if (GUILayout.Button ("StartServer"))
{
Network.InitializeServer(10, 25000);
}
if (GUILayout.Button ("Connect"))
{
Network.Connect (SSS, 25000);
}
}
else
{
if (GUILayout.Button ("creatCube"))
{
Network.Instantiate (CubeOBJ, Makan.transform.position, Makan.transform.rotation, 0);
}
}
}
}
it works good.
the problem is that in mobile devices i should make (turn on) hotspot by myself in one of the devices.
how can i do this automatically?