Skip to content

Fix various issues with Unity Joystick SDK #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
#
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/

# MemoryCaptures can get excessive in size.
# They also could contain extremely sensitive data
/[Mm]emoryCaptures/

# Recordings can get excessive in size
/[Rr]ecordings/

# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*

# Autogenerated Jetbrains Rider plugin
/[Aa]ssets/Plugins/Editor/JetBrains*

# Visual Studio cache directory
.vs/

# Gradle cache directory
.gradle/

# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db

# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
*.mdb.meta

# Unity3D generated file on crash reports
sysinfo.txt

# Builds
*.apk
*.aab
*.unitypackage
*.app

# Crashlytics generated file
crashlytics-build.properties

# Packed Addressables
/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*

# Temporary auto-generated Android Assets
/[Aa]ssets/[Ss]treamingAssets/aa.meta
/[Aa]ssets/[Ss]treamingAssets/aa/*

# IDEA
.idea/
94 changes: 57 additions & 37 deletions Runtime/Scripts/Core/Request/WebRequestInternal.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.Networking;
Expand All @@ -14,8 +17,8 @@ public class WebRequestInternal
public event Action<WebRequestResponseData> OnRequestDone;
public event Action<int> OnRequestWillRestart;

private const int RequestTimeOut = 8;
private int _requestAttemptsLimit = 3;
private const int RequestTimeOut = 4;
private int _requestAttemptsLimit = 1;

public WebRequestState RequestState { get; private set; }

Expand All @@ -24,6 +27,7 @@ public class WebRequestInternal

private int _requestTimeOutDuration;
private int _requestAttempts;
private CancellationTokenSource _cancellationTokenSource;

public WebRequestInternal(WebRequest.Configuration configuration)
{
Expand All @@ -47,7 +51,8 @@ private void StartRequest()
if (RequestState == WebRequestState.None)
{
RequestState = WebRequestState.Pending;
WebRequestManager.Instance.StartRequest(this, RequestRoutine());
_cancellationTokenSource = new CancellationTokenSource();
RequestRoutineAsync(_cancellationTokenSource.Token);
}
}

Expand All @@ -56,7 +61,8 @@ private void StopRequest()
if (RequestState == WebRequestState.Pending)
{
RequestState = WebRequestState.None;
WebRequestManager.Instance.StopRequest(this);
_cancellationTokenSource?.Cancel();
_request?.Abort();
DisposeRequest(true);
}
}
Expand All @@ -72,7 +78,8 @@ private void RestartRequest()
OnRequestWillRestart?.Invoke(_requestAttempts);

SetUpRequestConfiguration(_configuration);
WebRequestManager.Instance.RestartRequest(this, RequestRoutine());
_cancellationTokenSource = new CancellationTokenSource();
RequestRoutineAsync(_cancellationTokenSource.Token);
}
}

Expand Down Expand Up @@ -116,57 +123,68 @@ private bool SetUpRequestConfiguration(WebRequest.Configuration configuration)
return configured;
}

private IEnumerator RequestRoutine()
private async Task RequestRoutineAsync(CancellationToken cancellationToken)
{
if (RequestState == WebRequestState.Pending)
try
{
_requestTimeOutDuration = RequestTimeOut + (RequestTimeOut / 2 * _requestAttempts);
_requestAttempts++;
if (RequestState == WebRequestState.Pending)
{
_requestTimeOutDuration = RequestTimeOut + (RequestTimeOut / 2 * _requestAttempts);
_requestAttempts++;

_request.SendWebRequest();
}
var operation = _request.SendWebRequest();
}

float requestProgress = -1f;
float requestStuckTime = 0f;
float requestProgress = -1f;
Stopwatch requestStuckTime = Stopwatch.StartNew();

while (!_request.isDone)
{
bool requestNotProgressing = Mathf.Approximately(requestProgress, _request.uploadProgress + _request.downloadProgress);

if (requestNotProgressing)
while (!_request.isDone)
{
requestStuckTime += Time.deltaTime;
cancellationToken.ThrowIfCancellationRequested();

bool requestNotProgressing = Mathf.Approximately(requestProgress, _request.uploadProgress + _request.downloadProgress);

if (requestStuckTime >= _requestTimeOutDuration)
if (requestNotProgressing)
{
RequestState = WebRequestState.Timeout;
HandleOnRequestTimeOut();
if (requestStuckTime.Elapsed.TotalSeconds >= _requestTimeOutDuration)
{
RequestState = WebRequestState.Timeout;
HandleOnRequestTimeOut();

yield break;
return;
}
}
else
{
requestStuckTime.Restart();
requestProgress = _request.uploadProgress + _request.downloadProgress;
}

await Task.Yield();
}

RequestState = WebRequestState.Completed;

if (_request.result is UnityWebRequest.Result.ConnectionError or UnityWebRequest.Result.DataProcessingError or UnityWebRequest.Result.ProtocolError)
{
JoystickLogger.LogError($"Request result: {_request.result} | ErrorInfo: {_request.error} | Url: {_request.url}");
}
else
{
requestStuckTime = 0f;
requestProgress = _request.uploadProgress + _request.downloadProgress;
JoystickLogger.Log($"Url: {_request.url} | Response Code:{_request.responseCode} | Response Data: {_request.downloadHandler.text}");
}

yield return null;
HandleOnRequestDone();
DisposeRequest(true);
}

RequestState = WebRequestState.Completed;

if (_request.result is UnityWebRequest.Result.ConnectionError or UnityWebRequest.Result.DataProcessingError or UnityWebRequest.Result.ProtocolError)
catch (OperationCanceledException)
{
JoystickLogger.LogError($"Request result: {_request.result} | ErrorInfo: {_request.error} | Url: {_request.url}");
JoystickLogger.Log("Request was cancelled.");
}
else
catch (Exception e)
{
JoystickLogger.Log($"Url: {_request.url} | Response Code:{_request.responseCode} | Response Data: {_request.downloadHandler.text}");
JoystickLogger.LogError($"An error occurred during the request: {e.Message}");
}

HandleOnRequestDone();
DisposeRequest(true);
}

private void HandleOnRequestTimeOut()
Expand Down Expand Up @@ -224,6 +242,8 @@ private void DisposeRequest(bool disposeUploadHandler)
_request.disposeUploadHandlerOnDispose = disposeUploadHandler;
_request.Dispose();
_request = null;
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
}
}
}
}
94 changes: 0 additions & 94 deletions Runtime/Scripts/Core/Request/WebRequestManager.cs

This file was deleted.

11 changes: 0 additions & 11 deletions Runtime/Scripts/Core/Request/WebRequestManager.cs.meta

This file was deleted.

9 changes: 7 additions & 2 deletions Runtime/Scripts/Core/Utilities/JoystickUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Text;
using JoystickRemoteConfig.Core.Data;
using UnityEngine;
Expand Down Expand Up @@ -27,8 +28,9 @@ public static string GetConfigContentAPIUrl(string[] contentIds)

for (int i = 0; i < contentIds.Length; i++)
{
// Ensure each content ID is properly encoded
stringBuilder.Append("\"");
stringBuilder.Append(contentIds[i]);
stringBuilder.Append(Uri.EscapeDataString(contentIds[i]));
stringBuilder.Append("\"");

if (i < contentIds.Length - 1)
Expand All @@ -43,7 +45,10 @@ public static string GetConfigContentAPIUrl(string[] contentIds)
string responseTypeParam = "&responseType=serialized";
string appendParam = shouldSerialized ? responseTypeParam : string.Empty;

return $"https://api.getjoystick.com/api/v1/combine/?c=[{stringBuilder}]&dynamic=true{appendParam}";
// Properly encode the entire 'c=[...]' query parameter
string encodedCParameter = Uri.EscapeDataString($"[{stringBuilder}]");

return $"https://api.getjoystick.com/api/v1/combine/?c={encodedCParameter}&dynamic=true{appendParam}";
}

public static string GetCatalogAPIUrl()
Expand Down