Face Recognition with Unity and SDK Watson - c#

I would like to do facial recognition with the feed of the camera of my computer with Unity and SDK Watson. I looked for some tutorials and demos in the internet and I think finally get it. This is one of my first projects in Unity so I would be so grateful if someone could help me to correct two errors I cannot fix.
I use this code for camera render and capture the image:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CameraRender : MonoBehaviour {
public Image overlay;
public FaceDetector fd;
// Use this for initialization
void Start () {
WebCamTexture backCam = new WebCamTexture();
backCam.Play();
overlay.material.mainTexture = backCam;
}
public void CaptureImage()
{
ScreenCapture.CaptureScreenshot(Application.persistentDataPath + "/screenshot.png");
fd.DetectFaces(Application.persistentDataPath + "/screenshot.png");
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0))
{
CaptureImage();
}
}
}
And this other one for face detection:
using IBM.Watson.DeveloperCloud.Connection;
using IBM.Watson.DeveloperCloud.Logging;
using IBM.Watson.DeveloperCloud.Services.VisualRecognition.v3;
using IBM.Watson.DeveloperCloud.Utilities;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class FaceDetector : MonoBehaviour {
public Text dataOutput;
private VisualRecognition _visualRecognition;
// Use this for initialization
void Start ()
{
Credentials credentials = new Credentials(apiKey: "key", url: "url");
_visualRecognition = new ExampleVisualRecognition(credentials)
{
VersionDate = "2016-05-20"
};
}
public void DetectFaces(string path)
{
// Classify using image url
//if (!_visualRecognition.DetectFaces("<image-url>", OnDetectFaces, OnFail))
// Log.Debug("ExampleVisualRecognition.DetectFaces()", "Detect faces failed!");
// Classify using image path
if (!_visualRecognition.DetectFaces(OnDetectFaces, OnFail, path)) {
Log.Debug("ExampleVisualRecognition.DetectFaces()", "Detect faces failed!");
} else
{
Debug.Log("Calling Watson");
dataOutput.text = "";
}
}
private void OnDetectFaces(DetectedFaces multipleImages, Dictionary<string, object> customData)
{
var data = multipleImages.images[0].faces[0]; //assume 1
dataOutput.text = "Age : " + data.age.min + "-" + data.age.max + " PROBABILITY: " + data.age.score + "\n" + "Gender" + data.gender.gender + " PROBABILITY: " + data.age.score + "\n";
Log.Debug("ExampleVisualRecognition.OnDetectFaces(): Detect faces result: {0}", customData["json"].ToString());
}
private void OnFail(RESTConnector.Error error, Dictionary<string,object> customData)
{
Debug.LogError("ExampleVisualRecognition.OnFail(): Error received: " + error.ToString());
}
// Update is called once per frame
void Update () {
}
}
But I cannot fix this two errors:
NotImplementedException: The requested feature is not implemented. IBM.Watson.DeveloperCloud.Services.VisualRecognition.v3.VisualRecognition.op_Implicit (.ExampleVisualRecognition v) (at Assets/Watson/Scripts/Services/VisualRecognition/v3/VisualRecognition.cs:1444)
FaceDetector.Start () (at Assets/FaceDetector.cs:21)
NullReferenceException: Object reference not set to an instance of an object
FaceDetector.DetectFaces (System.String path) (at Assets/FaceDetector.cs:35)
CameraRender.CaptureImage () (at Assets/CameraRender.cs:20)
CameraRender.Update () (at Assets/CameraRender.cs:27)
Could someone bring some help? Thank you all.

