XNA 2D game - behaves differently on friend's computer - c#

I made a simple networking xna game using c# and lidgren. But velocity of objects are different on friend's computer - resolution of window is the same, fps are the same (both 60), application is the same, but he's character is just slower for some reason. For some time his velocity is equal to mine, but then it slows down again.
Other friends do have equal velocities as I do. What could be a problem? The program adjusts movement according to fps, so there is probably no problem in fps.

Without seeing your code its hard to say for sure.
The program adjusts movement according to fps
Well it's generally better to think of animation as a function elapsed since the last update rather than frames per second. That way, the animation will take the same amount of real world time to complete regardless of FPS whether it be fixed or variable update.
Movement deltas should take into account time elapsed since last game update not last/current FPS.
e.g.
public Vector3 Velocity;
public Vector3 Position;
public void Update(GameTime gameTime)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
// Apply acceleration
Vector3 acceleration = force / Mass;
Velocity += acceleration * elapsed;
// Apply psuedo drag
Velocity *= DragFactor;
// Apply velocity
Position += Velocity * elapsed;
.
.
.

You said you're using lindgren to make it multiplayer? Maybe it's rubberbanding due to latency. Try checking it on 2 computers on lan to see if it resolves the issue.
Possible there's different settings to lindgren to specify how to handle syncing or prediction.

Related

C#/Unity Camera Follow Jitter due to Time.deltaTime

Game: In a simple 2D Portrait Game made in Unity, I have a GameObject (Player) that has a fixed location and which is moving upwards. The Camera follows the Player and animated Obstacles are spawning from time to time moving left to right. The attached Screenshot shows the Scene.
The Problem:
The Movement is not smooth, as it seems like the Player is jittering. I think I already identified one of the causes: Big variation of Time.deltaTime. Average value is 0.0167, but I had variations. Minimum was 0.00177, maximum value was 0.2249519.
Settings:
Target Framerate is 60. I use Unity 2019.4.2f1 and as build target an iPhone X with iOS 14.2.
Scripts
public class Player: MonoBehaviour
{
float speed = 5f;
void Update()
{
transform.Translate(0,speed*Time.deltaTime,0);
}
}
public class CamFollow : MonoBehaviour
{
public Transform Player;
private Vector3 FollowVector;
void LateUpdate()
{
FollowVector = Player.position - new Vector3(0, -4.0f, 10);
transform.position = Vector3.Lerp(transform.position, FollowVector, Time.deltaTime * 4f);
}
}
Note: I need to use Lerp, because the Player may lower or increase the speed for one second, then the camera gently moves to the new position, before changing back. For the Obstacles I don't have a Script. They are moving, by using the Animation Component. For the Obstacles I only loop a change of the x value of the position.
My alternative solutions:
1. Changing the value for Time.deltaTime to a constant value of 0.01666667f:
void Update()
{
transform.Translate(0,speed*0.01666667f,0);
}
This makes the Player Object jitter a lot in the Unity Editor but only a little on the device
2. Using Fixed Update both for the Camera Follow and the Player Movement
This makes the movement and camera follow perfectly smooth, but the animated objects jitter a lot. I know Unity wants to adress the deltaTime issue in one of the next updates. But there should be a solution for my problem, so did anybody have a similiar problem, which could be solved? I prefer the 2nd alternative, because the movement looked really smooth and nice, so can I somehow make the animation part of "fixedUpdate"?
The variation in the 'deltaTime' is to be expected.
The variation is large on the PC because you are running on a complex computer with a complex operating system and lots of other applications running simultaneously, each with a multitude of threads, which every once in a while want to do some work. Thus, the scheduler of the operating system cannot guarantee that you are going to get a time slice at the precise moment that you want it in order to render your next frame.
The variation is smaller on the mobile device because it is a much simpler machine with a lot less going on, so the scheduler is able to give you time slices close to the precise intervals that you are asking.
You are already taking this variation into account when you do
transform.Translate( 0, speed * Time.deltaTime, 0 );
This is a fundamental technique in game development: the frame rate is never constant, so the distance by which you must move an object on each frame depends on the precise amount of time elapsed between this frame and the previous frame.
So, that part is fine.
Your problem lies in
transform.position = Vector3.Lerp( transform.position, FollowVector, Time.deltaTime * 4f );
Here you are passing Time.deltaTime * 4f for parameter t of Vector3.Lerp(). I have no idea what you are trying to accomplish, but the number you need to pass there needs to be a gradual transition between 0 and 1, and instead you are passing a randomly varying number of seconds multiplied by some magic constant 4. This does not look correct.
A couple of options that I can think of:
Always use 0.5 for t so that the camera always rushes to the right position and then slows down as it gets closer to it.
Calculate a separate speed vector for the camera, then move the camera using a translation just as you do for the player.

