Trying to programatically set the force based on the distance of the selected object, and another static object.
To understand this better I am making a golf game, I have forced being applied to ball already done but I am manually setting the force at this point. Right now I am trying to build some pseudo-code for how I can accomplish this. I do not have a lot of experience with physics so anything will help here. But basically I have a golfer who selects an area that he would like to hit it to. So once selected, I will grab the location of the selection, obviously find the difference via (selected.transform.position - golfer.transform.position) but now I am a little stuck on what to do next. How can I find the force needed to get to the selected location?
here's some current code in case it helps
var target : Transform;
var speed : float;
var force : float;
var angle = 50;
var i = 1;
function FixedUpdate()
{
if (target == null)
target = GameObject.FindWithTag("Hole").transform;
}
function Hit()
{
var torque = Vector3(Input.GetAxis("Vertical"), 0, -Input.GetAxis("Horizontal"));
var targetRotation = Quaternion.LookRotation (target.position-transform.position,Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation,targetRotation,8);
transform.eulerAngles.x = -angle;
rigidbody.AddTorque(torque.normalized*speed);
rigidbody.AddForceAtPosition (transform.forward * speed * force,target.position, ForceMode.VelocityChange );
}
You will need a few things.
Angle of Force theta
Mass of object m
On the x-axis:
Acceleration a
Initial velocity vi
Final velocity vf
Distance d
Time to travel t
On the y-axis:
Acceleration a = gravity
Initial velocity vi_y
Final velocity vf_y
Height traveled h
Then use the equations for Kinematics and F=ma to find the force.
Your goal is to combine what you know, mass of object, distance, etc. and apply the equations of kinematics to find the acceleration needed on the x-axis. Then you will plug in that acceleration and the mass to F=ma to find the Force.
Related
As per my game requirements, I was giving manual force when two cars collide with each other and move back.
So I want the correct code that can justify this. Here is the example, collision response that I want to get:
As per my understanding, I have written this code:
Vector3 reboundDirection = Vector3.Normalize(transform.position - other.transform.position);
reboundDirection.y = 0f;
int i = 0;
while (i < 3)
{
myRigidbody.AddForce(reboundDirection * 100f, ForceMode.Force);
appliedSpeed = speed * 0.5f;
yield return new WaitForFixedUpdate();
i++;
}
I am moving, my cars using this code:
//Move the player forward
appliedSpeed += Time.deltaTime * 7f;
appliedSpeed = Mathf.Min(appliedSpeed, speed);
myRigidbody.velocity = transform.forward * appliedSpeed;
Still, as per my observation, I was not getting, collision response in the proper direction. What is the correct way for getting above image reference collision response?
Until you clarify why you have use manual forces or how you handle forces generated by Unity Engine i would like to stress one problem in your approach. You calculate direction based on positions but positions are the center of your cars. Therefore, you are not getting a correct direction as you can see from the image below:
You calculate the direction between two pivot or center points therefore, your force is a bit tilted in left image. Instead of this you can use ContactPoint and then calculate the direction.
As more detailed information so that OP can understand what i said! In the above image you can see the region with blue rectangle. You will get all the contact points for the corresponding region using Collision.contacts
then calculate the center point or centroid like this
Vector3 centroid = new Vector3(0, 0, 0);
foreach (ContactPoint contact in col.contacts)
{
centroid += contact.point;
}
centroid = centroid / col.contacts.Length;
This is the center of the rectangle to find the direction you need to find its projection on your car like this:
Vector3 projection = gameObject.transform.position;
projection.x = centroid.x;
gameObject.GetComponent<Rigidbody>().AddForce((projection - centroid )*100, ForceMode.Impulse);
Since i do not know your set up i just got y and z values from car's position but x value from centroid therefore you get a straight blue line not an arrow tilted to left like in first image even in the case two of second image. I hope i am being clear.
I have a 2D scene that consists of 4 sprites, each with a box collider.
I then have a prefab that is simply a sprite of a circle with a 2D circle collider.
Finally I have a script named Atmosphere attached to my main camera that will fill the box with lots of instances of the prefab and give them a velocity in a random direction.
using UnityEngine;
public class Atmosphere : MonoBehaviour
{
public GameObject Molecule;
void Start()
{
float x = -4.5f;
while (x < 4.5f)
{
float y = -4.5f;
while (y < 4.5f)
{
var inst = GameObject.Instantiate(Molecule);
inst.transform.position = new Vector3(x, y, 0);
var rb = inst.GetComponent<Rigidbody2D>();
float xForce = Random.value * 2f - 1f;
float yForce = Random.value * 2f - 1f;
rb.AddForce(new Vector2(xForce, yForce) * 100f);
y += 0.5f;
}
x += 0.5f;
}
}
}
For a while the dots bounce around against each other and the edges of the box.
But after a while they eventually get stuck to the edges of the box.
Both the box and balls and the box walls have the same physics material
Which has zero friction and a bounciness of 1.
Why do they stick to the walls, and how can I stop it from happening?
Download Unity 3D demo
UPDATE
If I drop a single molecule into the box with the following script attached it gets stuck to the wall immediately.
[RequireComponent(typeof(Rigidbody2D))]
public class Molecule : MonoBehaviour
{
Rigidbody2D RigidBody2D;
void Start()
{
transform.position = new Vector3(0, 1, 0);
RigidBody2D = GetComponent<Rigidbody2D>();
float xForce = Random.value * 2f - 1f;
float yForce = Random.value * 2f - 1f;
RigidBody2D.AddForce(new Vector2(-.25f, -0.25f) * 100f);
}
}
Unity3D has a velocity threshold. Objects with a velocity below this threshold won't bounce etc.
The solution is to go to Edit > Project Settings > Physics 2D and to set the Velocity Threshold lower.
EDIT - The real solution:
So I was doing some reading on integration techniques and it hit me: The energy you're losing is quite likely coming from numerical inaccuracies stemming from several approximation techniques compounded.
I'm guessing the continuous collision detection algorithm is mostly to blame, floating-point error accumulation, but probably also from numerical integration techniques.
What you're trying to achieve is elastic collision, which means that it satisfies conservation of energy as well as momentum. The trick is going to be for you to add a script to every object that preserves the energy of the system by adding error-correcting velocity over time. Whether you actually use the energy route or not is up to you, there are a number of ways to track and modify the energy resulting in a change of velocity. Momentum would be the would be the easiest to track in my opinion. What you're trying to achieve is elastic collision, which means that it satisfies conservation
i.e.
Make a component that preserves the scalar quantity of kinetic energy or momentum (it'll probably produce the same results)
When you initialize all the particles with a velocity, make sure to save the starting momentum in the particle's script. I would save the scalar quantity for simplicity, so just use the length of velocity
Every frame, in the update event check the velocity of the rigid body. Find the change in momentum or change in energy and add the -difference and apply it to the object.
I doubt you'll have to work on collision events as well, especially if you use the exact same mass for every object. Here's a link with an example where someone corrected unity's friction-less physics using conservation of energy https://answers.unity.com/questions/168393/frictionless-physics.html
colliders may be stuck in each other for the reason of low contact offset, go to edit-project settings-physics2d and increase the default contact offset a little bit, 0.12 for example, it was work for me.
cheers
I am making an aircraft game and I need to the get the change in Yaw of the aircraft.
I am attempting to save the previous frame's transform.eulerAngles and push them back to local space of the transform so I can capture the change. I am trying transform.InverseTransformXXXXX but it doesn't seem to work.
private float _GetChangeInYawAngle()
{
float yaw = transform.InverseTransformDirection(m_lastForwardParented).y;
yaw = yaw > 180 ? yaw - 360 : yaw;
m_lastForward = transform.parent.eulerAngles;
return yaw;
}
There is no need to use InverseTransformDirection,
float _lastYaw;
void Update()
{
float thisYaw=transform.eulerAngles.y;
float deltaYaw=thisYaw-_lastYaw;
_lastYaw=thisYaw;
}
Of course you still need to handle 0-360 crossing in some way.
I may be misinterpreting what you are trying to achieve here, but if you are just trying to track current rotation against last rotation, the difference between eulerAngles and localEulerAngles handles your local-world space conversion automagically
#zambari
After looking at your answer I did some research into transforming quaternions.
The issue with your solution is that "thisYaw-_lastYaw" isn't pushed to local space and therefore the y axis can change wildly from frame to frame, thus the calculated difference can be much grater than the actual change. Moving the equation to local space resolves that issue unless there is a very high angular velocity, which I don't need to solve for. (In hind site, I guess I could have also used angular velocity to find this but I digress.)
Here is my working solution! Thanks for the input.
private float _SetChangeInYawAngle()
{
Quaternion LocalRotation = Quaternion.Inverse(m_lastYawRotation) * transform.rotation;
float yaw = LocalRotation.eulerAngles.y;
yaw = yaw > 180 ? yaw - 360 : yaw;
m_currentAngle -= yaw;
m_lastYawRotation = transform.rotation;
return m_currentAngle;
}
I am trying to build a 2D video game using JavaFX. There is a submarine at the bottom of the screen that fires torpedos. I have noticed that if I fire a torpedo on an Angle it travels at a faster rate, than if say I fired it straightup where is goes directly North. I'm assuming the difference in rates is because the screen is a rectangle, and when moving on a diagonal you are covering more distance.
Are there techniques to account for this, so you can get a constant rate of movement, regardless of the angle of travel of the projectile? I am writing the game using JavaFX under Eclipse.
Appreciate any help with this!
Thanks!
Since you are already firing in different directions, I'm assuming you have a velocity vector defined by two components (x, y). In JavaFX such a vector can be represented by Point2D. Given the speed you want the projectile to travel at, you can do the following:
public void fire() {
// the point at which you are shooting
Point2D target = ...
// the point from where you are shooting
Point2D source = ...
// the projectile speed per frame
double speed = ...
// velocity vector to be used to move
// the projectile at constant speed per frame
Point2D velocity = target.subtract(source).normalize().multiply(speed);
}
UPDATE: (included vector generation from angle)
In case you do not know the target point, you can obtain the vector from the angle you use to shoot:
public void fire() {
double angleDegrees = ...
double angleRadians = Math.toRadians(angleDegrees);
// the point from where you are shooting
Point2D source = ...
// the projectile speed per frame
double speed = ...
Point2D shootingVector = new Point2D(Math.cos(angleRadians), Math.sin(angleRadians));
// velocity vector to be used to move
// the projectile at constant speed per frame
Point2D velocity = shootingVector.normalize().multiply(speed);
}
Here is my code:
#pragma strict
public var spinAxis : Vector3 = Vector3(0,45,90);
function Start () {
}
function Update () {
// Slowly rotate the object around its X axis at 1 degree/second.
transform.Rotate(spinAxis * Time.deltaTime);
}
I just want the cube to spin on two axes (in this case, y and z) but it spins on all three. I know I'm making some dumb mistake here. I can do it successfully by saying
transform.Rotate(new Vector3(0,0,100) * Time.deltaTime);
for example. But I'd like the axes to be available from the inspector.
This will do what you want:
#pragma strict
public var spinSpeed : Vector3 = Vector3(0,45,90); // Degrees per second per axis
private var rotation = Vector3.zero;
function Update ()
{
rotation += spinSpeed * Time.deltaTime;
transform.rotation.eulerAngles = rotation;
}
The reason your code gives unexpected results is because I think you misread what the Transform.Rotate function does. It does not give you an axis and an amount to spin around like the spinAxis variable name suggests. That is achieved by Transform.RotateAround.
If you use Transform.Rotate then the rotations are applied sequentially. But in the process the axes get mixed up. For instance if you first rotate 90 degrees on the Y-axis then the X- and Z-axes have switched place. Rotate sequentially on any two axes and the third one will always get involved like this. Using the above code you essentially reset or recreate the entire rotation every update which allows you to keep the uninvolved axis at 0.