Zabiju je
This commit is contained in:
@@ -50,74 +50,131 @@ namespace Subsystems
|
||||
private Position _lastSentPosition;
|
||||
private GameObject _player;
|
||||
private bool _testMode;
|
||||
|
||||
|
||||
private GPSState _GPSState = GPSState.Uninitialized;
|
||||
private float _speed = 0.00001f;
|
||||
private Position _mapCenter;
|
||||
private CoroutineHost _coroutineHost = new CoroutineHost();
|
||||
private CoroutineHost _coroutineHost;
|
||||
|
||||
private int _gpsRetryCount = 0;
|
||||
private const int _maxGpsRetries = 5;
|
||||
private float _lastPositionSendTime;
|
||||
private const float _positionKeepAliveSeconds = 1.0f;
|
||||
|
||||
/// <summary>Last known GPS position (for CreateLobby centre point)</summary>
|
||||
public Position? LastKnownPosition => _currentPosition.Lat != 0 || _currentPosition.Lon != 0 ? _currentPosition : (Position?)null;
|
||||
|
||||
public GameManager_Input(GameClient gameClient, GameObject player, bool testMode)
|
||||
{
|
||||
_gameClient = gameClient;
|
||||
_player = player;
|
||||
_testMode = testMode;
|
||||
// CoroutineHost needs a MonoBehaviour on a real GameObject
|
||||
var hostGO = new UnityEngine.GameObject("_CoroutineHost");
|
||||
UnityEngine.Object.DontDestroyOnLoad(hostGO);
|
||||
_coroutineHost = hostGO.AddComponent<CoroutineHost>();
|
||||
}
|
||||
|
||||
/// <summary>Called from OnSceneLoaded when Client.unity loads so the
|
||||
/// Player capsule (which lives in Client.unity) can be wired at runtime.</summary>
|
||||
public void SetPlayerObject(GameObject player) { _player = player; }
|
||||
public void positionCheck()
|
||||
{
|
||||
var state = _gameClient?.CurrentLobbyState;
|
||||
if (state == null || state.Phase != GamePhase.Playing)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (_gameClient.CurrentLobbyState.Phase == GamePhase.Playing)
|
||||
if (_testMode)
|
||||
{
|
||||
if (_testMode)
|
||||
if (_currentPosition == new Position(0, 0))
|
||||
{
|
||||
if (state.MapData == null)
|
||||
return;
|
||||
|
||||
if (_currentPosition == null || _currentPosition == new Position(0, 0))
|
||||
{
|
||||
//Init blok
|
||||
_currentPosition = _gameClient.CurrentLobbyState.MapData.Center;
|
||||
_mapCenter = _gameClient.CurrentLobbyState.MapData.Center;
|
||||
_lastSentPosition = _currentPosition;
|
||||
}
|
||||
//Init blok
|
||||
_currentPosition = state.MapData.Center;
|
||||
_mapCenter = state.MapData.Center;
|
||||
_lastSentPosition = _currentPosition;
|
||||
}
|
||||
|
||||
TestPlayerPosition();
|
||||
TestPlayerPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_GPSState == GPSState.Uninitialized)
|
||||
{
|
||||
_coroutineHost.StartCoroutine(InitiallizeGPS());
|
||||
return;
|
||||
}
|
||||
else if (_GPSState == GPSState.Initializing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (_GPSState == GPSState.Running)
|
||||
{
|
||||
EnsureMapCenter();
|
||||
TrySendCurrentPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_GPSState == GPSState.Uninitialized)
|
||||
Debug.Log("GPS failed, trying again...");
|
||||
if (_gpsRetryCount < _maxGpsRetries)
|
||||
{
|
||||
_coroutineHost.StartCoroutine(InitiallizeGPS());
|
||||
return;
|
||||
}
|
||||
else if (_GPSState == GPSState.Initializing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (_GPSState == GPSState.Running)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_currentPosition != _lastSentPosition)
|
||||
{
|
||||
_gameClient.UpdatePosition(_currentPosition);
|
||||
_lastSentPosition = _currentPosition;
|
||||
_player.transform.position = _currentPosition.ToLocalVector3(_mapCenter);
|
||||
_player.transform.rotation = Quaternion.Euler(0, (float)CalculateHeading(_lastSentPosition.ToLocalVector3(_mapCenter), _currentPosition.ToLocalVector3(_mapCenter)), 0);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Log(ex);
|
||||
}
|
||||
_gpsRetryCount++;
|
||||
_GPSState = GPSState.Uninitialized;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("GPS failed, trying again...");)
|
||||
_GPSState = GPSState.Uninitialized;
|
||||
Debug.LogWarning("GPS unavailable after max retries. Using last known position.");
|
||||
// Keep _GPSState = Failed so we stop retrying
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NullReferenceException ex) { Debug.Log(ex); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[Input] positionCheck failed: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureMapCenter()
|
||||
{
|
||||
if (_mapCenter.Lat != 0 || _mapCenter.Lon != 0)
|
||||
return;
|
||||
|
||||
var md = _gameClient?.CurrentLobbyState?.MapData;
|
||||
if (md != null)
|
||||
_mapCenter = md.Center;
|
||||
}
|
||||
|
||||
private void TrySendCurrentPosition()
|
||||
{
|
||||
bool moved = _currentPosition != _lastSentPosition;
|
||||
bool keepAliveDue = (Time.time - _lastPositionSendTime) >= _positionKeepAliveSeconds;
|
||||
if (!moved && !keepAliveDue)
|
||||
return;
|
||||
|
||||
var previous = _lastSentPosition;
|
||||
_gameClient.UpdatePosition(_currentPosition);
|
||||
_lastSentPosition = _currentPosition;
|
||||
_lastPositionSendTime = Time.time;
|
||||
|
||||
if (_player == null || (_mapCenter.Lat == 0 && _mapCenter.Lon == 0))
|
||||
return;
|
||||
|
||||
var localCurrent = _currentPosition.ToLocalVector3(_mapCenter);
|
||||
_player.transform.position = localCurrent;
|
||||
|
||||
if (previous.Lat == 0 && previous.Lon == 0)
|
||||
return;
|
||||
|
||||
var heading = CalculateHeading(previous.ToLocalVector3(_mapCenter), localCurrent);
|
||||
if (heading.HasValue)
|
||||
_player.transform.rotation = Quaternion.Euler(0, (float)heading.Value, 0);
|
||||
}
|
||||
|
||||
private void TestPlayerPosition()
|
||||
{
|
||||
double x = Input.GetAxis("Horizontal");
|
||||
@@ -136,11 +193,7 @@ namespace Subsystems
|
||||
_player.transform.position = localCurrent;
|
||||
try
|
||||
{
|
||||
if (_currentPosition != _lastSentPosition)
|
||||
{
|
||||
_gameClient.UpdatePosition(_currentPosition);
|
||||
_lastSentPosition = _currentPosition;
|
||||
}
|
||||
TrySendCurrentPosition();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -150,63 +203,42 @@ namespace Subsystems
|
||||
}
|
||||
private double? CalculateHeading(Vector3 first, Vector3 second)
|
||||
{
|
||||
double? heading = null;
|
||||
if ((first - second).magnitude == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (first.x == second.x && first.z < second.z)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (first.x == second.x && first.z > second.z)
|
||||
{
|
||||
return 180;
|
||||
}
|
||||
else if (first.x > second.x && first.z == second.z)
|
||||
{
|
||||
return 270;
|
||||
}
|
||||
else if (first.x < second.x && first.z == second.z)
|
||||
{
|
||||
return 90;
|
||||
}
|
||||
else if (first.x < second.x && first.z < second.z)
|
||||
{
|
||||
heading = Math.Asin((second.z - first.z) / first.DistanceTo(second));
|
||||
return (heading * 180) / Math.PI;
|
||||
}
|
||||
else if (first.x < second.x && first.z > second.z)
|
||||
{
|
||||
heading = Math.Asin((second.z - first.z) / first.DistanceTo(second));
|
||||
return (heading * 180) / Math.PI + 180;
|
||||
}
|
||||
else if (first.x > second.x && first.z < second.z)
|
||||
{
|
||||
heading = Math.Asin((second.z - first.z) / first.DistanceTo(second));
|
||||
return (heading * 180) / Math.PI - 90;
|
||||
}
|
||||
else if (first.x > second.x && first.z > second.z)
|
||||
{
|
||||
heading = Math.Asin((second.z - first.z) / first.DistanceTo(second));
|
||||
return (heading * 180) / Math.PI - 90;
|
||||
}
|
||||
else
|
||||
{
|
||||
return heading;
|
||||
}
|
||||
if ((first - second).magnitude < 0.0001f) return null;
|
||||
float dx = second.x - first.x;
|
||||
float dz = second.z - first.z;
|
||||
float heading = Mathf.Atan2(dx, dz) * Mathf.Rad2Deg;
|
||||
if (heading < 0) heading += 360f;
|
||||
return heading;
|
||||
}
|
||||
IEnumerator InitiallizeGPS()
|
||||
{
|
||||
_GPSState = GPSState.Initializing;
|
||||
|
||||
#if UNITY_ANDROID
|
||||
// Request fine location permission if not already granted
|
||||
if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.FineLocation))
|
||||
{
|
||||
UnityEngine.Android.Permission.RequestUserPermission(UnityEngine.Android.Permission.FineLocation);
|
||||
// Wait up to 10 seconds for user to respond to the permission dialog
|
||||
float waited = 0f;
|
||||
while (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.FineLocation) && waited < 10f)
|
||||
{
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
waited += 0.5f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!Input.location.isEnabledByUser)
|
||||
{
|
||||
Debug.LogError("Location not enabled on device or app does not have permission to access location");
|
||||
_GPSState = GPSState.Failed;
|
||||
yield break;
|
||||
}
|
||||
// Starts the location service.
|
||||
|
||||
float desiredAccuracyInMeters = 10f;
|
||||
float updateDistanceInMeters = 10f;
|
||||
float desiredAccuracyInMeters = 5f;
|
||||
float updateDistanceInMeters = 1f;
|
||||
|
||||
Input.location.Start(desiredAccuracyInMeters, updateDistanceInMeters);
|
||||
|
||||
@@ -225,30 +257,34 @@ namespace Subsystems
|
||||
Debug.LogError("Timed out");
|
||||
yield break;
|
||||
}
|
||||
_GPSState = GPSState.Running;
|
||||
yield return _coroutineHost.StartCoroutine(GPSService());
|
||||
}
|
||||
IEnumerator GPSService()
|
||||
{
|
||||
// Check if the user has location service enabled.
|
||||
|
||||
|
||||
// If the connection failed this cancels location service use.
|
||||
if (Input.location.status == LocationServiceStatus.Failed)
|
||||
{
|
||||
_GPSState = GPSState.Failed;
|
||||
Debug.LogError("Unable to determine device location");
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the connection succeeded, this retrieves the device's current location and displays it in the Console window.
|
||||
_currentPosition = new Position(Input.location.lastData.latitude, Input.location.lastData.longitude);
|
||||
Debug.Log("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp);
|
||||
yield return new WaitForSeconds(5f);
|
||||
}
|
||||
|
||||
// Stops the location service if there is no need to query location updates continuously.
|
||||
yield return _coroutineHost.StartCoroutine(GPSService());
|
||||
_GPSState = GPSState.Running;
|
||||
_gpsRetryCount = 0;
|
||||
_coroutineHost.StartCoroutine(GPSService());
|
||||
}
|
||||
IEnumerator GPSService()
|
||||
{
|
||||
while (_GPSState == GPSState.Running)
|
||||
{
|
||||
if (Input.location.status == LocationServiceStatus.Failed)
|
||||
{
|
||||
_GPSState = GPSState.Failed;
|
||||
Debug.LogError("Unable to determine device location");
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Keep current GPS position fresh; sending is throttled in positionCheck().
|
||||
var data = Input.location.lastData;
|
||||
_currentPosition = new Position(data.latitude, data.longitude);
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user