RigidBody2D AddForce Not Adding Acceleration

I'm trying to add acceleration to an object with a RigidBody2D component using AddForce, but all it seems to do is add a fixed velocity instead.
Here are the RigidBody2D settings:
For testing I've modified the Update function to allow me to add forces and report the object's velocity periodically:
void Update()
{
time += Time.deltaTime;
if (time > 0.5)
{
Debug.Log("Velocity magnitude = " + rigidbody2D.velocity.magnitude);
time = 0;
}
if (Input.GetKeyDown(KeyCode.Q))
{
rigidbody2D.AddForce(Vector2.right);
}
}
What I see is that every time I press Q, the velocity magnitude increases by a fixed 0.02.
I.e. first it doesn't move at all and the velocity is 0, then after pressing Q the velocity magnitude changes to 0.02 and stays at 0.02 while the object trudges slowly to the right. Pressing Q again increases it to 0.04, then pressing once more increases it to 0.06 and so on.
These are results from two days ago. I did the experiment again today and got different velocity increments but the same behavior otherwise.
The velocity changes only when I add a force.
If I added a force of magnitude 1 to an object at rest with a mass of 1 then its velocity would increase by 1 in magnitude every single unit of time (which I think here is seconds).
Instead it's staying fixed.
Using ForceMode2D.Impulse increases the velocity increments from 0.02 to 1, but the behavior stays the same - no acceleration, only one-time increments in speed.
What am I doing wrong?
I've tried looking for similar posts and for the problem in general but the only things I found were either irrelevant or asking the opposite (how to stop acceleration from occurring).
Any help would be appreciated.
The Unity version is 2019.1.1f1.
TL;DR
What you are doing wrong is that you are expecting the wrong physics behavior from the apply force function. That function does what it says, it applies force. It changes the object velocity instantaneously adding to it. The force mode for 2d bodies only tells the engine to consider the object's mass or not.
The problem is the naming Unity uses, AddForce doesn't "add" the force, it just applies the force for a single frame. In the following frames, all forces are zero again. If you want to keep the force, just create your own vector in your script, modify it, and apply it to the object every frame using AddForce.
how are you?
I have created a sample project to reproduce your issue but I couldn't reproduce the velocity staying fixed as you said. I'm not sure how you set up your scene so I made some assumptions. You probably have disabled either gravity on your object or friction, since you are reporting that the velocity is increased.
Acceleration, on the other hand, is a constant force being applied, think of it. If your car is still, and you push it for a short amount of time, the car will move then stop. If you keep pushing on the other hand, adding more and more force, the car will move faster and faster. Now think about your environment, you have a frictionless object. Every time you press Q you add a small force to it. It moves to the right a bit faster but with a constant speed (there is no force to change its velocity).
Here is what you'd want to do. Instead of adding the force only in the frame you pressed Q, add while you are pressing Q. This is what you want to do:
private void FixedUpdate()
{
time += Time.deltaTime;
if (time > 0.5)
{
Debug.Log("Velocity magnitude = " + rigidbody2D.velocity.magnitude);
time = 0;
}
if (Input.GetKey(KeyCode.Q))
{
rigidbody2D.AddForce(speedMultiplier * Time.fixedTime * Vector2.right, ForceMode2D.Force);
}
}
Another problem is the naming Unity uses, AddForce doesn't "add" the force, it just applies the force for a single frame. In the following frames all forces are zero again. If you want to keep the force, just create your own vector in your script, modify it, and apply it to the object every frame using AddForce.
Also, see that I changed Update to FixedUpdate? In Unity, you are recommended to apply all physics changes in that method instead. Update runs as much as it can (once every frame if possible), fixed update instead runs only after the physics thread is done. This means you are not spending CPU time telling the object to move every frame, and instead you are waiting for the physics to be synchronized.
I don't think that's going to add enough force to the object to get it into motion. Normally you need to multiply your direction by a "force" multiple. Try something like rigidbody2D.AddForce(Vector2.right * 1000);. That is, intentianally, probably way too much force but at least you'll know it's moving.

