Posts: 9
Threads: 2
Joined: Jun 2019
Reputation:
0
Hello,
I discovered some performance issues I did not notice until more players joined but every rope generated takes about 15 fps away which is quite a lot considering I need about 20 ropes to be able to render at the same time. Are my expectations just way to high or is there something I did wrong? I can literally disable the rope and my fps instantly jumps at least 15.
The way my ropes work is they are constantly moving which is of course more demanding then static ropes I assume. Basically there is the players hand and then there is an animal that is on a lease, so the rope constantly need updating.
Help is appreciated
Posts: 6,323
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
20-08-2019, 05:46 PM
(This post was last modified: 20-08-2019, 05:48 PM by josemendez.)
(20-08-2019, 05:07 PM)Smurfj3 Wrote: Hello,
I discovered some performance issues I did not notice until more players joined but every rope generated takes about 15 fps away which is quite a lot considering I need about 20 ropes to be able to render at the same time. Are my expectations just way to high or is there something I did wrong? I can literally disable the rope and my fps instantly jumps at least 15.
The way my ropes work is they are constantly moving which is of course more demanding then static ropes I assume. Basically there is the players hand and then there is an animal that is on a lease, so the rope constantly need updating.
Help is appreciated
Hi there,
One word: profile
15 fps per rope is a lot, but without profiling, figuring out the cause is close to impossible. Maybe you have too many iterations per step, or maybe your rope rendering is taking up too much time, or maybe your timestep is too low.
Maybe you're hitting the "well of despair/death spiral", or whatever you call it. - If you don't know what this is, it is a critical topic when dealing with physics. Some resources: https://johnaustin.io/articles/2019/fix-...y-timestep
https://docs.nvidia.com/gameworks/conten...of-despair
https://www.youtube.com/watch?v=sUVqa-72-Ms
There's no magic improve performance button anywhere, so profiling is the only way to tell what the problem is, which is the first step towards fine-tuning performance.
Also, static ropes are just as costly as moving ones. Both need to be simulated, as long as they're visible to a camera.
Posts: 9
Threads: 2
Joined: Jun 2019
Reputation:
0
(20-08-2019, 05:46 PM)josemendez Wrote: Hi there,
One word: profile
15 fps per rope is a lot, but without profiling, figuring out the cause is close to impossible. Maybe you have too many iterations per step, or maybe your rope rendering is taking up too much time, or maybe your timestep is too low.
Maybe you're hitting the "well of despair/death spiral", or whatever you call it. - If you don't know what this is, it is a critical topic when dealing with physics. Some resources: https://johnaustin.io/articles/2019/fix-...y-timestep
https://docs.nvidia.com/gameworks/conten...of-despair
https://www.youtube.com/watch?v=sUVqa-72-Ms
There's no magic improve performance button anywhere, so profiling is the only way to tell what the problem is, which is the first step towards fine-tuning performance.
Also, static ropes are just as costly as moving ones. Both need to be simulated, as long as they're visible to a camera.
Hello thanks for the quick reply, yes I am aware that profiling is the way to go but that's the reason for my post, I should have been more clear though. I can see that ObiSolver.FixedUpdate() and ObiSolver.LateUpdate() are both using a lot and causing huge fps drops. I made some screenshots from 2 different frames that show the exact function that is causing the issue.
I did not know about the "well of despair/death spiral" thing, maybe thats because I am still somewhat new to unity.
Thanks a lot,
Jeffrey
Posts: 6,323
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
20-08-2019, 07:25 PM
(This post was last modified: 20-08-2019, 07:32 PM by josemendez.)
(20-08-2019, 06:53 PM)Smurfj3 Wrote: Hello thanks for the quick reply, yes I am aware that profiling is the way to go but that's the reason for my post, I should have been more clear though. I can see that ObiSolver.FixedUpdate() and ObiSolver.LateUpdate() are both using a lot and causing huge fps drops. I made some screenshots from 2 different frames that show the exact function that is causing the issue.
I did not know about the "well of despair/death spiral" thing, maybe thats because I am still somewhat new to unity.
Thanks a lot,
Jeffrey
From the profiler pics, I can tell two things:
- Rope rendering is taking up too much time. If you're using the extruded rope renderer, try using a less dense rope section asset, maybe 4 or 5 segments are enough instead of the default 8. You can also use the LineRenderer instead, as it is much cheaper than the extruded one. See: http://obi.virtualmethodstudio.com/tutor...modes.html
- Your scene has a bad case of death spiralling. FixedUpdate() is being called 5 times per frame (see the "calls" column in the profiler), ideally it would be called only once. Good news is things can run at least 5 times faster than they currently are. Try lowering Unity's max fixed timestep, to a small multiple of the fixed timestep (if fixed timestep is set to 0.02, use a max of 0.04 for instance). You can find these settings in the Time Manager: https://docs.unity3d.com/Manual/class-TimeManager.html
Death spiralling can take place in any fixed-timestep engine, not just Unity. So if you're making games where physics play an important role, it is crucial you understand what it is and why it happens, as it can very easily kill your performance.
Posts: 9
Threads: 2
Joined: Jun 2019
Reputation:
0
20-08-2019, 08:09 PM
(This post was last modified: 20-08-2019, 08:11 PM by Smurfj3.)
(20-08-2019, 07:25 PM)josemendez Wrote: From the profiler pics, I can tell two things:
- Rope rendering is taking up too much time. If you're using the extruded rope renderer, try using a less dense rope section asset, maybe 4 or 5 segments are enough instead of the default 8. You can also use the LineRenderer instead, as it is much cheaper than the extruded one. See: http://obi.virtualmethodstudio.com/tutor...modes.html
- Your scene has a bad case of death spiralling. FixedUpdate() is being called 5 times per frame (see the "calls" column in the profiler), ideally it would be called only once. Good news is things can run at least 5 times faster than they currently are. Try lowering Unity's max fixed timestep, to a small multiple of the fixed timestep (if fixed timestep is set to 0.02, use a max of 0.04 for instance). You can find these settings in the Time Manager: https://docs.unity3d.com/Manual/class-TimeManager.html
Death spiralling can take place in any fixed-timestep engine, not just Unity. So if you're making games where physics play an important role, it is crucial you understand what it is and why it happens, as it can very easily kill your performance.
Alright so I have tried using 4 segments and weird enough it has 0 impact on fps, it literally didn't do anything not noticeable with 1 rope anyway. I do thank you for pointing out the death spiralling thing, I have been reading up on it and that was quite interesting although it didn't change much performance wise for my game, apparently the right time was 0.03 for me. So how would I go about implementing the rope using the linerenderer because wouldn't that mean that the rope is just going to be completely straight? Also my rope is always kind of flat or more or less like an oval shape, is this intended and maybe it has anything to do with my current issues? Maybe the code that generates my rope is just bad?
This is the code that I use to generate ropes:
Code: public IEnumerator MakeRope(Transform fromtrans, Transform totrans, float ropeLength)
{
GameObject ropeObject = new GameObject("HitchRope", typeof(ObiSolver),
typeof(ObiRope),
typeof(ObiCurve),
typeof(ObiRopeExtrudedRenderer),
typeof(ObiRopeCursor));
ropeObject.transform.position = fromtrans.position;
rope = ropeObject.GetComponent<ObiRope>();
path = ropeObject.GetComponent<ObiCurve>();
solver = ropeObject.GetComponent<ObiSolver>();
ropeextruder = ropeObject.GetComponent<ObiRopeExtrudedRenderer>();
cursor = ropeObject.GetComponent<ObiRopeCursor>();
render = ropeObject.GetComponent<MeshRenderer>();
rope.Solver = solver;
rope.ropePath = path;
ropeextruder.section = Resources.Load("DefaultRopeSection") as ObiRopeSection;
ropeextruder.section.CirclePreset(4);
render.material = RopeMaterial;
ropeextruder.uvScale = new Vector2(1, 10);
rope.thickness = 0.03f;
yield return rope.StartCoroutine(rope.GeneratePhysicRepresentationForMesh());
rope.AddToSolver(null);
GameObject HandleObject01 = new GameObject("Obi Handle01", typeof(ObiParticleHandle));
HandleObject01.transform.parent = fromtrans;
GameObject HandleObject02 = new GameObject("Obi Handle02", typeof(ObiParticleHandle));
HandleObject02.transform.parent = totrans;
ObiParticleHandle handle01 = HandleObject01.GetComponent<ObiParticleHandle>();
handle01.Actor = rope;
handle01.AddParticle(0, fromtrans.position, Quaternion.identity, rope.invMasses[0], 1);
handle01.AddParticle(1, fromtrans.position, Quaternion.identity, rope.invMasses[1],1);
ObiParticleHandle handle02 = HandleObject02.GetComponent<ObiParticleHandle>();
handle02.Actor = rope;
int index = rope.UsedParticles - 1;
Vector3 hitchpoint = new Vector3(totrans.GetComponent<Collider>().bounds.center.x,
totrans.GetComponent<Collider>().bounds.center.y + (totrans.GetComponent<Collider>().bounds.size.y / 2),
totrans.GetComponent<Collider>().bounds.center.z);
handle02.AddParticle(index, hitchpoint, Quaternion.identity, rope.invMasses[index], 1);
handle02.AddParticle(index - 1, hitchpoint, Quaternion.identity, rope.invMasses[index - 1], 1);
rope.AddToSolver(null);
cursor.normalizedCoord = 0.5f;
cursor.direction = true;
cursor.ChangeLength(ropeLength);
}
Posts: 6,323
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
21-08-2019, 04:28 PM
(This post was last modified: 21-08-2019, 04:29 PM by josemendez.)
(20-08-2019, 08:09 PM)Smurfj3 Wrote: Alright so I have tried using 4 segments and weird enough it has 0 impact on fps, it literally didn't do anything not noticeable with 1 rope anyway. I do thank you for pointing out the death spiralling thing, I have been reading up on it and that was quite interesting although it didn't change much performance wise for my game, apparently the right time was 0.03 for me. So how would I go about implementing the rope using the linerenderer because wouldn't that mean that the rope is just going to be completely straight? Also my rope is always kind of flat or more or less like an oval shape, is this intended and maybe it has anything to do with my current issues? Maybe the code that generates my rope is just bad?
This is the code that I use to generate ropes:
Code: public IEnumerator MakeRope(Transform fromtrans, Transform totrans, float ropeLength)
{
GameObject ropeObject = new GameObject("HitchRope", typeof(ObiSolver),
typeof(ObiRope),
typeof(ObiCurve),
typeof(ObiRopeExtrudedRenderer),
typeof(ObiRopeCursor));
ropeObject.transform.position = fromtrans.position;
rope = ropeObject.GetComponent<ObiRope>();
path = ropeObject.GetComponent<ObiCurve>();
solver = ropeObject.GetComponent<ObiSolver>();
ropeextruder = ropeObject.GetComponent<ObiRopeExtrudedRenderer>();
cursor = ropeObject.GetComponent<ObiRopeCursor>();
render = ropeObject.GetComponent<MeshRenderer>();
rope.Solver = solver;
rope.ropePath = path;
ropeextruder.section = Resources.Load("DefaultRopeSection") as ObiRopeSection;
ropeextruder.section.CirclePreset(4);
render.material = RopeMaterial;
ropeextruder.uvScale = new Vector2(1, 10);
rope.thickness = 0.03f;
yield return rope.StartCoroutine(rope.GeneratePhysicRepresentationForMesh());
rope.AddToSolver(null);
GameObject HandleObject01 = new GameObject("Obi Handle01", typeof(ObiParticleHandle));
HandleObject01.transform.parent = fromtrans;
GameObject HandleObject02 = new GameObject("Obi Handle02", typeof(ObiParticleHandle));
HandleObject02.transform.parent = totrans;
ObiParticleHandle handle01 = HandleObject01.GetComponent<ObiParticleHandle>();
handle01.Actor = rope;
handle01.AddParticle(0, fromtrans.position, Quaternion.identity, rope.invMasses[0], 1);
handle01.AddParticle(1, fromtrans.position, Quaternion.identity, rope.invMasses[1],1);
ObiParticleHandle handle02 = HandleObject02.GetComponent<ObiParticleHandle>();
handle02.Actor = rope;
int index = rope.UsedParticles - 1;
Vector3 hitchpoint = new Vector3(totrans.GetComponent<Collider>().bounds.center.x,
totrans.GetComponent<Collider>().bounds.center.y + (totrans.GetComponent<Collider>().bounds.size.y / 2),
totrans.GetComponent<Collider>().bounds.center.z);
handle02.AddParticle(index, hitchpoint, Quaternion.identity, rope.invMasses[index], 1);
handle02.AddParticle(index - 1, hitchpoint, Quaternion.identity, rope.invMasses[index - 1], 1);
rope.AddToSolver(null);
cursor.normalizedCoord = 0.5f;
cursor.direction = true;
cursor.ChangeLength(ropeLength);
}
Hi there,
I don't see anything wrong with your code at first sight.
Using a ObiRopeLineRenderer won't make your rope straight, it works just like Unity's line renderer: it draws a camera-facing triangle strip, which is quite cheap compared to a full extruded mesh.
Also, always profile the exact same scenario, ie. the one that exhibits performance issues. Using a 4 segment section instead of a 8 segment one will have a negligible impact on just one rope, but the benefit will add up when you have several ropes.
Posts: 9
Threads: 2
Joined: Jun 2019
Reputation:
0
(21-08-2019, 04:28 PM)josemendez Wrote: Hi there,
I don't see anything wrong with your code at first sight.
Using a ObiRopeLineRenderer won't make your rope straight, it works just like Unity's line renderer: it draws a camera-facing triangle strip, which is quite cheap compared to a full extruded mesh.
Also, always profile the exact same scenario, ie. the one that exhibits performance issues. Using a 4 segment section instead of a 8 segment one will have a negligible impact on just one rope, but the benefit will add up when you have several ropes.
Okay so the problem just got a whole lot weirder. Even using ObiRopeLineRenderer which btw doesn't look very good, the fps still drops the same amount. Is there anything else you can think of that could cause this to happen? I will tomorrow see what happens if I just reimport obirope and do it all from scratch. Thanks for your help so far I am sorry for being such a weird case
Posts: 6,323
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
23-08-2019, 07:22 AM
(This post was last modified: 23-08-2019, 07:23 AM by josemendez.)
(22-08-2019, 08:59 PM)Smurfj3 Wrote: Okay so the problem just got a whole lot weirder. Even using ObiRopeLineRenderer which btw doesn't look very good, the fps still drops the same amount. Is there anything else you can think of that could cause this to happen? I will tomorrow see what happens if I just reimport obirope and do it all from scratch. Thanks for your help so far I am sorry for being such a weird case
When profiling, see if there's any difference in the amount of ms taken by rendering. Without profiling myself, I cannot think of anything more that could cause this.
The line renderer can look really good, depending on how you shade it. There's a material included called "LineRope" that uses a very simple normal map to improve lighting. Using it appropiately can make the line renderer indistinguishable from the extruded renderer most of the time, specially for thin ropes.
Posts: 1
Threads: 0
Joined: Sep 2019
Reputation:
0
I found myself here due to performance issues too (except obi solver was taking between 50-60fps off my fps per rope...). I imported into a new project and it seems fine though. The big difference between the projects is the one that is suffering is using the HD render pipeline. Testing the sample scenes in both projects sees about 100fps difference in play mode.
I have no idea why this would be but just thought I would offer this piece of information in case it is helpful. As it stands I'll either need to choose between switching back to a different rendering pipeline (far from ideal) or not use Obi. Neither great options unfortunately since Obi seems really nice.
Posts: 6,323
Threads: 24
Joined: Jun 2017
Reputation:
400
Obi Owner:
10-09-2019, 08:36 AM
(This post was last modified: 10-09-2019, 08:41 AM by josemendez.)
(10-09-2019, 07:59 AM)Mancomb Wrote: I found myself here due to performance issues too (except obi solver was taking between 50-60fps off my fps per rope...). I imported into a new project and it seems fine though. The big difference between the projects is the one that is suffering is using the HD render pipeline. Testing the sample scenes in both projects sees about 100fps difference in play mode.
I have no idea why this would be but just thought I would offer this piece of information in case it is helpful. As it stands I'll either need to choose between switching back to a different rendering pipeline (far from ideal) or not use Obi. Neither great options unfortunately since Obi seems really nice.
I'm 99.99% positive the culprit is not the rendering pipeline. Take a look at your profiler (regular profiling, not deep profile), see how many times is FixedUpdate() being called per frame. It should be just once or twice. More calls per frame means you've found the cause.
Chances are your project is heavy on other areas besides physics, or has different Time settings, leaving little time per frame for simulation and causing it to plummet into the "well of despair" or "death spiral" (If you don't know what I'm talking about, read up on it as it is fixed-timestep 101). Take a look at your Time settings in Unity's time manager. These settings are critical for physics. Start with a fixed timestep of 0.02 and a max fixed timestep of 0.04, then work from there.
This is just a wild guess, but i've seen so many projects struggling due to death spiraling (usually a trivial fix) that I almost always point people in that direction when they complain about performance.
|