Joystick Controller - Web Server - Unity Game

Hi there,

I'm trying to get a Joystick data values, map them and send them to a web server using NodeMCU.
Get the data from the web server and use it in a Unity Game to control a Player's movement.

The problem: The response time from Joystick to the Player movement is VERY SLOW.

I'm trying to make it so that the response time is acceptable, and still stick to the main ideea: using a web server to communicate with the Unity Game.

If there is a better ideea to my approach in the code, please lend me a hand.

Here's the NodeMCU code:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
const char* ssid = "xxx";
const char* password = "xxx";
ESP8266WebServer server(80);
    #define S0  D0
    #define S1  D1
    #define S2  D2
    #define S3  D3
    #define SIG A0
    #define BP  D7
    int sensor13;
    int sensor14;
    int sensor15;
    char commandArray[16];
    char temp[8];
void setup() {
    pinMode(S0,OUTPUT);      
    pinMode(S1,OUTPUT); 
    pinMode(S2,OUTPUT);
    pinMode(S3,OUTPUT);
    pinMode(SIG, INPUT); 
    pinMode(BP, INPUT);
    Serial.begin(9600);
    delay(200);
    Serial.println("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) 
    {
      delay(1000);
      Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected..!");
    Serial.print("Got IP: ");  
    Serial.println(WiFi.localIP());
    
    server.on("/", serverHandler);
    server.begin();
    Serial.println("HTTP server started");
}
void loop() {
    server.handleClient();
    sensor13 = digitalRead(BP);
    // Channel 14 (C14 pin - binary output 0,1,1,1)
    digitalWrite(S0,LOW); digitalWrite(S1,HIGH); digitalWrite(S2,HIGH); digitalWrite(S3,HIGH);
    sensor14 = analogRead(SIG);
    // Channel 15 (C15 pin - binary output 1,1,1,1)
    digitalWrite(S0,HIGH); digitalWrite(S1,HIGH); digitalWrite(S2,HIGH); digitalWrite(S3,HIGH);
    sensor15 = analogRead(SIG);
  
    Serial.print("X : ");Serial.print(mapCoordinate(sensor14));
    Serial.print("    Y : ");Serial.print(-mapCoordinate(sensor15));
    Serial.print("    B : ");Serial.println(sensor13);
    commandString(sensor13, sensor14, sensor15);
    delay(500);
}
void serverHandler() {
  server.send(200, "text/html", commandArray);
}
void commandString(unsigned int sw,unsigned int x,unsigned int y){
  itoa(sw, temp, 10);
  strcpy(commandArray, temp); strcat(commandArray, ";");
  itoa(mapCoordinate(x), temp, 10);
  strcat(commandArray, temp); strcat(commandArray, ";");
  itoa(-mapCoordinate(y), temp, 10);
  strcat(commandArray, temp); 
}
int mapCoordinate(int coordinate){
  if(coordinate >= 0 && coordinate <= 255) return -1;
  else if(coordinate >= 256 && coordinate <= 767) return 0;
  else if(coordinate >= 768 && coordinate <= 1024) return 1;
}

And here is the Unity Code:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System;
public class joycontroller : MonoBehaviour
{
    string currentWebString, lastWebString = "2";
    public CharacterController controller;
    float horizontal = 0f, vertical= 0f;
    public float speed = 15f;
    public float gravity = -19.62f;
    public float jumpHeight = 2f;
    public Transform groundCheck;
    public float groundDistance = 0.3f;
    public LayerMask groundMask;
    Vector3 velocity;
    bool isGrounded, jump;
    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        StartCoroutine(GetRequest("http://192.168.0.102/"));
    }
    void Update()
    {
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
        if(isGrounded && velocity.y < 0f)
        {
            velocity.y = -2f;
        }
        Vector3 move = transform.right * horizontal + transform.forward * vertical;
        controller.Move(move * speed * Time.deltaTime);
        if(jump && isGrounded)
        {
            velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
            jump = false;
        }
        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }

    void moveCommander(string commandString)
    {
        char[] spearator = { ';'};
        Int32 count = 3;
        String[] tempString = commandString.Split(spearator, count, StringSplitOptions.None);
        int[] commandArray = Array.ConvertAll(tempString, int.Parse);
        if(commandArray[0] == 1) jump = true;
        else jump = false;
        horizontal = commandArray[1];
        vertical = commandArray[2];
        Debug.Log("Button: " + commandArray[0] + " X: " + commandArray[1] + " Y: " + commandArray[2]);
    }

    IEnumerator GetRequest(string uri)
    {
        while (true)
        {
            UnityWebRequest uwr = UnityWebRequest.Get(uri);
            yield return uwr.SendWebRequest();
            
            if (uwr.isNetworkError)
            {
                Debug.Log("Error While Sending: " + uwr.error);
            }
            else
            {
                currentWebString = uwr.downloadHandler.text;
                if(!String.Equals(currentWebString, lastWebString)) moveCommander(currentWebString);
                lastWebString = String.Copy(currentWebString);
            }
            yield return new WaitForSeconds(0.1f);
        }
    }
}

And a little video with a demonstration:
https://youtu.be/xttRqo-II8E

What is that? There is a way to measure time delays, response time. It's called seconds, minutes etc.....
"response time is acceptable".... The same comment as above. What is "acceptable"?

Well.. as we can see from the video, the delay is about 1 second or more, from when I drag the Joystick to one direction, to when the player moves.

I would like to have a shorter delay, the shorter the better.

What I was mainly asking was how could I optimize my code from the Unity Game, to make the delay shorter.

I suggest old fashioned debugging using serial monitor and Serial.print.
In the device sending data, print when it is ready to send, if it has to wait for the channel to be free etc.
In the receiving device do the corresponding thing, print when the loop asks for data....
If You include the value of millis() in the printout maybe You can see something. Is it the sending side or the receiving side?
Could using a hard wired digital test line between the sender and receiver add debugging? Like the sender sets the test signal active when a message is sent and the receiver somehow reads this and starts an internal timer.... That would tell how slow/fast the cloud/server is.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.