Double movement on key down (Update/frame problem?)

I am creating a tile-based 3D FPS, similar to Legend of Grimrock. So I have the player move 1 unit (=1 tile) forward etc. every time the wasd keys are pressed down.

It behaves nicely when playing it in Unity, but when I play the compiled game it performs the movement function twice. I suspect it has something to do with the place where I put the code sections (Java).

In my Update part, I register for KeyDown which sets the movement direction, then declare movement variables and then comes a complicated “if…” statement that checks which movement direction is active, then checks if there’s anything blocking via raycast and then calls the actual transform.position function which is declared at the end of the code. Is there the correct use of the Update part of the code?

A related problem is that if I use onKey instead of onKeyDown, I can keep the key pressed down and it continues to move forward like it should but if I only press it once it performs two moves as well, even in in-engine play.

So my questions are:

  1. Why does the game perform one movement step when testing in the engine, but two in the compiled version?

  2. Why does onKey perform two movement steps if the key is only tapped quickly, even in-engine?


EDIT :

I was hoping to avoid it as it's all very primitive, clunky and excessively un-optimized, but at least it basically works as it should (in the editor), so here it goes...

(It was pretty much the first code I created, based on the script of another user. In the days since I learned a lot and would probably write it far more efficient, but for now I'll just go with it :) )

    var MakeMove : int = 0;
    var IsMoving : boolean = false;
    var Facing : int = 2;
    var WalkSpeed : float = 7.0;
    var TurnSpeed : float = 7.0;
    var GridSize : float = 1.0;
    var StartPosition : Vector3;
    var EndPosition : Vector3;
    var Inputer = Vector3.zero;
    var t : float;

    function OnGUI() {
            if (Input.GetKeyDown(KeyCode.W))
                MakeMove = 1;
    }

function Update() {

    var localOffset = transform.position + transform.up * 0.5;
    var hitCollision : RaycastHit;

        //move forward        
        if (MakeMove == 1 && !IsMoving)

       {            
            if (Physics.Raycast (localOffset, transform.forward, hitCollision, 1.1)) 
             {
              print(hitCollision.collider); //oh yeah, I am hitting stuff such as, UnityEngine.MeshCollider
               Debug.DrawLine (transform.position, hitCollision.point);//I can also see that the rays work, awesome.
              if (hitCollision.collider.gameObject.CompareTag("walls-blocks"))
              {
                  print("front blocked");
                 }

             }
             else {GoForward();}

        }  

function GoForward() {
        MakeMove = 0;
        IsMoving = true;

        StartPosition = transform.position;

        if (Facing == 0)
            EndPosition = transform.position - Vector3(0.0, 0.0, GridSize);

        if (Facing == 1)
            EndPosition = transform.position - Vector3(GridSize, 0.0, 0.0);

        if (Facing == 2)
            EndPosition = transform.position - Vector3(0.0, 0.0, -GridSize);

        if (Facing == 3)
            EndPosition = transform.position - Vector3(-GridSize, 0.0, 0.0);

        t = 0.0;

        while (t < 1.0) {
        t += Time.deltaTime * (WalkSpeed/GridSize);
        transform.position = Vector3.Lerp(StartPosition, EndPosition, t);
        yield;
        }

        IsMoving = false;

    }

can we see the code you're using?

–

Code. Post please.

–

Comments should be posted as comments , not answers. Post comments by clicking the [add new comment] button, a window then open for you to type in. Answer fields are for answers only, as this is a knowledge base. Here at Unity Answers, Answer means Solution, not Response. Please watch : http://video.unity3d.com/video/7720450/tutorials-using-unity-answers I will convert this one this time, but now you are aware and will use the correct response procedure. http://answers.unity3d.com/page/newuser.html

–

Comments should be posted as comments , not answers. If you have more information you need to add, simply edit your question. Post comments by clicking the [add new comment] button, a window then open for you to type in. Answer fields are for answers only, as this is a knowledge base. Here at Unity Answers, Answer means Solution, not Response. Please watch : http://video.unity3d.com/video/7720450/tutorials-using-unity-answers I will convert this one this time, but now you are aware and will use the correct response procedure. http://answers.unity3d.com/page/newuser.html

–

@MrSteve1 : Please don't post comments as answers. Post comments by clicking the [add new comment] button, a window then open for you to type in. Answer fields are for answers only, as this is a knowledge base. Here at Unity Answers, Answer means Solution, not Response. Please watch : http://video.unity3d.com/video/7720450/tutorials-using-unity-answers I have converted this to a comment for you , but now you know. Please read : http://answers.unity3d.com/page/newuser.html

–

1 Answer

1

You should be checking input only in the Update loop, not in the OnGui loop. The calling rate of OnGui depends on FPS while Update is dependent upon the game logic rate.

Wow, that fixed it! Thank you so much! The OnGUI function was an artifact from the original code form the other user, he didn't call movement by keys but by buttons on the hut, so I just changed that to keyboard commands and left everything else in place. Now I know how to do it. Strangely enough, it doesn't fix the secondary issue (two steps when onKey is used instead of onKeyDown), but it's not that important at the moment.

–