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