I have a FPS Faux gravity player controller it can do the basics Walk Run Jump Crouch but I'm now implementing Slide functionality to it and it works I have this Equation that calculates weather or not we should be decreasing in speed or increasing
moveSpeed = moveSpeed * ((slopeAngle / 2250) + .99);
it works, it works well but we have a issue that the equation doesn't care if we are gong Uphill or down so, I can actually slide accelerate up a hill so how can I implement a system that will lower my speed if my direction is facing up hill and increase it when I'm facing down hill
I'm already using terrain normals so I need a way to figure out what the up direction of a terrain normal is and then plug it into my equation so when I'm facing down I accelerate and facing up the terrain normal I decelerate
You need to use the geometry of the situation:
You have two known vectors: n, the normal to the surface you are currently on, and g, gravity (both direction and magnitude).
You also have one desired vector: a, your acceleration due to sliding (this would then be added to any other accelerations)
Neglecting friction (which you probably don't want to do, but that's separate), your acceleration is given by the projection of the gravity vector onto the surface plane:
a = g - n * Vector3.Dot (g, n) / Vector3.Dot (n, n)
If n is known to be a unit vector, you can skip the division as an optimization.
This will take care of acceleration direction regardless of the slope and your current velocity, or even the direction of gravity. It will also work equally well in 2D or 3D (or any other dimension, really).
You could raycast forward in a forward direction from your feet to check if they are going uphill. If it hits something, then we will not calculate the sliding.
The height value must be slightly less than half your player's height
Also, dist must be a low number, but not too low.
public float height = 0.99f; //--> Must be a little less than half the height
public float dist = 0.02f; //--> Must be a low number, but not too low
void Update()
{
Ray ray = new Ray(transform.position - height, transform.forward);
if (!Physics.Raycast(ray, dist))
{
moveSpeed = moveSpeed * ((slopeAngle / 2250) + .99);
}
}
Related
While writing a quadrotor simulation in Unity, I've needed to calculate the angle of attack.
However, all the examples and implementations I can find on the internet are calculating angle of attack with respect to the current direction of the aircraft.
e.g.
Vector3 linearVelocity = GetComponent<Rigidbody>().velocity;
Vector3 localVelocity = transform.InverseTransformDirection(linearVelocity);
return Mathf.Atan2(-localVelocity.y, localVelocity.z);
But to properly simulate quadrotor dynamics, I need to find the angle of attack with respect to the current vehicle velocity, that is to say, simply yawing the aircraft should not have any effect on the angle of attack, as the angle of attack should be with respect to the velocity instead of the aircraft direction, and yawing only changes direction, only pitch and roll can change angle of attack in this sense.
However, I am at a loss as to how to go about calculating angle of attack in this manner. My initial guess was to get the body frame velocity, but with its direction pointing at the velocity vector (such that its horizontal velocity should always be zero I think?), and then perform the inverse tangent on it to calculate angle of attack, but I can't figure out how to calculate velocity in this manner.
My camera jitters on rotation, but not movement. This script is the only asset in a new project, and it's attached to the camera - it's supposed to be a free-flying camera. I added a few cubes into the environment so I could check it was moving correctly, and it stutters several times a second whenever it's rotated. Movement works just fine.
I've tried changing camera clipping planes, I've tried moving either movement or rotation or both into Update() instead, removing the default camera and adding my own, and since it's an otherwise empty project I'm showing over 500fps so don't have any performance issues - nothing has had any effect, for better or worse.
Any suggestions welcome! If someone has a minute to open up a default project and slap this script on the camera and make sure it's not something on my end, that would at least rule that out and I'd really appreciate it. Thanks in advance.
public class CameraController : MonoBehaviour
{
public Vector2 mouseSensitivity = Vector2.one;
public Vector3 moveSensitivity = Vector2.one;
public Transform camTransform;
Vector3 camEulers = Vector3.zero;
void Start()
{
camTransform = FindObjectOfType<Camera>().transform;
}
void LateUpdate()
{
KeyboardMovement();
LockedMouseRotation();
}
void KeyboardMovement()
{
camTransform.position += Input.GetAxis( "Vertical" ) * camTransform.forward * Time.deltaTime * moveSensitivity.y;
camTransform.position += Input.GetAxis( "Horizontal" ) * camTransform.right * Time.deltaTime * moveSensitivity.x;
}
void LockedMouseRotation()
{
camEulers.x -= Input.GetAxis( "Mouse Y" ) * mouseSensitivity.y * Time.deltaTime;
camEulers.y += Input.GetAxis( "Mouse X" ) * mouseSensitivity.x * Time.deltaTime;
camEulers.x = Mathf.Clamp( camEulers.x, -90.0f, 90.0f );
camTransform.rotation = Quaternion.Euler( camEulers );
}
}
Don't use Time.deltaTime here.
Your goal here is to convert measurements of linear distance (GetAxis("Mouse X") and GetAxis("Mouse Y")) into a measurement of angular distance (the angular distance you are using to adjust the camera's Euler angles). For that you only need a constant factor, which can be your mouseSensitivity components.
But GetAxis gets multiplied by Time.deltaTime in other places and works perfectly fine. Why do those work like that?
Your goal is not converting to distance from "throttle position" like one might from GetAxis("Horizontal") or GetAxis("Vertical") or GetAxis("customKeyButtonOrThrottleAxis") . That is a situation where you would want to multiply by a time (Time.deltaTime) to calculate a distance if you are using the position of the button or throttle as velocity. This is because distance = speed * time.
In some cases you might multiply by Time.deltaTime to calculate a velocity or speed if the button or throttle is to represent acceleration, because speed = acceleration * time.
Okay, so why doesn't Time.deltaTime work here?
When you use GetAxis("Mouse X") or GetAxis("Mouse Y"), you get a measurement of pixel difference in position since the last frame.
The typical way a mouse driven camera works in games is that moving the mouse the same distance in the same direction should move the camera the same way (assuming you don't move the camera all they way up or down of course).
So what that means is that multiplying by Time.deltaTime does here is often actually the opposite of what you might expect - moving the mouse the same distance moves the camera's rotation differently depending on how many frames that movement occurred over and how quickly those frames were rendered.
The faster the frames were rendered (that means, a smaller Time.deltaTime), the less camera rotation the same mouse distance becomes. This results in unpredictable jitter especially when the very act of moving the camera can drastically change the framerate.
So how do I fix it then?
So, the only thing you need to do here is to remove the multiplication by Time.deltaTime:
camEulers.x -= Input.GetAxis( "Mouse Y" ) * mouseSensitivity.y;
camEulers.y += Input.GetAxis( "Mouse X" ) * mouseSensitivity.x;
A similar situation where you might want to include Time.deltaTime is if you want to calculate the speed or velocity of the mouse movement.
But, in that case, you would want to divide by Time.deltaTime. This is because speed = distance / time.
Vector2 mouseVelocity = Vector2.Scale(mouseSensitivity,
new Vector2(Input.GetAxis("Mouse X"),
Input.GetAxis("Mouse Y"))
) / Time.deltaTime;
In most cases, you probably don't want to be concerned with the speed/velocity of the mouse movement. But, for example, those interested in a super monkey ball type game using a track ball input might find this side bit useful!
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
I'm trying to find a way to handle reflections for a breakout clone.
I would upload an image to the post instead of the following paragraph, however i have not yet gained the privilege of that yet.
If the ball intersects the left hand side i want it to bounce off to the left.
if the ball intersects the right hand side i want it to bounce off to the right. if the ball intersects the middle section i want it to bounce up the way. i want to learn how to make it bounce in a varying direction dependant on what side of the left, right, or middle section was intersected
I would like to not use three separate rectangles for this, i want to learn how to do it with one.
I use a Vector2 for ball velocity, projVel.
It's position is projPos.
A rectangle for the paddle lightRect.
The reason I use proj.collRect for the beginning of the if is because I cannot use the intersect method with Vector2.
This is my makeshift collision handler at present, which does work but the speed changes to an extent which renders the game unplayable. The speed clamp i have only slightly slows it down i think. i have a variable for projSpeed i cannot clamp that or it will never be able to stop.
if (proj.collRect.Intersects(lightSaber.lightRect))
{
proj.projPos.Y = lightSaber.lightRect.Y - proj.projTxr.Height;
proj.projVel.Y *= -1;
proj.projVel.X = 10 * (proj.projPos.X - lightSaber.lightRect.Center.X) / (lightSaber.lightRect.Center.X);
}
proj.projVel.X = Math.Max(-4, Math.Min(proj.projVel.X, 4));
proj.projVel.Y = Math.Max(-4, Math.Min(proj.projVel.Y, 4));
Help me by showing me how I could do this, maybe in the Math. method, or even an alternative to .Intersects so I can use projPos instead of collRect.
I really am not sure where to start, if there is another way I could do it an example would be great.
Instead of manipulating X and Y velocities independently, I recommend that you calculate a reflection angle based on the position and then derive the velocity from the angle and the speed prior to impact.
Example:
// NOTE: this code assumes that positive Y is down
if (proj.collRect.Intersects(lightSaber.lightRect) && projPos.projVel.Y > 0.0f) // only bounce if projectile is moving downward
{
// remember current speed for when we calculate new velocity
var projSpeed = projVel.Length();
// make sure the projectile no longer intersects the bar
proj.projPos = lightRect.Y - proj.projTxr.Height;
// interpolate reflection angle
var t = (proj.projPos.X - lightSaber.lightRect.X) / lightSaber.lightRect.Width;
var reflectDegrees = 150.0f - t * 120f; // straight up +/- 60 degrees
var reflectRadians = reflectDegrees * (float)Math.PI / 180.0f;
// final velocity determined by angle and original projectile speed
proj.projVel = new Vector2((float)Math.Cos(reflectRadians) * projSpeed, -(float)Math.Sin(reflectRadians) * projSpeed);
}
I am currently experimenting with some physics toys in XNA using the Farseer Physics library, however my question isn't specific to XNA or Farseer - but to any 2D physics library.
I would like to add "rocket"-like movement (I say rocket-like in the sense that it doesn't have to be a rocket - it could be a plane or a boat on the water or any number of similar situations) for certain objects in my 2D scene. I know how to implement this using a kinematic simulation, but I want to implement it using a dynamic simulation (i.e. applying forces over time). I'm sort of lost on how to implement this.
To simplify things, I don't need the dynamics to rotate the geometry, just to affect the velocity of the body. I'm using a circle geometry that is set to not rotate in Farseer, so I am only concerned with the velocity of the object.
I'm not even sure what the best abstraction should be. Conceptually, I have the direction the body is currently moving (unit vector), a direction I want it to go, and a value representing how fast I want it to change direction, while keeping speed relatively constant (small variations are acceptable).
I could use this abstraction directly, or use something like a "rudder" value which controls how fast the object changes directions (either clockwise or counter clockwise).
What kind of forces should I apply to the body to simulate the movement I'm looking for? Keep in mind that I would also like to be able to adjust the "thrust" of the rocket on the fly.
Edit:
The way I see it, and correct me if I'm wrong, you have two forces (ignoring the main thrust force for now):
1) You have a static "fin" that is always pointed in the same direction as the body. If the body rotates such that the fin is not aligned with the direction of movement, air resistance will apply forces to along the length of the fin, proportional to the angle between the direction of movement and the fin.
2) You have a "rudder", which can rotate freely within a specified range, which is attached some distance from the body's center of mass (in this case we have a circle). Again, when this plane is not parallel to the direction of movement, air resistance causes proportional forces along the length of the rudder.
My question is, differently stated, how do I calculate these proportional forces from air resistance against the fin and rudder?
Edit:
For reference, here is some code I wrote to test the accepted answer:
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
float dc = 0.001f;
float lc = 0.025f;
float angle = MathHelper.ToRadians(45);
Vector2 vel = new Vector2(1, 0);
Vector2 pos = new Vector2(0, 0);
for (int i = 0; i < 200; i++)
{
Vector2 drag = vel * angle * dc;
Vector2 sideForce = angle * lc * vel;
//sideForce = new Vector2(sideForce.Y, -sideForce.X); // rotate 90 degrees CW
sideForce = new Vector2(-sideForce.Y, sideForce.X); // rotate 90 degrees CCW
vel = vel + (-drag) + sideForce;
pos = pos + vel;
if(i % 10 == 0)
System.Console.WriteLine("{0}\t{1}\t{2}", pos.X, pos.Y, vel.Length());
}
}
When you graph the output of this program, you'll see a nice smooth circular curve, which is exactly what I was looking for!
If you already have code to integrate force and mass to acceleration and velocity, then you just need to calculate the individual part of each of the two elements you're talking about.
Keeping it simple, I'd forget about the fin for a moment and just say that anytime the body of your rocket is at an angle to it's velocity, it will generate a linearly increasing side-force and drag. Just play around with the coefficients until it looks and feels how you want.
Drag = angle*drag_coefficient*velocity + base_drag
SideForce = angle*lift_coefficent*velocity
For the rudder, the effect generated is a moment, but unless your game absolutely needs to go into angular dynamics, the simpler thing to do is let the rudder control put in a fixed amount of change to your rocket body angle per time tick in your game.
I suddenly "get" it.
You want to simulate a rocket powered missile flying in air, OK. That's a different problem than the one I have detailed below, and imposes different limits. You need an aerospace geek. Or you could just punt.
To do it "right" (for space):
The simulated body should be provided with a moment of inertia around its center of mass, and must also have a pointing direction and an angular velocity. Then you compute the angular acceleration from the applied impulse and distance from the CoM, and add that to the angular velocity. This allows you to compute the current "pointing" of the craft (if you don't use gyros or paired attitude jets, you also get a (typically very small) linear acceleration).
To generate a turn, you point the craft off the current direction of movement and apply the main drive.
And if you are serious about this you also need to subtract the mass of burned fuel from the total mass and make the appropriate corrections to the moment of inertia at each time increment.
BTW--This may be more trouble than it is worth: maneuvering a rocket in free-fall is tricky (You may recall that the Russians bungled a docking maneuver at the ISS a few years ago; well, that's not because they are stupid.). Unless you tell us your use case we can't really advise you on that.
A little pseudocode to hint at what you're getting into here:
rocket {
float structuralMass;
float fuelMass;
point position;
point velocity;
float heading;
float omega; // Angular velocity
float structuralI; // moment of inertia from craft
float fuelI; // moemnt of inertia from the fuel load
float Mass(){return struturalMass + fuelMass};
float I(){return struturalI + fuelI};
float Thrust(float t);
float AdjustAttitude(float a);
}
The upshot is: maybe you want a "game physics" version.
For reason I won't both to go into here, the most efficient way to run a "real" rocket is generally not to make gradual turns and slow acceleration, but to push hard when ever you want to change direction. In this case you get the angle to thrust by subtracting the desired vector (full vector, not the unit) from the current one. Then you pointing in that direction, and trusting all out until the desired course is reached.
Imagine your in floating in empty space... And you have a big rock in your hand... If you throw the rock, a small impulse will be applied to you in the exact opposite direction you throw the rock. You can model your rocket as something that rapidly converts quantum's of fuel into some amount of force (a vector quantity) that you can add to your direction vector.