- Home /
Why is Unity skyrocketing its memory usage?
I am using Unity 5.0.3 on a desktop with 8 GB of RAM. I started with 5.2.1 and kept moving downward. I am developing a proof of concept plugin. The plugin is written in C#, in Mono for whatever version of Unity is installed. All the plugin does right now is open a server socket and accept a connection. The connection just puts the floats it receives into a Queue. The game is the Roll a Ball tutorial. The floats (randomly generated by the client to the server socket, are the SPEED in the game. The plugin is started at scene start(). And after the Thread is spawned, the plugin is called called in the fixed_update(). The call is a DeQueue() on the Queue used in the plugin. It returns (is supposed to) a float, which is then directly assigned to the SPEED variable.
Ok, that is the base. Now the problem: Once I press play, and run through the test the first time, it will work. But, once I stop the scene and try to go back to developing, the memory usage will climb until the HDD is paging constantly. It won't allow using the close window option, or respond at all. Task manager has to be used to kill it. I have tried: cleaning all, rebuild all, both with and without Unity up, removing the installation entirely and reinstalling, and even currently have every shadow in the game turned off. I don't know if it related, but the Unity I was using to start ( 5.2.1 ) would only get 5 out the hundreds of floats sent. But it would get some. After the problem started, it would not receive any. Version 5.0.3 is the first version that started receiving any floats at all. But again, only about the first 5 or 6 out of hundreds. And once it stops, it doesn't get anymore. I am very new to Unity, so other than those general troubleshooting steps listed above, I don't have Unity expertise to go any further without some help. Thank you in advance.
Some code would be the only thing between an answer and guesswork.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using NetControlPlugin;
public class PlayerController : $$anonymous$$onoBehaviour
{
public float speed;
public Text countText;
public Text winText;
private Rigidbody rb;
private int count;
private $$anonymous$$yClass plugin;
void Start()
{
plugin = new $$anonymous$$yClass (); // Here is where the plugin is started
if (plugin.IsPluginStarted().Equals("true"))
{
print ("Server listening.");
}
else
{
print ("Server failed to start.");
}
rb = GetComponent<Rigidbody> ();
count = 0;
SetCountText();
winText.text = "";
}
void FixedUpdate()
{ // Place physics code here
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
float speed2 = plugin.GetValues (); // Call the plugin here
print ("Speed : " + speed2);
print ("Errors : " + plugin.GetErrors ()); // And here
rb.AddForce (movement * speed2);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("Pickup"))
{
other.gameObject.SetActive (false);
count++;
SetCountText();
}
}
void SetCountText()
{
countText.text = "Count: " + count.ToString ();
if (count >= 11)
{
winText.text = "You Win!!";
}
}
}
And for the plugin code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
namespace NetControlPlugin
{
public class $$anonymous$$yClass
{
static TcpListener serverSocket;
TcpClient clientSocket;
NetworkStream networkStream;
byte[] bytesFrom;
String started;
Boolean moreValues;
static Queue dataWaiting;
static Queue errors;
public string IsPluginStarted()
{
return started;
//return "true";
}
public string GetErrors()
{
return errors.ToString ();
}
public float GetValues()
{
try
{
object obj = (float)dataWaiting.Dequeue ();
float retval = Convert.ToSingle(obj);
return retval;
}
catch(InvalidOperationException ioe)
{
return 20.0f;
}
}
public $$anonymous$$yClass ()
{
IPAddress address = IPAddress.Parse("127.0.0.1");
serverSocket = new TcpListener(address, 8888);
clientSocket = default(TcpClient);
serverSocket.Start();
// Server Started
clientSocket = serverSocket.AcceptTcpClient();
// Accept connection from BT
dataWaiting = new Queue ();
errors = new Queue ();
errors.Enqueue ("In $$anonymous$$yClass");
handleClinet client = new handleClinet();
client.startClient(clientSocket);
errors.Enqueue ("After Started Client invoked");
started = "true";
}
//Class to handle each client request separatly
public class handleClinet
{
TcpClient clientSocket;
public void startClient(TcpClient inClientSocket)
{
errors.Enqueue ("In Start Client");
this.clientSocket = inClientSocket;
Thread ctThread = new Thread(doChat);
ctThread.Start();
}
private void doChat()
{
errors.Enqueue ("In doChat");
byte[] bytesFrom = new byte[10025];
string dataFromClient = "";
Byte[] sendBytes = null;
string serverResponse = null;
string rCount = null;
while ((true))
{
try
{
NetworkStream networkStream = clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
float shit = Convert.ToSingle(dataFromClient);
dataWaiting.Enqueue(shit);
}
catch (Exception ex)
{
errors.Enqueue(ex.ToString());
}
}
}
}
}
}
The server is sent data from the connecting client. The client sends 1 float a second. But I have tried it with no limiter as well.
Answer by Bunny83 · Oct 04, 2015 at 11:26 PM
The answer is quite simple: Your plugin design is horrible ^^. You never terminate your thread, so it will keep running even in edit mode since Unity only has one Mono environment. Threads aren't terminated automatically, only when the appdomain is actually unloaded (when you exit Unity).
Next thing is you use a TCP connection. It's based on a stream, not on messages. That means it's possible that you receive 2 floats at once or only a "half float". This could give you additional problems.
You also don't have any synchronisation / locking between the two threads. This could result in random errors as well.
Argh, ter$$anonymous$$ate the thread. I knew this but I didnt want to sound stupid, which I inevitably would have : I was also thinking, unload dll, kill stream.
He can't unload the DLL since it's a managed DLL. Once a DLL is loaded (statically or dynamically) it can't be unloaded. The only thing you can unload is an AppDomain. It's possible to create a new AppDomain, dynamically load a DLL and unload that AppDomain, but the communication between two AppDomains is a pain.
In the end it's just managed code, so it's not an actual "plugin". It's just managed code like all the scripts in Unity but precompiled.
Bunny83, yep. The POC was a throw this new language at the wall and see what sticks. I didn't even think about the life cycle of the thread under the DLL. Once I put in the thread stop mechanism in there, and called that method from OnApplicationQuit(), all went back to being well. Thank you for the quick and accurate help! Well done.
Your answer
![](https://koobas.hobune.stream/wayback/20220612040008im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Receive events from C++ code 0 Answers
Plugins colliding with each other. 0 Answers
Finding the Problematic dll in "Extracting Referenced dlls Failed" (Unity5) 1 Answer
GL POINT_SIZE doesn't works in BUILD on Linux Unity Editor 5.4.3f1. Works only in Editor 0 Answers
Vive HMD tracking does not work 2 Answers