You are instantiating ExampleVisualRecognition when you should be instantiating VisualRecognition. Please see this gist.
private IEnumerator CreateService()
{
// Create tokenOptions
TokenOptions visualRecognitionTokenOptions = new TokenOptions()
{
IamApiKey = visualRecognitionApiKey
};
// Create credentials
Credentials visualRecognitionCredentials = new Credentials(visualRecognitionTokenOptions, visualRecognitionServiceUrl);
// Wait for tokendata
while (!visualRecognitionCredentials.HasIamTokenData())
yield return null;
// Instantiate service
visualRecognition = new VisualRecognition(visualRecognitionCredentials);
// Set version date
visualRecognition.VersionDate = versionDate;
// Classify
visualRecognition.DetectFaces(OnDetectFaces, OnFail, imagePath);
}
private void OnDetectFaces(DetectedFaces response, Dictionary<string, object> customData)
{
// Print response json to console
Log.Debug("ClassifyExample", "{0}", customData["json"].ToString());
// Print gender, age and confidence
Log.Debug("ClassifyExample", "gender: {0}, score: {1}, age: {2} - {3}, score: {4}", response.images[0].faces[0].gender.gender, response.images[0].faces[0].gender.score, response.images[0].faces[0].age.min, response.images[0].faces[0].age.max, response.images[0].faces[0].age.score);
}
// Fail callback
private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
Log.Debug("ClassifyExample", "Failed to classify");
}
}

Related

HoloLens 2 throwing NotSupportedException on System.Net.Http.WebRequestHandler

I am trying to use Azure Cognitive Services (OCR) on the HoloLens 2. I'm using their .NET demo application with Nuget for Unity and importing all the necessary libraries. Everything compiles the way it should, but in runtime on the HoloLens, the code fails to execute the authentication part, saying there's a NotSupportedException. I've checked Internet/Client capabilities in Unity and I'm using the .NET 2.0 API (using the .NET 4.x doesn't help either). The scripting backend is IL2CPP because it's a UWP app. I'm using Unity 2020.3.13. I've gone through Azure's services and double-checked my endpoints and keys and those all work fine. It works through the Unity editor but fails on the HoloLens side. I've tried adding in a 'using' statement for System.Net.Http and double-checked the .dll is included in my editor folder, but I'm not sure how to make the HoloLens support this call. How do I get the device to access the API from within the code? I am new to networking and POST/GET calls.
Here's the part from UnityPlayer.log that details the exception:
NotSupportedException: System.Net.Http.WebRequestHandler::.ctor
at System.Net.Http.WebRequestHandler..ctor () [0x00000] in <00000000000000000000000000000000>:0
at Microsoft.Rest.ServiceClient`1[T].CreateRootHandler () [0x00000] in <00000000000000000000000000000000>:0
at Microsoft.Rest.ServiceClient`1[T]..ctor (System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <00000000000000000000000000000000>:0
at Microsoft.Azure.CognitiveServices.Vision.ComputerVision.ComputerVisionClient..ctor (Microsoft.Rest.ServiceClientCredentials credentials, System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <00000000000000000000000000000000>:0
at MainController.Start () [0x00000] in <00000000000000000000000000000000>:0
Here's my main program (I've shortened the unnecessary + working methods):
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Linq;
using UnityEngine;
using UnityEngine.Windows.WebCam;
using System.Net.Http;
using TMPro;
public class MainController : MonoBehaviour
{
PhotoCapture photoCaptureObject = null;
public TextMeshPro debugText;
private ComputerVisionClient client;
private static string subscriptionKey = "<key>";
private static string endpoint = "<endpoint>";
private string photoFilePath;
// Start is called before the first frame update
void Start()
{
debugText.text = "In start" + "\n";
ComputerVisionClient client = Authenticate(endpoint, subscriptionKey);
// fails here, in the HL, doesn't even go into the if block
if (client == null)
{
debugText.text += "client is null" + "\n";
}
else
{
debugText.text += "client is not null" + "\n";
}
}
// Update is called once per frame
void Update()
{
}
public static ComputerVisionClient Authenticate(string endpoint, string key)
{
ComputerVisionClient client =
new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
{ Endpoint = endpoint };
return client;
}
public void CaptureImage()
{
// called from ImageCapture button in app
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}
void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
...
// code for use in the HL to capture an image from what the user is seeing
}
void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
...
// save photo as .jpg and store on device
}
void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
...
// check success result and stop photo mode
}
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
photoCaptureObject.Dispose();
photoCaptureObject = null;
ReadFileLocal(client, photoFilePath).Wait();
}
public async Task ReadFileLocal(ComputerVisionClient client, string localFile)
{
debugText.text += "reading file from local" + "\n";
string operationLocation = "";
string operationId = "";
if (!File.Exists(localFile))
{
debugText.text += "file does not exist in the path" + "\n";
}
else
{
debugText.text += "file exists, continuing" + "\n";
}
try
{
// Read text from URL
var textHeaders = await client.ReadInStreamAsync(File.OpenRead(localFile));
// After the request, get the operation location (operation ID)
operationLocation = textHeaders.OperationLocation;
Thread.Sleep(2000);
}
catch (Exception e)
{
debugText.text += "reading file failed" + "\n";
debugText.text += "Exception: " + e + "\n";
}
// <snippet_extract_response>
// Retrieve the URI where the recognized text will be stored from the Operation-Location header.
// We only need the ID and not the full URL
const int numberOfCharsInOperationId = 36;
operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);
// Extract the text
ReadOperationResult results;
do
{
results = await client.GetReadResultAsync(System.Guid.Parse(operationId));
}
while ((results.Status == OperationStatusCodes.Running ||
results.Status == OperationStatusCodes.NotStarted));
// </snippet_extract_response>
// <snippet_extract_display>
// Display the found text.
var textUrlFileResults = results.AnalyzeResult.ReadResults;
foreach (ReadResult page in textUrlFileResults)
{
foreach (Line line in page.Lines)
{
debugText.text += line + "\n";
}
}
}
}

