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.
Related
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
I have looked at other answers, but it hasnt helped because I did add the object and not the script in the OnClick() box, but it still won't let me access the variable. What's going on?
The object in the box, not the script
The Method I want to access
public void IncreaseStat(string stat, float val)
{
switch (stat)
{
case "Hunger":
gm.juice.hunger += val;
break;
case "Energy":
gm.juice.energy += val;
break;
case "Happiness":
gm.juice.happiness += val;
break;
case "Health":
gm.juice.health += val;
break;
default:
Debug.LogError("INVALID STAT: " + stat);
break;
}
}
Look like Unity not allow you to put function with more than one parameter into the OnClick() event
using UnityEngine;
using UnityEngine.UI;
public class ButtonEventDemo : MonoBehaviour
{
public void FunctionWithNoParams()
{
// This is working fine
}
public void FunctionWithStringParam(string text)
{
// This is working fine
}
public void FunctionWithIntParam(int number)
{
// This is working fine
}
public void FunctionWithButtonParam(Button button)
{
// This is working fine
}
public void FunctionWithTwoParams(int first, int second)
{
// Cannot put this function into OnClick() event
}
}
OnClick() demo
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?