How can i throw an object to a specific point with physics - unity3d

I want exactly this :
The probability of going to the basket must be 100%.
Throw
I tried this :
Vector3 direction = new Vector3(pota.position.x - transform.position.x, pota.position.y - transform.position.y, pota.position.z - transform.position.z);
float vAngle = Vector3.Angle(direction, Vector3.forward);
float hAngle = Vector3.Angle(direction, Vector3.left);
float distance = Vector3.Distance(transform.position, pota.position);
float yDistance = Mathf.Abs(distance * Mathf.Cos(vAngle)) + 0.5f;
float xzDistance = (distance * Mathf.Sin(vAngle));
float xDistance = (xzDistance * Mathf.Sin(hAngle));
float zDistance = Mathf.Abs(xzDistance * Mathf.Cos(hAngle));
rb.AddForce(new Vector3(xDistance, yDistance, zDistance), ForceMode.Impulse);
Thank you for your help.

this is something VERY complicated and there is no real easy way to figure this one out
Read one of the answers in this quetion
and good luck figuring this out
https://math.stackexchange.com/questions/3486775/how-do-you-calculate-the-trajectory-of-an-arrow
(or you could just use lurp or slurp or movetowards lel)

Related

What's wrong with this mouse look function?

I've been toying with iterations of this for a few weeks, but it's still busted so I thought id reach out for some help.
This performs as expected except for one glaring issue: the output sensitivity appears to be super pitch dependent.
`
//Grab mouse input
float rotateHorizontal = Input.GetAxis("Mouse X");
float rotateVertical = -Input.GetAxis("Mouse Y");
Vector3 rotation = new Vector3(rotateVertical, rotateHorizontal, 0);
transform.Rotate(sensitivity * Time.deltaTime * rotation);
Vector3 eAngles = transform.eulerAngles;
float pitch = eAngles.x;
pitch = ClampAngle(pitch, -camClamp, camClamp);
transform.localEulerAngles = new Vector3(pitch, eAngles.y, eAngles.z);
`
What am I missing? I'm pretty sure it's not the clamp angle function since I stole it from a reputable source.
Thanks for the help.
Rotations are hard!
I think it was a rotation order problem.
Switched to quaternions, problem remained, then found this lovely thread and reordered the operands.
originalRotation = transform.localRotation;
//Grab mouse input
float rotateHorizontal = Input.GetAxis("Mouse X");
float rotateVertical = Input.GetAxis("Mouse Y");
Quaternion xQuaternion = Quaternion.AngleAxis(rotateHorizontal, Vector3.up);
Quaternion yQuaternion = Quaternion.AngleAxis(rotateVertical, -Vector3.right);
transform.localRotation = xQuaternion * originalRotation * yQuaternion;
Vector3 eAngles = transform.eulerAngles;
float pitch = eAngles.x;
pitch = ClampAngle(pitch, -camClamp, camClamp);
transform.localEulerAngles = new Vector3(pitch, eAngles.y, eAngles.z);
Thank you freya holmer
Order matters in quaternion multiplication!

How to change the distance/radius from center that the objects are instantiated

How would it be possible to move the 8 instantiatedObjects "cubes" closer to the pillar.
public void instantiateInCircle()
{
for (int i = 0; i < amount; i++)
{
float radius = 8;
float angle = i * Mathf.PI * 2f / radius;
Vector3 newPos = transform.position + (new Vector3(Mathf.Cos(angle) * radius, spawnHeight, Mathf.Sin(angle) * radius ));
GameObject instantiatedObject = Instantiate(itemToSpawn, newPos, Quaternion.Euler(0, 0, 0));
instantiatedObject.transform.LookAt(spawnAroundThis.transform);
instantiatedObject.transform.parent = spawnAroundThis.transform;
instantiatedObject.transform.localScale = new Vector3(scale, scale, scale);
//this seems to work-ish , not sure if its good math but hey :)
//Thanks BugFinder!
instantiatedObject.transform.position = instantiatedObject.transform.position += instantiatedObject.transform.forward * distance;
}
}
Ideally these could be moved closer to the pillar
Due to the fact your code already points the object towards where you are trying to get closer, you need only move the object forward until its at the correct distance.
Decreasing the value of the radius variable should spawn them closer to the pillar.
Since you are offsetting the cube position from the pillar position by the cosine and sine components of the radius, it will place them correctly spaced around the pillar.
Also, I believe
float angle = i * Mathf.PI * 2f / radius;
Should really be
float angle = i * Mathf.PI * 2f / amount;
The radius should not affect the angle the object is spawned, but the number of objects should.

Unity - Projectile Motion, find the angle needed to hit coordinates x,y