Unity Firebase Null reference problem. After firebase authentication cannot send or recieve data in unity 2020.1.17f

Here is the code i am currently using to send data and receive data:
all the plugins have been downloaded to the latest version.we are trying to use firebase real time database is send and receive scores that have to be implemented in the game.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Firebase.Auth;
using Firebase;
using Google;
using Firebase.Database;
using System.Linq;
public class LBnew : MonoBehaviour
{
private GoogleSignInConfiguration configuration;
private FirebaseAuth auth;
public string userID;
private DatabaseReference reference;
public string webClientId = " <your client id>";
private void Awake()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
var dependencyStatus = task.Result;
if (dependencyStatus == DependencyStatus.Available)
{
FirebaseApp app;
app = FirebaseApp.DefaultInstance;
Initialize();
}
else
{
Debug.Log(" not resolve firebase dependencies");
}
});
}
void Initialize()
{
configuration = new GoogleSignInConfiguration { WebClientId = webClientId, RequestEmail = true, RequestIdToken = true };
auth = FirebaseAuth.DefaultInstance;
userID = FirebaseAuth.DefaultInstance.CurrentUser.DisplayName;
reference = FirebaseDatabase.DefaultInstance.RootReference;
Debug.Log(" initiallized");
sendscore();
}
public void sendscore()
{
StartCoroutine(UpdateScore(10));
}
private IEnumerator UpdateScore(int _score)
{
Debug.Log(" Your userID " + userID);
//Set the currently logged in user score
var DBTask = reference.Child("user").Child(userID).Child("score").SetValueAsync(_score);
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register score task with {DBTask.Exception}");
// Debug.Log(" failed to reg score ");
}
else
{
Debug.Log(" success to reg score ");
}
StartCoroutine(LoadScoreboardData());
}
private IEnumerator LoadScoreboardData()
{
var DBTask = reference.Child("users").OrderByChild("score").GetValueAsync();
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $" load leaderboard task with {DBTask.Exception}");
Debug.Log(" srinu failed to load leaderScoreboardData ");
}
else
{
//Data has been retrieved
DataSnapshot snapshot = DBTask.Result;
//Destroy any existing scoreboard elements
//foreach (Transform child in scoreboardContent.transform)
//{
// Destroy(child.gameObject);
//}
//Loop through every users UID
//foreach (DataSnapshot childSnapshot in snapshot.Children)
//{
foreach (DataSnapshot childSnapshot in snapshot.Children.Reverse<DataSnapshot>())
{
// Instantiate new scoreboard elements
// GameObject scoreboardElement = Instantiate(scoreElement, scoreboardContent);
// scoreboardElement.GetComponent<LbAllList>().NewDataElement(username, Schoolname, score);
Debug.Log(" leaderScoreboardData " + childSnapshot.Child("score"));
}
//}
}
}
}
we are using unity 2020.1.17f as the version of unity
Any help would be appreciated thanks

