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();
}
}
Related
I have two functionality that need to achieve:
movement
rotation
both must be in Update(), i can combine it but i prefer both of them in separate script in each Movement.cs and Rotation.cs.
So i have two method:
Combine both into one script in and using one Update().
Separate into two script and each of them have Update().
My question : does it cost performance if separate them into each individual Update() instead of combine in one script with one Update().
Both script will be attach on one object, so if i have hundreds of object.
Method 1 - 100 objects and 100 script with Update().
Method 2 - 100 objects and 200 script with Update().
Another question : is it really bad to do Method 2 ?.
This is a case of micro-optimisation. You should use any of the methods that makes more sense in your particular case and after you're done you should to some profiling.
Based on the results of profiling you'll end up knowing where and what to optimise.
Getting back to the problem at hand having 2 Updates will cost you one more function call per frame and some time when your MonoBehaviour is first loaded, but that is negligible, you'll eat a lot more CPU cycles in other parts of your code.
If you can combine, do it. The Unity MonoBehaviours are usefull but eat quickly your resources, especially if you have many scripts running at the same time.
Check this blog ticket : https://blogs.unity3d.com/2015/12/23/1k-update-calls/
WHAT SHOULD YOU DO?
Of course it all depends on your project, but in the field it’s not rare to see a game using a large number of GameObjects in the scene each executing some logic every frame. Usually it’s a little bit of code which doesn’t seem to affect anything, but when the number grows very large the overhead of calling thousands of Update methods starts to be noticeable.
Perhaps a third option would be better for you, it elaborates on the first option but still splits your logic into two separate areas, thus achieving the loose coupling you were going for originally.
public static class Manipulators
{
public static void Rotate(MonoBehaviour behaviour, float amount)
{
Transform t = behaviour.GetComponent<Transform>();
// Do stuff with t
}
public static void Move(MonoBehaviour behaviour, float amount)
{
Transform t = behaviour.GetComponent<Transform>();
// Do stuff with t
}
}
Then in your monobehaviour...
public void Update()
{
Manipulators.Rotate(this, 15f);
Manipulators.Move(this, 15f);
}
Here are some tests I did on how Update() compares to some common Unity3d functions.
In the scene there are 10000 empty GameObjects with UpdateTest script on them.
The Average FPS value is smoothed heavily and I use the Mono backend.
So it seems the cost of Update() function is somewhat less than moving an empty GameObject with transform.localposition.
I've used Unity3d 2020.1.5
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.
So I am currently making a game where you are running and defeating enemies. When you get to the boss and kill him he has a death sound, but what happens is that is plays the death sound all distorted. I don't know what is going on, sometimes are better than others but they are all distorted. MonsterA is my boss Monster and enemy health is his health. here is my code(This is in the Draw() Method):
if (enemyHealth == 0)
{
sprite.PlayAnimation(deathAnimation);
if (spriteSet != "MonsterA")
{
killedSound.Play();
}
if (spriteSet == "MonsterA")
{
bossKilledSound.Play();
}
isDead = true;
}
Put your code in the Update method. The Draw method is ment (pretty much) only for drawing. Also, it's not very clear to me, but the Draw function does't fire just every time after Update. I think it's kind of async, but watis for Update. It's a foggy topic for me, but try putting that code in Update instead of Draw. If that's not the case, try running the game on another PC that is much slower or much faster than the one you are debugging on. That should lead you to the next clue why is this happening.
EDIT:
... assuming that you are not starting the sound on every fire of Draw/Update, witch is not likely because from your explanation, other sounds play well, and only this one is the problem.
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'm developing a 2D overhead shooter game using C# and XNA. I have a class that I'll call "bullet" and need to update many of these instances every fraction of a second.
My first way to do this was to have a generic List of bullets and simply remove and add new bullets as needed. But in doing so the GC kicks in often and my game had some periodic jerky lag. (Alot of code cut out, but just wanted to show a simple snippet)
if (triggerButton)
{
bullets.Add(new bullet());
}
if (bulletDestroyed)
{
bullets.Remove(bullet);
}
My second and current attempt is to have a separate generic Stack of bullets that I push to when I'm done with a bullet, and pop off a bullet when I need a new one if there's anything in the stack. If there's nothing in the stack then I add a new bullet to the list. It seems to cut the jerky lag but then again, sometimes there's still some jerky lag springing up (though I don't know if it's related).
if (triggerButton)
{
if (bulletStack.Count > 0)
{
bullet temp = bulletStack.Pop();
temp.resetPosition();
bullets.Add(temp);
}
else
{
bullets.Add(new bullet());
}
}
if (bulletDestroyed)
{
bulletStack.Push(bullet);
bullets.Remove(bullet);
}
So, I know premature optimization is the root of all evil, but this was very noticeable inefficiency that I could catch early (and this was before even having to worry about enemy bullets filling the screen). So my questions are: Will pushing unused objects to a stack invoke the garbage collection? Will the references by kept alive or are objects still being destroyed? Is there a better way to handle updating many different objects? For instance, am I getting too fancy? Would it be fine to just iterate through the list and find an unused bullet that way?
There are a lot of issues here, and it's tricky to tell.
First off, is bullet a struct or a class? If bullet is a class, any time you construct one, then unroot it (let it go out of scope or set it to null), you're going to be adding something the GC needs to collection.
If you're going to be making many of these, and updating them every frame, you may want to consider using a List<bullet> with bullet being a struct, and the List being pre-allocated (generate it with a size large enough to hold all of your bullets, so it's not being recreated as you call List.Add). This will help dramatically with the GC pressure.
Also, just because I need to rant:
So, I know premature optimization is the root of all evil, but this was very noticeable inefficiency
Never, ever, be afraid to optimize a routine that you know is causing problems. If you're seeing a performance issue (ie: your lags), this is no longer premature optimization. Yes, you don't want to be optimizing every line of code, but you do need to optimize code, especially when you see a real performance issue. Optimizing it as soon as you see it's a problem is much easier than trying to optimize it later, as any design changes required will be much more easily implemented before you've added a lot of other code that uses your bullet class.
You may find the flyweight design pattern useful. There need be only one bullet object, but multiple flyweights may specify different positions and velocities for it. The flyweights can be stored in a preallocated array (say, 100) and flagged as active or not.
That should eliminate garbage-collection completely, and may reduce the space necessary for tracking each bullet's malleable properties.
I will admit that I don't have any experience in this per se, but I would consider using a traditional array. Initialize the array to a size that is more then you need, and would be the theoretical maximum number of bullets, say 100. Then starting at 0 assign the bullets at the beginning of the array, leaving the last element as a null. So if you had four active bullets your array would look like:
0 B
1 B
2 B
3 B
4 null
...
99 null
The benefit is that the array would always be allocated and therefore you are not dealing with the overhead of a more complex data structure. This is actually fairly similar to how strings work, since they are actually char[] with a null terminator.
Might be worth a shot. One downside, you'll have to do some manual manipulation when removing a bullet, probably move everything after that bullet up a slot. But you are just moving pointers at that point, so I don't think it would have a high penalty like allocating memory or a GC.
You are correct in assuming that by keeping the unused Bullets in a Stack prevents them from being Garbage Collected.
As for the cause of the Lag, have you tried any profiling tools? Just to find where the problem is.
Your stack based solution is pretty close to a class I wrote to generically do this sort of resource pooling:
http://codecube.net/2010/01/xna-resource-pool/
You mentioned that this makes the problem mostly go away, but it still crops up here and there. What's happening is that with this stack/queue based method of pooling, the system will reach a point of stability once you are no longer requesting more new objects than the pool can supply. But if the requests go higher than your previous max # of requested items, it will cause you to have to create a new instance to service the request (thus invoking GC from time to time).
One way you can side-step this is to go through and pre-allocate as many instances as you think you might need at the peak. That way, you won't have any new allocations (at least from the pooled objects), and the GC won't be triggered :-)
List actually has a built in capacity to prevent allocation for every add/remove. Once you exceed the capacity, it adds more ( I think I doubles every time ). The problem may be more on remove than add. Add will just drop on at the first open spot which is tracked by size. To remove, the list has to be condensed to fill in the now empty slot. If you are always removing for the front of the list, then every element needs to slide down.
A Stack still uses an array as its internal storage mechanism. So you are still bound by the add/remove properties of an array.
To make the array work, you need to create all the bullets up from with an Active property for each. When you need a new one, filled the Active flag to true and set all of the new bullets properties. Once complete, flip the Active flag false.
If you wanted to try to eliminate the need to iterate the list ( which could be very large depending on what you are going to allow ) for each repaint, you could try to implement a double linked list within the array. When a new bullet is needed, asked the array for the first available free entry. Go to the last active bullet ( a variable ) and add the new bullet array position into its next active bullet property. When it is time to remove it, go to the previous bullet and change its active bullet property to the removed next active.
//I am using public fields for demonstration. You will want to make them properties
public class Bullet {
public bool Active;
public int thisPosition;
public int PrevBullet = -1;
public int NextBullet = -1;
public List<Bullet> list;
public void Activate(Bullet lastBullet) {
this.Active = true;
this.PrevBullet = lastBullet.thisPosition;
list[this.PrevBullet].NextBullet = this.thisPosition;
}
public void Deactivate() {
this.Active = false;
list[PrevBullet].NextBullet = this.NextBullet;
list[NextBullet].PrevBullet= this.PrevBullet;
}
}
That way, you have a prebuilt array with all the needed bullets but the paint only hits the bullets that are active regardless of their position within the array. You just need to maintain a link to the first active bullet to start the paint and the last active bullet to know where list starts anew.
Now you are just worried about the memory to hold the entire list instead of when the GC is going to clean up.