Plenty of questions asked around the same topic, but nothing seems to be working for me.
The problem is simple, a player and an enemy are on the x,y plane. I want to launch my projectile at a calculated angle in such way that the projectile will hit the enemy at it's coordinates.
I've tried implementing both
Angle of Reach and Angle required to hit x,y
Both of these implementation end up doing the same for me; Shooting but not hitting the target in this manner
Any help or pointers would be much appreciated! Thank you
Here is the code:
public Rigidbody projectile;
public float projectileSpeed;
public float Firerate = 9f;
private float nextfire;
private GameObject enemy;
private float gravity = Physics.gravity.y;
private Vector3 directionalVector;
// Start is called before the first frame update
void Start()
{
enemy = GameObject.FindGameObjectWithTag("enemy");
}
void Update()
{
directionalVector = enemy.transform.position - transform.position;
}
void FixedUpdate()
{
nextfire = Time.time + (1 / Firerate);
float projectileSpeed2 = projectileSpeed * projectileSpeed;
float projectileSpeed4 = projectileSpeed2 * projectileSpeed2;
float x = enemy.transform.position.x;
float y = enemy.transform.position.y;
float x2 = x * x;
float theta = Mathf.Atan(projectileSpeed2-Mathf.Sqrt(projectileSpeed4-gravity*(gravity*x2+2*y*projectileSpeed2))/gravity*x);
print(theta);
Vector3 releaseVector = (Quaternion.AngleAxis(theta, Vector3.up) * directionalVector).normalized;
Debug.DrawRay(transform.position, releaseVector, Color.red,0.5f);
Rigidbody instantiatedProjectile = Instantiate(projectile, transform.position, transform.rotation) as Rigidbody;
instantiatedProjectile.velocity = releaseVector * projectileSpeed;
}
}
Why not avoid the problem of finding the angle, and just move the bullet based on the direction on where it first saw the enemy.
(target.transform.position - transform.position).normalized;
It will return a Vector direction to the target.
When the projectile moves, just move it based on this direction.
No headache needed in calculating angles :)
Edit
I made a function before to 'convert' an angle to direction:
protected Vector2 DetermineBulletMoveDirection(float shootingAngle) {
// Determine the direction of the bullet travel on the x and y axis.
float bulletDirectionX = transform.position.x + Mathf.Sin((shootingAngle * Mathf.PI) / 180);
float bulletDirectionY = transform.position.y + Mathf.Cos((shootingAngle * Mathf.PI) / 180);
// Determines the direction this bullet should be moving.
Vector2 bulletDirection = new Vector2(bulletDirectionX, bulletDirectionY);
return (bulletDirection - (Vector2)transform.position).normalized;
}
It takes in an angle, and converts it into a direction based on where the shooter is currently at.
The angle should start from Vector.down, and rotates clockwise.
The next problem is to find out the angle between you and the enemy.
This is the simplest solution I could think of, here is a diagram first:
Notice that you can use TOACAHSOH on this?
So all you have to do, is to 'virtually' align the Y axis of the shooter to the origin.(Apply the movement to the shooter too!)
Do the same thing for the shooter, but on the x-axis this time.
And you would be able to achieve that state where you have a triangle with a 90-degree.
From there on, you can calculate the angle to rotate from Vector.down to the enemy.
Just make sure you move both of the objects back to it's initial position.
After fighting this for a while I found a solution.
In the end I ended up using the Angle of Reach. The second error was that Mathf.Atan returns radians and not degrees, while Quantion.AngleAxis takes in angles. The third and the final one was the fact that Unity uses left hand coordinate system as opposed to the usual right hand system which I was used to.
Here is the final piece of code:
public class TargetAndShoot : MonoBehaviour
{
public Rigidbody projectile;
public float projectileSpeed;
public float firerate;
private float nextfire;
private GameObject enemy;
private float gravity = Physics.gravity.y;
// Start is called before the first frame update
void Start()
{
enemy = GameObject.FindGameObjectWithTag("enemy");
}
void Update()
{
if (Time.time >= nextfire)
{
nextfire = Time.time + (1 / firerate);
float distance = enemy.transform.position.x - transform.position.x;
Vector3 directionalVector = enemy.transform.position - transform.position;
float v2 = projectileSpeed * projectileSpeed;
float v4 = v2 * v2;
float x = enemy.transform.position.x;
float x2 = x * x;
float y = enemy.transform.position.y;
float theta = 0.5f*Mathf.Asin((gravity * distance) / (projectileSpeed * projectileSpeed));
Vector3 releaseVector = (Quaternion.AngleAxis(theta * Mathf.Rad2Deg, -Vector3.forward) * directionalVector).normalized;
Debug.DrawRay(transform.position, releaseVector*5, Color.cyan, 0.5f);
Rigidbody instantiatedProjectile = Instantiate(projectile, transform.position, transform.rotation) as Rigidbody;
instantiatedProjectile.velocity = releaseVector * projectileSpeed;
}
}
}