Unity - Appending Data to Existing Document in Firestore

How do you add data to Firestore without over-writing previous data for the same key? For example, I want to add a document called "Player 1" to the Collections "Trajectory Log." I want to keep track of all the positions for Player 1 throughout one game into a single doc. In other words, how do you append data to a Firestore document?
This is the code I have for writing the data to Firestore. How do I make sure that the "data" is not over-written every time this code runs for the same user? Any help in how to implement this would be appreciated:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Firebase.Firestore;
using System.Threading.Tasks;
using UnityEngine.UI;
using System.Linq;
using System.Threading;
using Firebase.Auth;
public class TrajectoryToFirebase : MonoBehaviour
{
protected bool operationInProgress;
protected Task previousTask;
protected CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
// name of the collection container that documents get stored into
protected string collectionPath = "Trajectory Log";
protected string documentId = "";
public float samplingRate = 1f;
private System.DateTime dt;
private Vector3 lastpos = Vector3.zero;
private Quaternion lastrot = Quaternion.identity;
//public GameStats gameStats;
public Text text;
//Boilerplate taskmanagement code made by the Firebase People
////////////////////////////////////////////////////////////////////////////
class WaitForTaskCompletion : CustomYieldInstruction
{
Task task;
TrajectoryToFirebase dbManager;
protected CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
// Create an enumerator that waits for the specified task to complete.
public WaitForTaskCompletion(TrajectoryToFirebase dbManager, Task task)
{
dbManager.previousTask = task;
dbManager.operationInProgress = true;
this.dbManager = dbManager;
this.task = task;
}
// Wait for the task to complete.
public override bool keepWaiting
{
get
{
if (task.IsCompleted)
{
dbManager.operationInProgress = false;
dbManager.cancellationTokenSource = new CancellationTokenSource();
if (task.IsFaulted)
{
string s = task.Exception.ToString();
Debug.Log(s);
}
return false;
}
return true;
}
}
}
////////////////////////////////////////////////////////////////////////////
//Get the instance of the Firestore database
protected FirebaseFirestore db
{
get
{
return FirebaseFirestore.DefaultInstance;
}
}
private CollectionReference GetCollectionReference()
{
return db.Collection(collectionPath);
}
//Gets the reference to the docuement in Firstore
//Here I am just setting the document manually to the userID of the sign in user
private DocumentReference GetDocumentReference()
{
//documentId = FirebaseAuth.DefaultInstance.CurrentUser.UserId;
documentId = "User 1";
return GetCollectionReference().Document(documentId);
}
// Need function here that sends log data to firestore
// make this so that it checks to see if the document is null, and if it is not, it appends to the previous entry
// Firebase transaction?
public void TrackTrajectory()
{
Debug.Log("Trajectory Tracker Called");
if (transform.position != lastpos || transform.rotation != lastrot)
{
var data = new Dictionary<string, object>
{
{"Time", System.Math.Round(Time.time, 2)},
{"Pos X", System.Math.Round(transform.position.x, 3)},
{"Pos Y", System.Math.Round(transform.position.y, 3)},
{"Pos Z", System.Math.Round(transform.position.z, 3)},
{"Rot X", System.Math.Round(transform.rotation.x, 3)},
{"Rot Y", System.Math.Round(transform.rotation.y, 3)},
{"Rot Z", System.Math.Round(transform.rotation.z, 3)},
};
StartCoroutine(WriteDoc(GetDocumentReference(), data));
Debug.Log("I recorded trajectory data");
// append here? firestore transaction?
lastpos = transform.position;
lastrot = transform.rotation;
}
}
// starts "timer" to start recording position and orientation?
public void Start()
{
dt = System.DateTime.Now;
Debug.Log(dt.ToString("yyyy-MM-dd-H-mm-ss"));
InvokeRepeating("TrackTrajectory", 0f, 1f / samplingRate);
}
// *** what does this do?
public void readDataButton()
{
StartCoroutine(ReadDoc(GetDocumentReference()));
}
private static string DictToString(IDictionary<string, object> d)
{
return "{ " + d
.Select(kv => "(" + kv.Key + ", " + kv.Value + ")")
.Aggregate("", (current, next) => current + next + ", ")
+ "}";
}
//Writes the data
private IEnumerator WriteDoc(DocumentReference doc, IDictionary<string, object> data)
{
Task setTask = doc.SetAsync(data);
yield return new WaitForTaskCompletion(this, setTask);
if (!(setTask.IsFaulted || setTask.IsCanceled))
{
Debug.Log("Data written");
}
else
{
Debug.Log("Error");
}
}
private IEnumerator ReadDoc(DocumentReference doc)
{
Task<DocumentSnapshot> getTask = doc.GetSnapshotAsync();
yield return new WaitForTaskCompletion(this, getTask);
if (!(getTask.IsFaulted || getTask.IsCanceled))
{
DocumentSnapshot snap = getTask.Result;
IDictionary<string, object> resultData = snap.ToDictionary();
text.text = DictToString(resultData);
Debug.Log("Data read");
}
else
{
text.text = "Error";
}
}
}
You have to use UpdateAsync() instead of SetAsync()
You can read here the Firebase documentation on updates

