Removing the timer may not always work for fast timers, as by the time the collision callback has been triggered, the timer may have expired and the callback event queued up ready to be called - at least if i recall correctly. A just as simple and more robust solution is to use a variable to track whether or not to renew the timer. E.g.
//Start walking forward
void StartWalking(float afAmount)
{
SetLocalVarFloat("WalkAmount",afAmount);
cbWalkTimer("WalkTimer");
}
//Stop walking forward
void StopWalking()
{
SetLocalVarFloat("WalkAmount",0);
}
//Timestep - this constant is the delay between timer calls
const float TIMESTEP = 1.0f / 60.0f;
void cbWalkTimer(string &in asTimer)
{
//Get step amount -> if 0 then walking has stopped
float walkamt = GetLocalVarFloat("WalkAmount");
if(walkamt == 0) return;
//Else step forward and add timer so that you can walk forward again next frame
MovePlayerForward(walkamt);
AddTimer(asTimer,TIMESTEP,"cbWalkTimer");
}
In the above code I have encapsulated the behaviour into a "StartWalking" and "StopWalking" function - which you can just call (the float parameter to start walking is the same as the one you would put into MovePlayerForward).
Apologies if there any syntax errors, i am unable to test run the code from this computer.