Unity: Faux Gravity - inner Capsule/ Cylinder

I'm struggling with false Gravity in a Cylinder or Capsule. Basically I thought I could take the same Code as for spherical gravity, which does not work. So I changed some lines to get a better result.
[SerializeField] float gravity = 10;
public void Attract ( Transform target )
{
Vector3 gravityUp = (target.position - new Vector3(transform.position.x, transform.position.y,target.position.z)).normalized;
Vector3 bodyDown = -target.up;
Rigidbody rb = target.GetComponent<Rigidbody>();
rb.AddForce(gravityUp * gravity);
Quaternion targetRotation = Quaternion.FromToRotation(bodyDown, gravityUp) * target.rotation;
targetRotation.x = 0;
target.rotation = Quaternion.Slerp(target.rotation, targetRotation, 30.0f * Time.deltaTime);
}
This worked OK on the first try. But the Player(target) can't rotate one the Y-Axis. Does anyone have any ideas?
OK, I tried the following.
Quaternion targetRotation = Quaternion.FromToRotation(bodyDown, gravityUp) * target.rotation;
targetRotation.x = 0;
target.rotation = Quaternion.Slerp(target.rotation, targetRotation, 30.0f * Time.deltaTime);
Now I use the Surface normal to rotate the Player.
if (Physics.Raycast(attractedBody.transform.position + attractedBody.transform.forward, -attractedBody.transform.up, out hit, distance))
{
surfaceNorm = hit.normal;
}
But without Rigidbody Contrains the Player starts rotating without any Input. So I have to use:
rb.constraints = RigidbodyConstraints.FreezeRotation;
This works.

Check if the camera is focused on a sprite

I am writing a Cardboard game in Unity and I want to check whether my camera is facing a sprite or not. I have written the following code:
private void GetSphericalCoordinates(Vector3 vector, out float tetta, out float fi)
{
float r = Mathf.Sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
tetta = Mathf.Acos(vector.z / r);
fi = Mathf.Atan2(vector.y, vector.x);
}
public bool IsLookingAtMe(Vector3 point, Quaternion angle)
{
Vector3 topLeftPoint = new Vector3(transform.position.x - transform.localScale.x / 2, transform.position.y - transform.localScale.y / 2);
Vector3 topRightPoint = new Vector3(transform.position.x + transform.localScale.x / 2, transform.position.y - transform.localScale.y / 2);
Vector3 bottomLeftPoint = new Vector3(transform.position.x - transform.localScale.x / 2, transform.position.y + transform.localScale.y / 2);
Vector3 bottomRightPoint = new Vector3(transform.position.x + transform.localScale.x / 2, transform.position.y + transform.localScale.y / 2);
float topLeftTetta, topRightTetta, bottomLeftTetta, bottomRightTetta, lookTetta;
float topLeftFi, topRightFi, bottomLeftFi, bottomRightFi, lookFi;
GetSphericalCoordinates(topLeftPoint - point, out topLeftTetta, out topLeftFi);
GetSphericalCoordinates(topRightPoint - point, out topRightTetta, out topRightFi);
GetSphericalCoordinates(bottomLeftPoint - point, out bottomLeftTetta, out bottomLeftFi);
GetSphericalCoordinates(bottomRightPoint - point, out bottomRightTetta, out bottomRightFi);
lookTetta = angle.eulerAngles.x * Mathf.Deg2Rad;
lookFi = angle.eulerAngles.y * Mathf.Deg2Rad;
if (lookTetta >= topLeftTetta && lookTetta <= bottomRightTetta)
return true;
return false;
}
In my code I find the 4 angles of my sprite, which is a square, so I have 5 points which make a pyramid. Now I need to check whether my camera is inside my pyramid or not.
The problem is, my lookTetta and lookFi never goes inside my pyramid. I just checked the Tetta only.
Please help me with it.
Using WorldToViewportPoint it should be a single statement. No need to deal with viewing cones manually.
Project the sprite world position to viewport position, then lookup if it is within bounds (ignoring z).
public bool IsMainCameraLookingAtMe()
{
Bounds viewportBounds = new Bounds.SetMinMax(Vector2.zero, Vector2.one);
return viewportBounds.Contains((Vector2)Camera.main.WorldToViewportPoint(transform.position));
}
May check each sprite corner individually to fit your needs.
I have used IntersectRay using the code below:
public bool IsLookingAtMe(Vector3 origin, Vector3 direction)
{
Bounds bounds = GetComponent<Renderer>().bounds;
Ray ray = new Ray(origin, direction);
return bounds.IntersectRay(ray);
}