Unity 2D launch gameObject at a specific angle without affecting speed

I am working on a game where i need to shoot the ball at an angle and power defined by 2 sliders (1 angle slider, 1 power slider). I currently have this code to control the launching of the ball:
public void shoot()
{
float angle = angleSlider.GetComponent<Slider>().value;
float power = powerSlider.GetComponent<Slider>().value;
gameObject.SetActive(false);
ball.GetComponent<Rigidbody2D>().simulated = true;
Vector2 releaseVector = Quaternion.AngleAxis(angle, transform.up) * transform.forward;
ball.GetComponent<Rigidbody2D>().velocity = releaseVector * (power/3);
}
with this current code it works almost perfect apart from one thing. When the angle is like between 30 and 60, the ball is launched well but if i set it to 0 degrees the ball would barely move and on the contrary if i set it to 90 degrees, the ball launches with much more power. How can i set a constant speed for all degrees so that the speed is only affected by the power slider only please? Thanks.
Typically, you shouldn't set the velocity of a rigidbody directly. Per the Unity docs...
In most cases you should not modify the velocity directly, as this can result in unrealistic behaviour.
Instead, you usually want to impart a physical impulse to the ball using an API like AddForce or AddRelativeForce
That is easy.. You have to normalize the releaseVector.
ball.GetComponent<Rigidbody2D>().velocity = releaseVector.normalized * (power/3);
Then adjust the power to what you want. That way you will have the direction u wanted and speed depends on the power value.
If you want to know what normalize do, you can find more information here;
https://docs.unity3d.com/ScriptReference/Vector3.Normalize.html

Unity 2D scripted friction equation

I am working on the friction for a square object for after it is done being pushed by the player. The block's movements are controlled purely through script using transform.Translate(velocity) each frame and only a boxcollider2D. I am speculating that because i am controlling the block's movements each frame manually is the reason i can't seem to get the boxcolliders2D's physics material 2D friction to work.
Basically, I am trying to recreate the built in physics similar to rigidbodies by using transform.translate, or use the built in physics if possible. So far, i've landed on something like this
newVelocity.x -= ( 1 / (newVelocity.x * newVelocity.x));
In an attempt to reduce the velocity.x each frame until it hits 0 and shorts out. Obviously, this falls apart when the velocity.x becomes a decimal number. I'm stumped on what i should be doing to achieve a friction similar to rigid bodies where it slows down a little at first and then much faster towards the end as it stops. Any and all help appreciated, thanks in advance!
You could compare the signs of the velocity before and after calculating the change in velocity, and set the velocity to zero when the sign changes, like so:
newVelocity.x -= ( 1 / (newVelocity.x * newVelocity.x));
if(Mathf.Sign(previousVelocity.x) != Mathf.Sign(newVelocity.x)) {
newVelocity.x = 0f;
}
One thing, though, is that normal friction is not calculated using the above equation, it's calculated as follows:
newVelocity.x -= frictionCoefficient*Time.fixedDeltaTime;
And with this, you wouldn't need to compare the velocity to the previous velocity as you can just say if the velocity is low, it's zero. You could still compare the previous velocity sign stuff if you wanted to though, but this is probably more efficient
if(newVelocity.x < 0.01f) {
newVelocty.x = 0f;
}

How to make Fluid Drag equation not framerate dependent

