- Home /
Intermittent detection of input in FixedUpdate()
Hi, I have this code attached to a rigidbody, pretty simple stuff ... or so I thought:
using UnityEngine;
using System.Collections;
public class PlayerInput : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void FixedUpdate () {
if ( Input.GetMouseButtonDown( 0 ) )
{
Debug.Log("Added force");
rigidbody.AddRelativeForce (Vector3.right * 500);
}
}
}
The problem is that it's not always detecting the input - it does sometimes but not others...the kind of behaviour you'd expect if the input detection wasn't based in Update(). But I assume as the code is physics related FixedUpdate() is the place to put it..? Isn't FixedUpdate() also called every frame? Thanks
Just change FixedUpdate to Update. If FixedUpdate was called every frame, it wouldn't be fixed. It's O$$anonymous$$ to do this in Update since it's just done once per button press, and not every physics frame.
Answer by hathol · May 23, 2012 at 09:19 AM
Fixed Update is called at a fixed time rate and completely independent from your frame time. Dependant on your frame rate, it can be called multiple times per frame (if your timestep is very small and/or your framerate very low) or only once every couple of frames (the normal case, where you have a medium to high timestep and a high framerate).
Your problem here is, that GetMouseButtonDown (unlike GetMouseButton) is only fired exactly once in the frame (not physics timestep -> FixedUpdate) it occurred, so you will likely miss it during FixedUpdate. Try catching and storing the Input during normal Update() and then act upon the cached values during your FixedUpdate. Something like this might work:
bool HasMouseBeenPressed = false;
void Update()
{
if(Input.GetMouseButtonDown(0))
HasMouseBeenPressed = true;
}
void FixedUpdate()
{
if(HasMouseBeenPressed)
{
// do stuff
HasMouseBeenPressed = false;
}
}
Though I'm sure there are more clever ways to handle your input than that. In case you're interested, here's a better explanation of the relation between Update and FixedUpdate http://answers.unity3d.com/questions/10993/whats-the-difference-between-update-and-fixedupdat.html
Ah right I understand - thankyou so much for taking the time to explain that so clearly.
NOTE: this problem affects "transition detecting" functions like Input.Get...Down and Input.Get...Up (Input.Get$$anonymous$$eyDown, Input.GetButtonUp etc.) You can read "state detecting" functions like Input.GetButton, Input.Get$$anonymous$$ey etc. without noticeable difference (if any). I'm not sure about Input.GetAxis("$$anonymous$$ouse ...") readings.
$$anonymous$$y issue is that my "//do stuff" happens two times every key press. I tried this method but it still happens twice. I realize that my issue is different the the original question but I think it could be related. You solution looks like it should work do you have any other observations that could help?
Note: Testing, I printed //do stuff to the debug log and it always shows twice.
I checked and it is only attached once. :( $$anonymous$$y solution for now is pass in half the value (Score/points). But I do find it odd.
Answer by Marrt · Jul 29, 2012 at 06:07 PM
I use a kind of Input Converter to gather Network Input and even KeyUps/downs etc. based on simple check if key is pressed or not:
//Trigger: converts weapontrigger States to keyUp/KeyDown for fixedUpdate or coroutines
private WeaponTrigger wt;
private bool triggerWasPulled = false;
private bool triggerWasReleased = true;
private bool triggerDown = false;
private bool triggerUp = false;
private int triggerIndex = 0;
private bool trigger; //trigger 1-4 assignable
public void LinkTrigger(int index){//called by Loadout
triggerIndex = index;
}
void SetWt(){ //do in start
wt = transform.parent.GetComponent();
}
void TriggerCheck(){//do in Update
switch (triggerIndex){
case 0: trigger = wt.activation1; break;
case 1: trigger = wt.activation2; break;
case 2: trigger = wt.activation3; break;
case 3: trigger = wt.activation4; break;
case 4: trigger = wt.activation5; break;
case 5: trigger = wt.activation6; break;
case 6: trigger = wt.activation7; break;
case 7: trigger = wt.activation8; break;
//in WeaponTrigger Update:
//if (Input.GetKey(""+activationKey1)){activation1 = true;}else{activation1 = false;}
}
void KeyUpDownTransform(){//if keyup, keydown is needed
if(trigger &∓& triggerWasReleased) {triggerDown = true;}
if(!trigger && triggerWasPulled) {triggerUp = true;}
triggerWasPulled = trigger;
triggerWasReleased = !trigger;
}
void TriggerReset(){//if using keyup,down conversion reset on the end of update()
//resetTriggers
triggerDown = false;
triggerUp = false;
}
//Then Put the functions in the Right Frame-based Functions:
void Start () {
SetWt();
}
void Update () { //or LateUpdate or even FixedUpdate
TriggerCheck(); //on start of Update/Late/Fixed
KeyUpDownTransform(); //on start of Update/Late/Fixed
//Your KeyDepending Code
TriggerReset(); //on the end of Update/Late/Fixed
}
so you convert input based on its state of the last frame. however, things that you will still miss is if the user presses AND releases the key between 2 frames (mostly ~15ms) that also have happend between 2 fixed frames. this is nearly impossible as pressing a key for only 15ms alone is pretty hard to achieve
Your answer
Follow this Question
Related Questions
Determinism problems: Mathf, Unity.Random VS Math, System.Random 2 Answers
Rigidbody.AddForceAtPosition & functions 1 Answer
Why won't my door open? 1 Answer
detection raycast too late 2 Answers
W key is unresponsive with input 1 Answer