separate spaces for each user

Sorry for my bad english. The application reads data from the accelerometer of the smartphone. He has a server in which when a smartphone is connected, a pair of id-data about the position in space is created. At the moment, data from all users come to the server. The task is to do the opposite: each time a user connects, a separate space is created that receives data from only one id.
Server code:
var express = require('express');
var compression = require('compression');
var http = require('http');
var path = require('path');
var socketIO = require('socket.io');
const port = process.env.PORT || 5000;
var cors = require('cors');
var app = express();
var server = http.Server(app);
var io = socketIO(server);
app.use(cors()) ;// Use this after the variable declaration
app.set('port', port);
app.use(compression());
app.use(express.static(__dirname + '/'));
app.use('/static', express.static(__dirname + '/static'));
// Routing
app.get('/', function (request, response) {
response.sendFile(path.join(__dirname, 'view.html'));
console.log(Object.keys(player_move).length);
if (Object.keys(player_move).length >= 1){
let data = {
id: socketId,
x: player_move[socketId].x,
z: player_move[socketId].z,
};
response.send(data);
console.log('connected');
}else{
response.send("no");
console.log('not connected');
};
});
app.use(express.static(__dirname + '/client/'));
// Routing
app.get('/view', function (request, response) {
response.sendFile(path.join(__dirname, '/client/index.html'));
});
server.listen(port, function () {
console.log('Старт сервера по адресу localhost:' + port);
console.log('Старт просмотра по адресу localhost: ' + port + ' /view');
});
var player_move = {};
var socketId;
io.on('connection', function (socket) {
socket.on('new player', function () {
console.log('new player');
socket.emit('ok');
});
socket.on('disconnect', function () {
});
socket.on('movement', function () {
console.log('movement');
console.log('player_move', player_move);
if (player_move[socketId]) {
let data = {
id: socketId,
x: player_move[socketId].x,
z: player_move[socketId].z,
};
socket.emit('ok', data);
}
});
socket.on('phone_data', function (data) {
console.log('phone_date', data);
socketId = socket.id;
player_move[socket.id] = {
x: data.x,
z: data.z
};
});
// GET method route
app.get('/', function (req, res) {
res.send('Contact');
console.log("est kontakt");
});
});
socket code:
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
using UnityEngine.Networking;
public class SocketController : MonoBehaviour
{
[SerializeField]
PlayerController player;
// Start is called before the first frame update
void Start()
{
StartCoroutine(GetRequest("http://plantgo.ru:5000"));
}
private void Awake()
{
//socket.url = "ws://127.0.0.1:5000/socket.io/?EIO=4&transport=websocket";
}
// Update is called once per frame
void Update()
{
}
//private IEnumerator Connector()
//{
// while (true)
// {
// socket.Emit("movement");
// yield return new WaitForSeconds(0.10f);
// }
// wait 1 seconds and continue
// }
class PlayerInfo
{
public string id;
public string x;
public string z;
}
IEnumerator GetRequest(string uri)
{
while (true)
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
{
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
string[] pages = uri.Split('/');
int page = pages.Length - 1;
if (webRequest.isNetworkError)
{
Debug.Log(pages[page] + ": Error: " + webRequest.error);
}
else
{
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
if (webRequest.downloadHandler.text == "no")
{
continue;
}
else
{
PlayerInfo playerInfo = (PlayerInfo)JsonUtility.FromJson<PlayerInfo>(webRequest.downloadHandler.text);
Debug.Log(playerInfo);
player.PlayerMove(float.Parse(playerInfo.x, CultureInfo.InvariantCulture), float.Parse(playerInfo.z, CultureInfo.InvariantCulture));
}
}
}
//yield return new WaitForSeconds(0.1f);
}
}
}
when I start the server, several users can control the character at once, since they are in the same game space, it is necessary for each to have its own.

