- Home /
Unity Physics frame rate. void FixedUpdate
I have a problem with Physics frame rate. Sometimes spheres don't detect collision, sometimes they do. Its not just little things, its a big problem, I'm trying to use vr controllers and my sword just goes through the collision, if I swing bit fast.
I don't know how to put the codes and scripts that don't even use void Update
into void FixedUpdate
I really need an advice here or maybe try and put this script, into FixedUpdate, so I can repeat it on other scripts.{
public Transform brokenObject;
public float magnitudeCol, radius, power, upwards;
void OnCollisionEnter(Collision collision)
{
if(collision.relativeVelocity.magnitude > magnitudeCol)
{
Destroy (gameObject);
Instantiate(brokenObject, transform.position, transform.rotation);
brokenObject.localScale = transform.localScale;
Vector3 explosionPos = transform.position;
Collider[] colliders = Physics.OverlapSphere (explosionPos, radius);
foreach (Collider hit in colliders)
{
if (hit.GetComponent<Rigidbody>())
{
hit.GetComponent<Rigidbody>().AddExplosionForce(power*collision.relativeVelocity.magnitude, explosionPos, radius,upwards);
}
Thank you.
As a general rule, if you are experiencing an issue where collision of fast-moving objects is not being detected, it may be necessary to get creative to solve the problem.
$$anonymous$$eep in $$anonymous$$d that few things are automatically interpolated in the world of computers. Everything happens in discrete steps.
As an object's position is changed, the path you'd intuitively think it traversed is actually not considered at all. If an object moves quickly enough, the gap between its new position and its previous position may be large enough to "miss" a collision altogether.
This is why, for instance, bullets tend to be handled by long raycasts. The length of the ray should be deter$$anonymous$$ed by how far the bullet moved from one frame to the next.
If indeed this is the issue affecting your project, we can discuss options. Can you confirm or deny that this is what's happening? For instance, by testing using very slow, deliberate movements? If it works for slow movements but not fast movements, this is likely the issue.
That is definitely a case. When I was testing particle effects, on my bullet collision, I had to limit the force or majority of particle effects wouldn't be activated, there for bullets had missed collisions. I made sword work but I'm not happy with this. https://www.youtube.com/watch?v=pX3xQg1puRE
Answer by AlwaysSunny · Dec 28, 2016 at 03:38 AM
So, if you want to discuss options for improving collision detection for fast-moving objects, we can get into that.
Before we get creative, you can try changing the sword's rigidbody interpolation mode. Here's a fairly through explanation of each mode - just try each one and see if a different mode will solve the issue. (Fairly unlikely, but it's worth a try.)
Assuming there's still a problem, we've got several options. What I recommend is basically the same solution described for bullets in my comment above: Using linecasts to "fill in the gap" created by moving the object too far in a given frame. It's more complicated because it's a sword, but it shouldn't be too bad.
Note: What I am proposing is the least-sophisticated way to implement this idea. If you wanted to get fancy, you could make the sword's traversal in a given frame into a proper arc by using multiple sets of linecasts. Only do this if you really need the extra fidelity, because it will quickly become harder to manage / understand.
So, what we want to do is address the gap created by moving the object too quickly. By drawing linecasts between the sword's old position (last frame) and new position (current frame) we can see whether those lines intersect an object.
You'll probably want to do this for several points along the length of the sword. You can achieve this with pure math if you feel comfortable doing so, but it may be easier to understand if you use some dummy objects.
Create some empty game objects along the blade of the sword. One at the hilt, one at the tip, and three or four in between. Expose and populate a collection of these objects in your script:
public Transform[] blade_helpers;
We also want a record of their previous position. Let's use a collection that is the same size as the one above, where each entry corresponds to one of the objects:
private Vector3[] blade_history = new Vector3[ blade_helpers.Length ];
In FixedUpdate(), create a linecast between each helper object's old position and its new position. After performing these linecasts, update the history to reflect the current position of each helper object.
Note that you'll get weird behavior unless you populate the history with the current positions in the first frame, but that's easy to fix. Let's move on instead:
If any of your linecasts hit something, you'll know you've hit something with your sword. You'll need to adapt your current logic which responds to collisions to also respond in a similar way to these linecast results.
We can get into that too if need be. Let me know if this requires more explanation.
Note: What we're doing here is creating a kind of simple "trajectory" test along the length of the blade. We'll get information about the tip and hilt and all points in between separately. Another method, perhaps just as good, would involve using linecasts that represent the sword blade itself. You'd create a "fan" of linecasts to fill in the gap, whereas what I'm suggesting is more like a "trail". Either way, the idea is to fill in the gap created by fast motion.
Best,
I have to learn more about raycast before be able to do that. I'll watch few videos next couple of days, I'll get back to you, Thanks.
Answer by AurimasBlazulionis · Dec 28, 2016 at 12:42 PM
So, I guess the sword is a rigidbody. Just set it's collision detection to continuous or continuous dynamic and you should be good to go.
It is never a good idea to do this but for one object it should not hurt the performance at all.
As I mentioned briefly, @TheDiamondPlay is right, you should definitely try this before you attempt my long and complex workaround. There's a chance it will satisfy your expectations.
video which i showed you does have continuous dynamic on it https://www.youtube.com/watch?v=pX3xQg1puRE
Answer by Socapex · Dec 28, 2016 at 06:39 PM
Once you've tested different collision modes (as @TheDiamondPlay suggested), you can do the following to debug.
To make sure you are never moving anything in an update, go to Project Settings > Time
and change Fixed Timestep
to something ridiculously big like 1 or 2. If you are affecting position from somewhere other than FixedUpdate, the object will "jitter" or teleport itself. If everything is smooth than you are fine.
You can try lowering the Fixed Timestep to 0.016 (60 Hz), though that will consume more CPU.
He is moving his sword using his own hands in VR. I do not think it will be smooth.
Smooth as in interpolating. It will be if everything is called from FixedUpdate, since unity is interpolating movement every x seconds. Try it on a project.
Your answer
Follow this Question
Related Questions
Physics behaviour changing with framerate - Is FixedUpdate() actually working properly? 3 Answers
How to smooth physics without interpolation 0 Answers
Not registering input when checking input in Update and using input in FixedUpdate 1 Answer
Raycast and Physics(Ragdolls): Update() or FixedUpdate()? 1 Answer
Framerate independent physics (FixedTimestep, FixedDeltaTime) 1 Answer