- Home /
How do you calculate DeltaX and DeltaZ for a character?
Hey everyone, first time posting a question here, I'll try to be as clear as possible.
I have a character system that uses transform.translate to mode in the X and Z directions, but physics for the Y direction (jumping). The reason for this is I don't want any momentum for the character when they stop moving, and I have coded in a custom initial speed up system that I don't want to rely on unity's physics for accuracy.
Obviously, when the character jumps, they should continue moving at the same speed and direction they were going (not necessarily vector3.forward).
To do this, I tried to code in a DeltaX and DeltaZ function, that updates every-other frame:
if(abovegr == false && jumping == false && startedjump == false)
{
movex = (transform.position.x - delx)/Time.deltaTime;
movez = (transform.position.z - delz)/Time.deltaTime;
jumptimer = 60;
nextx--;
if(nextx <= 0)
{
delx = transform.position.x;
delz = transform.position.z;
nextx = 1;
}
}
Then when the character is jumping, the following X and Z translations are used:
if((abovegr == true || jumping == true) && gliding == false)
{
transform.Translate(Vector3(movex*Time.deltaTime,0,movez*Time.deltaTime),Space.World);
}
(There is a bit more code that stops the character from continuing to attempt to fly in a direction after coming into contact with an object mid air, but my problem doesn't stem from the other parts)
This tends to work most of the time, but every so often, the character either doesn't move at all, or doubles the speed. I assume it is because there are framerate changes that affect the deltaX and deltaZ between multiple frames. (I tried Time.smoothDeltaTime, but it didn't seem to have any effect)
Is there a better way to implement a DeltaX and Z system? I'd like not to modify it too much since the system works fairly well as is, but if there is a different way to approach other than having to use:
nextx--;
if(nextx <= 0)
{
delx = transform.position.x;
delz = transform.position.z;
nextx = 1;
}
If I'm reading your question correctly, the behavior you want is what you get from the example script for CharacterController.$$anonymous$$ove(). It might be something to study for logic. It calculates its own gravity (no Rigidbody necessary). It uses CharacterController.$$anonymous$$ove() to move, but there is no logic difference between that and Transform.Translate().
Answer by whydoidoit · Mar 16, 2013 at 08:55 PM
I would imagine what you actually want to do is move the character by transform.forward - or if there is any danger of that containing a Y component then:
var forwardVector = new Vector3(transform.forward.x, 0, transform.forward.z);
Then you just want to do:
transform.position += forwardVector * Time.deltaTime * speed;
I mentioned that the caracter might not be facing the way he needs to move (ie strafing while jumping). Unless transform.forward works differently than I think, it doesn't seem to work. also, there is variable speed, so "transform.forward.x" would need to be multiplied by a variable that changed with speed (which as I mentioned, is not physics based). It's the "current speed" that I really need help calculating, not the transform.position.
Actually you mentioned that it wasn't facing Vector3.forward - a very different thing :)
In the case the character isn't facing the direction of movement - you still want a Vector3 to describe the direction. Do you know the direction of movement? If you do then replace forward with that. If you know the rotation of movement then it's
var forwardVector = rotation * Vector3.forward;
If you need to calculate it then it's:
var forwardVector = (transform.position - previousPosition);
forwardVector.y = 0;
var speed = forwardVector.magnitude/Time.deltaTime;
forwardVector = forwardVector.normalized;
previousPosition = transform.position;
With that code in the second part above you have a speed in the X/Z direction and a vector to use to move the character in the X/Z plane.
Alternatively you could do this and just have a scaled vector:
var forwardVector = (transform.position - previousPosition);
forwardVector.y = 0;
forwardVector = Vector3.Scale(forwardVector, 1/Time.deltaTime);
previousPosition = transform.position;
Then the speed is baked into the vector (and you saved a square root).