WWW/UnityWebRequest POST/GET request won't return the latest data from server/url

I am creating a HoloLens app using Unity which has to take data from a REST API and display it.
I am currently using WWW datatype to get the data and yield return statement in a coroutine that will be called from the Update() function. When I try to run the code, I get the latest data from the API but when someone pushes any new data onto the API, it does not automatically get the latest data in real time and I have to restart the app to see the latest data.
My Code:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
public class TextChange : MonoBehaviour {
// Use this for initialization
WWW get;
public static string getreq;
Text text;
bool continueRequest = false;
void Start()
{
StartCoroutine(WaitForRequest());
text = GetComponent<Text>();
}
// Update is called once per frame
void Update()
{
}
private IEnumerator WaitForRequest()
{
if (continueRequest)
yield break;
continueRequest = true;
float requestFrequencyInSec = 5f; //Update after every 5 seconds
WaitForSeconds waitTime = new WaitForSeconds(requestFrequencyInSec);
while (continueRequest)
{
string url = "API Link goes Here";
WWW get = new WWW(url);
yield return get;
getreq = get.text;
//check for errors
if (get.error == null)
{
string json = #getreq;
List<MyJSC> data = JsonConvert.DeserializeObject<List<MyJSC>>(json);
int l = data.Count;
text.text = "Data: " + data[l - 1].content;
}
else
{
Debug.Log("Error!-> " + get.error);
}
yield return waitTime; //Wait for requestFrequencyInSec time
}
}
void stopRequest()
{
continueRequest = false;
}
}
public class MyJSC
{
public string _id;
public string author;
public string content;
public string _v;
public string date;
}
This is happening because resources caching is enabled on the Server.
Three possible solutions I know about:
1.Disable resources caching on the server. Instructions are different for every web server. Usually done in .htaccess.
2.Make each request with unique timestamp. The time should in Unix format.
This method will not work on iOS. You are fine since this is for HoloLens.
For example, if your url is http://url.com/file.rar, append ?t=currentTime at the end. currentTime is the actual time in Unix Format.
Full example url: http://url.com/file.rar?t=1468475141
Code:
string getUTCTime()
{
System.Int32 unixTimestamp = (System.Int32)(System.DateTime.UtcNow.Subtract(new System.DateTime(1970, 1, 1))).TotalSeconds;
return unixTimestamp.ToString();
}
private IEnumerator WaitForRequest()
{
string url = "API Link goes Here" + "?t=" + getUTCTime();
WWW get = new WWW(url);
yield return get;
getreq = get.text;
//check for errors
if (get.error == null)
{
string json = #getreq;
List<MyJSC> data = JsonConvert.DeserializeObject<List<MyJSC>>(json);
int l = data.Count;
text.text = "Data: " + data[l - 1].content;
}
else
{
Debug.Log("Error!-> " + get.error);
}
}
3.Disable Cache on the client side by supplying and modifying the Cache-Control and Pragma headers in the request.
Set Cache-Control header to max-age=0, no-cache, no-store then set Pragma header to no-cache.
I suggest you do this with UnityWebRequest instead of the WWW class. First, Include using UnityEngine.Networking;.
Code:
IEnumerator WaitForRequest(string url)
{
UnityWebRequest www = UnityWebRequest.Get(url);
www.SetRequestHeader("Cache-Control", "max-age=0, no-cache, no-store");
www.SetRequestHeader("Pragma", "no-cache");
yield return www.Send();
if (www.isError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Received " + www.downloadHandler.text);
}
}

Categories

Resources