I have a method which instantiates a lot of objects with this for loop
for(int i = 0; i < 8; i++){
Vector3 position = new Vector3(Random.Range(player.position.x+30f, player.position.x+80f), Random.Range(player.position.y, player.position.y+40), 0);
Instantiate(prefabs[Random.Range(0, 15)], position, Quaternion.identity);
}
Based on gameplay this loop runs let's say every 5-10 seconds. (based on checking some parameters in Update()
After some time I use gameObject.Destroy() on not needed objects. And here comes the problem:
On Instantiate I see 70% CPU usage in Profiler
On Destroy I see 10-20% CPU usage in Profiler
Sometimes Destroy and Instantiate methods would run at the same time causing CPU throttle.
Need to say that I'm targeting Mobile. The FPS is okay, but when testing the game, the mobile phone gets hot in a minute. I am really sure that is not how I should do this. I've read about polling but not sure how to reproduce it based on this code.
I am testing on Huawei Ascend G600, but I guess it's not the phones problem because Profiler shows the same high CPU usage on the desktop too.
Solved by using Spawning Pool by John Johnson. Very easy implementation:
GameObject obj = SpawningPool.createFromCache(""+Random.Range(0, 15))
All prefabs are atached to SpawningPool object and are accesed via key name.
Instead of Destroy() I am now using SpawningPool.ReturnToCache(gameObject)
Totally recommend, CPU usage is reduced dramatically.
Related
I'm running a robot simulation in unity where each of the 300 robots runs the same script and I'm using RayCast for communication between robots. Each robot cast 36 Rays in 10 degree increments to cover all 360 degree every 0.02s. This is done using the RaycastCommand so its done in parallel and isn't causing any performance issues. The issue comes when trying to process the RayCast Data.
I need to loop over every result and compare the tags and ID in each robot script as such:
for(int k =0; k< results.Length; k++) // For every result
{
if(results[k].collider !=null) // Check if RayCast collision happened
{
if(results[k].collider.tag == "Robot") // Check that collision is with robot
{
var ID = results[k].collider.GetComponent<RobotControl>().ID; // Get The robot ID
if(!listID.Contains(ID)) // Check that it hasnt comunicated with that robot yet
{
listID.Add(ID);
Debug.DrawRay(origin + (0.55f* Directions[k]), Directions[k] * results[k].distance , new Color(Directions[k].x, Directions[k].y, Directions[k].z, 1));
// Grab important info here
}
}
}
}
The main problem being I cant use IJobParallelFor since I'm accessing the collider and trying to read the tag, and this is the part of the code tanking my performance since everything else is done using Parallel Jobs. The real issue is accessing the components is expensive.
Any Ideas on how to make it more efficient or somehow parallelize it?
Is there a way to access GameObject specific data, like ID, without accessing their components?
In general instead of 36 casts per robot can't you just use a Physics.OverlapSphere would probably already reduce it a lot since an overlap sphere is pretty easy to compute for the physics engine (if(distance < sphereRadius))
Then one thing costing a lot performance in your case is probably that Contains on a List. There you should rather use a HashSet. See Performance List vs HashSet for your 300 objects that would probably be worth it.
Or further to me it sounds like you would want to know which other robots are close to that one ... you could give each robot a SphereCollider on a certain layer so they only collide with each other, make it Triggers and store them in OnTriggerEnter andremove them in OnTriggerExit.
Is there a way to access GameObject specific data, like ID, without accessing their components?
Well, yes, you can access GameObject specific data like e.g. .name. But that ID is clearly not something GameObject specific but in your RobotControl class so, no, there is not really a way around GetComponent.
However, in newer Unity versions the GetComponent isn't that expensive anymore since the references are hashed and serialized on edit time.
Question is do you really need that ID list or would it be enough to simply save the collider/GameObject references and access the specific component only when really needed?
In your specific case here also the Debug.DrawRay is something extremely expensive and you should not do it too often and for possible 300 * 299 times ;)
I have the following method in my code:
private void OnMouseDown()
{
cube.transform.position = new Vector3(0, 1, 0);
}
When clicked on the gameObject, this method is called. It takes long to change the position of the cube (not more than a second, but still long, at least half a second). It does affect the user playing experience.
If I don't change the position of the cube, but for example its material, it is still slow. So I do know that this doesn't have to do with the line in my OnMouseDown() event.
Note however that I do have around 35 imported 3D meshes in my Scene, as well as over 50 primitive game objects. Does this have anything to do with the method being slow? Because when I make an empty Unity project with just 2 gameObjects, the method is fast.
Is it because of my full scene? Any ideas? Thanks!
If someone knows how to speed it up as well, I'd love to know!
EDIT: If I remove all my 3D meshes, the method is fast...
Unless your transfom tree is hundereds of children deep, this should be pretty much instant, its one of the things Unity has been designed to do quickly, so I think this has to do with the meshes you import. The should not have too many verticies, too many materials, and too many objects.
You can try to go through you objects with a 3D editor package (blender?) and combine the chunks into single objects.
If unity lags when you move an object, it may mean it has too many individual transforms to process. If your scene is intense you can gain a lot of performance by 'baknig' it, combining individual objects into larger meshes (those live on the gpu and cost gpu time not cpu time).
It is also possible that one or more of the meshes you imported has too many verts/triangles. If you currently have 10fps you may want to target having lighter meshes, and as few seperate GameObjects as possible (ideally you want the environment to be just a few combined meshes (to enable culling), not thousands of objects)
solution
Try to check if there are heavy materials are used that can slow the procedure. The game becomes slow when the objects are being added in the project and it destroy the overall efficiency of the game . It happens with me when i used too heavy models in the project the overall speed of the game is decreased . I replaced them with lightweight models of truck and issue was resolved .
I'm making a mobile clone of pacman for android. Everything is working fine, but I am trying to optimize my game as much as possible.
Currently in some scripts I am finding GameObject's by doing GameObject.Find() in the Start() function of my scripts, like this:
void Start()
{
ghosts = GameObject.FindGameObjectsWithTag("Ghost");
pacman = GameObject.Find("Pacman");
gameManager = GameObject.Find("Game Manager").GetComponent<GameManager>();
}
My question is, would performance increase if I made some of these GameObject's inspector assigned variables instead of doing .Find()?
Would that increase the performance speed or would it make no difference seen as though I do a .Find() in the Start() function?
Obviously performance would decrease if it was called in the Update() as the script would try and find a GameObject every frame, but a Start() function would only search for it once?
Performance at startup for this kind of things is totally negligible, Inspector assignment requires deserialization, while Find requires message dispatch, both are slow operations, if you think that matters, profile that.
I would anyway use
FindObjectOfType<GameManager>() as GameManager
wich is at least more typesafe, I would not use editor inspection if possible, because manual wiring is source of many little errors. So I give a human-time performance reason:
Do not use editor inspection because if you miss to wire something you will have to debug a nullpointer wich on the long run will eat hours of your time.
You have anyway to use Editor Insection in cases where you do not have just to find 1 component, no workaround for that (unless you use Svelto or Svelto-ECS wich are rather advanced topics.)
I'm doing a chess game with AI in it.
There are some functions that handle the rule of game, like DoMove(), DoSkill().
But for some reasons (most for display cool effects), the function return type is IEnumerator instead of void. So the usage of the function look like this :
yield return StartCoroutine(DoSkill());
Now the problem comes, AI is a heavy work, but I've heard that Unity's Coroutines is not suitable for heavy calculating. When I change functions to IEnumerator, the speed of AI obviously getting very slow.
I'm sure that there isn't any WaitForSeconds(someFloat) will be execute in AI(I use some parameter & if/else to skip it), it just seems like the performance is really poor if I continuously call StartCoroutine again and again.
The possible solution I can think of is write two kind of DoSkill() funtion, one's return type is void , the other is IEnumerator. but it's really not a good way. because I have to maintain lots of similar functions, and it's ugly too.
Any suggestions would be greatly appreciated.
Coroutines are nothing magical - they are a way to have a function keep giving up control mid-execution, and continuing on next time they are pumped. They exist really to allow developers to avoid writing multi-threaded code.
The reason they don't work for heavy calculations is that they are executed in the main thread, so any long running code would effectively kill your frame rate.
They do work where you know you can do a small deterministic pieces of work and defer for next time - such as processing downloaded byte streams, copying data, etc. So if you are running smoothly at 60FPS you know you have 16 ms to do everything in a frame, and heavy calculations might be variable in time and hard to know ahead. If you exceed 16 ms in total (everything including your calculation) the FPS will slow down and the game will appear jerky.
I suggest in your case you run the calculations in a background thread. It's basically:
using UnityEngine;
using System.Threading;
public class ChessAI : MonoBehaviour
{
Thread aiThread;
void StartAI()
{
aiThread = new Thread(new ThreadStart(AIThread));
aiThread.Start();
}
void AIServer()
{
// do stuff here - be careful of accessing data being changed by main thread
}
public void OnApplicationQuit()
{
// It is crucial in the editor that we stop the background thread when we exit play mode
aiThread.Abort();
}
}
I've modified my physics from the last post: Updating physics engine ina separate thread, is this wise? like so:
public void PhysicsThread()
{
int milliseconds = TimeSpan.FromTicks(333333).Milliseconds;
while(true)
{
System.Threading.Thread.Sleep(milliseconds);
world.Step(milliseconds / 1000.0f);
}
}
As before it's running in its own thread. I'm finding something odd which I'm not sure I quite understand, it's a bit difficult to explain so I made a video recording of it: http://www.youtube.com/watch?v=qFf6oSRfVt8
If you look carefully you can see the object being fired from the cannon occasionally stutters and appears to move backwards a set amount of distance. This is only noticable on fast moving objects (such as the projectile being fired).
This has baffled me completely. I've even created a system where I cache the position of bodies in the game logic thread so that as the physics thread may update bodies positions it won't affect the positions being read in by the game logic until an update function is called within the game logic thread which updates the physics bodies positions for the game logic to read.
Any ideas what aspect of multithreading may be causing this issue? I don't think it's the physics engine updating the bodies positions during game logic and drawing as I've alrady mentioned I cache that and it remains constant throughout...
My first guess is that you may have a classic race condition, where multiple threads are competing to update the object's position without locking or ordering guarantees.
You can check Wikipedia to learn more about race conditions, locking, and other fundamentals of multithreading/multiprocessing.
It's hard to say more without seeing more of your code, especially the part that does the update.
Edit: One thing you can do is to store DateTime.Now on each loop, and compare it with the previous value. If your time delays are inconsistent you'll see it.
Another thing to check is to see how long your world.Step() function is taking to execute (again using DateTime.Now and some logging, or whatever).
If both of these indicate consistent timing, then my suspicion would fall on the physics engine. Check the position of the object before and after calling world.Step(), and if you see any weird jumps that should tell you where to look.
This should probably be a comment, but it would be difficult to post code. If you're trying to do realtime then this code is prone to time jitter as there's no guarantee that Thread.Sleep will sleep for the perscribed time. I'd use a stopwatch to measure elapsed time and use that to drive your world.
public void PhysicsThread()
{
int milliseconds = TimeSpan.FromTicks(333333).Milliseconds;
var stopwatch=System.Diagnostics.Stopwatch.StartNew();
while(true)
{
System.Threading.Thread.Sleep(milliseconds );
world.Step(stopwatch.ElapsedTicks);
stopwatch.Restart();
}
}