Simpler way to detect movement than checking each axis each tick?

I’m trying to create a generic method that checks each frame to see if the character is moving, and if they are, message an event that cancels out of anything the player was doing (using items, sitting down). I could check if (Input.GetAxis(“Horizontal”) != 0 &&Input.GetAxis(“Vertical”) != 0), but running that check while the player is moving and sending a message every time seems incredibly wasteful. One alternative would be to check every frame if both axes are zero, set some bool NotMoving to true, and only fire off an event if the player is moving and NotMoving=true, but that’s a lot of work to do every single frame for comparatively minimal functionality.

Please define “wasteful”. Does it solve your problem? If it does, go for it.

Bad advice.
There are many solutions most of the time. Some of them are better than others.

@Sendatsu_Yoshimitsu
Yes, you are right. Sending the message during every frame is wasteful. SendMessage is rather slow and using it even frame is something you should avoid.

Instead of sending whether the player is moving, just send whether the state changed.
If the player starts moving, you send a single “Moving” message. Once the player stopped moving, you send a single “Stopped” message.

That way your scripts have access to exactly the same amount of information, just with waaaaaay less redundancy.

1 Like

Yes, but premature optimization is the root of all evil. :wink: My point is that OP doesn’t seem to know if this is the best solution or not, and thus he/she should just make it work, first and foremost.

This particular shouldn’t be solved using message sending at all, IMO, but by simply setting a bool value (or preferably have a method which returns bool and does all the mumbo jumbo required to find out what’s going on.)

Also, the problem is a bit ambiguous. Should it be “is the character moving”, or should be “is the player trying to move the character”? Those are totally different; a character might for example slide or fall - thus be moving - without any input from the player. The former is usually checked by differentiating position over time, while the latter requires checking the input values from the player.

There’s not much you can do against checking every frame (unless its acceptable that there is a delay for abilities getting enabled/disabled)

But you certainly dont have to send a message every frame, as @TheSniperFan said.

I’d do something like this:

public bool isMoving {
    get {
         //Approximatly so were not making a float comparison to exactly 0
         return !Mathf.Approximatly(rigidbody.velocity.magnitude, 0f);

    }
}

void Update() {
    SetAbilities(!isMoving);
}

bool abilitiesEnabled = true;
void SetAbilities(bool enabled) {
       //Optimization bool. If our abilities are already disabled or enabled, we wont send redundant messages
       if (enabled == abilitiesEnabled) return;

       abilitiesEnabled = enabled;

       if (abilitiesEnabled) {
             //send enable message
       } else {
            //send disable message
       }

}

You’ll notice I check RigidBody for movement rather than Input. Input isn’t wrong, but if you want the abilties disabled if the character is sliding, falling or moving as a result of something that wasn’t necessarily a command, this code would take that into account.

And if youre not using physics to move your character, you could just track it’s position with another Vector3:

Vector3 lastPosition;
public bool isMoving {
    get {
         Vector3 delta = transform.position - lastPosition;

         return !Mathf.Approximatly(delta.velocity.magnitude, 0f);

    }
}


void Update() {
    SetAbilities(!isMoving);

    //ensure you do this after isMoving is used for the last time this frame. Could even do it in LateUpdate()
    lastPosition = transform.position;
}

There’s a huge difference between looking for a better solution and looking for the best solution. Sure, you shouldn’t loose yourself in micro-optimization, but this isn’t. You really should think something that fundamental through first. Otherwise you might find yourself in the situation where you need to optimize the code, and optimizing meaning rewriting massive parts of it.
If you have some algorithm and think to youself: “Boy, this sure looks inefficient as hell.”, rethink it. If you can’t come up with a better one within a reasonable amount of time, ask on the forums.

I don’t know. Yes, a simple boolean variable would be more efficient, but without knowing the OP code’s structure and what exactly he’s trying to accomplish, it’s impossible to tell which solution is better.
I assumed that the OP chose SendMessage for a reason and merely gave him a hint for optimizing its usage.

public static bool IsMoving {
    get;
    private set;
}

Something like this would probably be the most efficient way of accessing this information. However, it’s limited to only one entity. If you want multiple, you can’t have a static variable anymore, which is less efficient and leads to more code, since you need to manage all the references somewhere.

Right, but that’s one of the pitfalls, you let inexperienced developers fall into. It’s a learning experience. :wink:

1 Like
public static bool IsMoving {
    get;
    private set; // <- I did not know you could put access modifiers on getters/setters
}

@BenZed

You can in order to restrict access. This example makes it read-only from the outside. Immensely useful.

Yeah, normally I just do this:

bool _foo;

public bool foo {
    get {
        return _foo;
    }
}

void Main(){
       ///and then set like so:
      _foo = true;
}

But it’s way better to not have the storage field be accessed anywhere but by the property. THE MORE YOU KNOW indeed!

And old benchmark from eric showed that sendmessage is 400 times slower than having a reference to a gameobject and using getComponent().method();

1 Like

Ack, sorry for the delay between replies, life happened. :slight_smile:

To clarify, I’m trying to test for movement attempts, regardless of whether actual movement occurs: I basically want WSAD to be a fast, reliable way to cancel out of any menu and action if the player doesn’t feel like hunting down the cancel key.

I should also clarify, since I used “message” ambiguously, that I’m using an event, not sendmessage, both for performance reasons and because my world timescale is notified by an event the timer sends out, which biases me towards using events to accomplish anything that might need to act based on time.

I think using the bool for optimization will be very marginally faster, as there are enough circumstances where activities/usable items shouldn’t be accessible that I’ll want a reliable way to toggle it on and off, right now it’s about a 70/30 split in playtime between items enabled and items disabled.

Also, holy freaking crap, I had no clue you could make setters read only, that is incredibly useful.