@Kei_Jin I recently had to solve a similar issue myself.
I was using input from a custom USB controller so I had c++ code to handle its input. I created a shared memory location in a c++ program, I used CreateFileMapping since it is stored in ram and so gives the fastest refresh rate. The guides recommend using the global namespace, but that did not work for me, and simply removing it did work.
You will then need to read from that memory address in c#, this is a little complicated as you have to use unsafe code and pinvokes. Also unity will crash if you ever try to access the pointers but they haven’t successfully accessed the memory yet, so be sure to save the project before any testing.
As for transforming your data, just make sure you use the equivalent datatypes on both ends and use Marshal functions to access it. In your case maybe three floats would be best. You may need to cast them from int if there are no marshall float functions.
Useful links:
See code snippetts below for details.
c++ Code:
//For shared memory with Unity
#define BUF_SIZE 256
TCHAR szMapName[] = TEXT("UnityFileMappingObject");
TCHAR szCountName[] = TEXT("UnityFileCountObject");
signed int sharedMemOut[7];
LPCTSTR pBuf;
HANDLE hMapFile;
Init(){
// Request shared memory from the OS to share with Unity
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szMapName); // name of mapping object
if (hMapFile == NULL)
{
printf(TEXT("Could not create file mapping object (%d).
"),
GetLastError());
return -1;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
printf(TEXT("Could not map view of file (%d).
"),
GetLastError());
CloseHandle(hMapFile);
return -1;
}
}
Update(){
sharedMemOut[0] = (int)count;
sharedMemOut[1] = X[0];
sharedMemOut[2] = Y[0];
sharedMemOut[3] = X[1];
sharedMemOut[4] = Y[1];
sharedMemOut[5] = SQ[0];
sharedMemOut[6] = SQ[1];
CopyMemory((PVOID)pBuf, sharedMemOut, (7 * sizeof(signed int)));
}
c# unity code:
using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
public class PlaneController: MonoBehaviour {
//Shared Memory
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern SafeFileHandle OpenFileMapping(
uint dwDesiredAccess,
bool bInheritHandle,
string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr MapViewOfFile(
SafeFileHandle hFileMappingObject,
UInt32 dwDesiredAccess,
UInt32 dwFileOffsetHigh,
UInt32 dwFileOffsetLow,
UIntPtr dwNumberOfBytesToMap);
/*
[DllImport("kernel32.dll", SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
*/
string szMapName = "UnityFileMappingObject";
const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
const UInt32 SECTION_QUERY = 0x0001;
const UInt32 SECTION_MAP_WRITE = 0x0002;
const UInt32 SECTION_MAP_READ = 0x0004;
const UInt32 SECTION_MAP_EXECUTE = 0x0008;
const UInt32 SECTION_EXTEND_SIZE = 0x0010;
const UInt32 SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |
SECTION_MAP_WRITE |
SECTION_MAP_READ |
SECTION_MAP_EXECUTE |
SECTION_EXTEND_SIZE);
const UInt32 FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS;
private SafeFileHandle sHandle;
private IntPtr hHandle;
private IntPtr pBuffer;
private int sharedInputCount;
bool attachSuccessful;
//
int count;
int X0;
int Y0;
int X1 = -1;
int Y1 = -1;
int SQ0 = -1;
int SQ1 = -1;
void Start (){
sHandle = new SafeFileHandle(hHandle, true);
sharedInputCount = 0;
attachSuccessful = Attach(szMapName, 256);
}
unsafe public bool Attach(string SharedMemoryName, UInt32 NumBytes)
{
if (!sHandle.IsInvalid) return false;
sHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, SharedMemoryName);
Debug.Log("Shared mem open: ");
if (sHandle.IsInvalid) return false;
Debug.Log("Shared mem open SUCCESS: ");
pBuffer = MapViewOfFile(sHandle, FILE_MAP_ALL_ACCESS, 0, 0, new UIntPtr(NumBytes));
Debug.Log("Shared mem mapped: ");
return true;
}
unsafe public void Detach()
{
if (!sHandle.IsInvalid && !sHandle.IsClosed )
{
//CloseHandle(hHandle); //fair to leak if can't close
sHandle.Close();
}
pBuffer = IntPtr.Zero;
//lBufferSize = 0;
}
void Update()
{
if (!attachSuccessful)
{
attachSuccessful = Attach(szMapName, 256);
return;
}
}
void OnApplicationQuit()
{
if (attachSuccessful)
{
Detach();
}
}
void FixedUpdate ()
{
//get Shared memory Input
if (!attachSuccessful)
{
return;
}
count = Marshal.ReadInt32(pBuffer, 0);
X0 = Marshal.ReadInt32(pBuffer, 4);
Y0 = Marshal.ReadInt32(pBuffer, 8);
X1 = Marshal.ReadInt32(pBuffer, 12);
Y1 = Marshal.ReadInt32(pBuffer, 16);
SQ0 = Marshal.ReadInt32(pBuffer, 20);
SQ1 = Marshal.ReadInt32(pBuffer, 24);
}
}
I hope that puts you on the right track.