I am trying to plan for a game I started coding. (Very much in the beginnings)
My problem is that I want the acceleration / movement portion of all game objects to be based on acceleration force vs drag (thus resulting in terminal velocity as the upper limit of speed available)
While I could go another route, I'd rather not if possible. Additionally, it has been suggested (by a friend) that I could use a physics library, but that seems overkill and besides, I'd like to learn and understand these concepts myself - I always feel like I better understand my own programs when I do.
I am making a 2D game and using Vector2 variables for position, heading and thrust force (the acceleration force applied). It's top-down so gravity is not a part of the equation.
Before I code it, I'm working out test cases in Excel - which is how I check my math before committing math to code. And I'm discovering that my use of the drag equation is making the object in question framerate dependent!! Specifically, the better the framerate, the lower the resultant terminal velocity.
I've been trying to modify the equations as necessary to account for framerate, but it eludes me.
If you want to work with the same spreadsheet I am, you can download the spreadsheet here.
But you don't have to - here are the specifics.
The drag equation as I understand it is:
Drag = 0.5 * FluidDensity * Velocity * Velocity * DragCoefficient * IncidenceArea
Using some numbers picked from thin air for calculations, if Fluid Density is 0.233 and the Drag Coefficient is 0.4 and the Incidental Area is 0.1 and the Acceleration force is 50 pixels per second, then here is what happens:
If I calculate that acceleration is applied every 0.25 seconds (once every quarter second) at 1/4 the Acceleration force (to match the timing) then we reach terminal velocity at about 39.3 pixels per second.
If I calculate acceleration instead at every second, we reach terminal velocity at about 53.6 pixels per second.
Specifically, every time I calculate for a given DeltaTime, the resultant speed is calculated as (code is from my head - not from an IDE - apologies if there's a bug in it):
//In globals / initialization:
Vector2 Position;
Vector2 Speed;
Vector2 ThrustForce;
float Density = 0.233f;
float DragCoefficient = 0.4f;
float IncidentalArea = 0.1f;
//In the update loop
//DeltaTime is a float based upon how much of a second passed
Vector2 AccelerationToApply = ThrustForce * DeltaTime;
Vector2 NewSpeed = Speed + AccelerationToApply;
Vector2 Drag = Speed * Speed * 0.5f * Density * DragCoefficient * IncidentalArea;
NewSpeed -= Drag;
Speed = NewSpeed;
That's the problem math. Here is the question:
How should this be expressed so that it's framerate independent?
The classic approach is to step the simulated physical time independent from the game loop frame rate, calculating multiple sub-iterations per frame if necessary to advance the physics. This allows you to control your time step (generally making it smaller than the main frame rate), which also helps to keep other potentially unstable calculations under control (such as oscillators.) This of course means that your physics has to compute faster than real time for the fixed time step chosen, as otherwise your world goes into slow motion.
Speaking of instability, I imagine that you'll see some oscillation effects in your current implementation, depending on whether you're overshooting the terminal velocity in a given time step. One way to resolve this is to compute the speed via analytical integration instead of approximating using a incremental step. To do that, express your formula as a differential equation and see if it is of a form that can be readily solved analytically.
There were two parts missing from the code above. While I had played with turning one part "on" and "off" to experimentally determine if it was needed, without the other I was having problems finding the right answer.
The two parts are this: The resultant drag does need to be multiplied by the time step in order to reduce its effect upon the acceleration, but also and perhaps more importantly - the acceleration force to be applied on this frame needs the drag subtracted from it before it is applied to the speed - not after like I had above.
The modified (and now framerate independent) code looks like this:
Also, I reduced having 4 "constant" coefficients to just one coefficient for the sake of simplicity.
//In globals / initialization:
Vector2 Position;
Vector2 Speed;
Vector2 ThrustForce;
float Coefficient = 0.009f;
float PreviousDrag = 0.000f;
//In the update loop
//DeltaTime is a float based upon how much of a second passed
Vector2 AccelerationToApply = ThrustForce * DeltaTime + PreviousDrag * DeltaTime;
Vector2 NewSpeed = Speed + AccelerationToApply;
PreviousDrag = Coefficient * NewSpeed * NewSpeed;
Speed = NewSpeed;
Running this logic through excel, I find that at approximately the same times I reach the same approximate terminal velocity no matter how often (or not) I calculate a change in velocity.

Categories