Check if the camera is focused on a sprite - unity3d

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);
}

Related

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

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)

find the heading angle between 2 objects taking into account the forward angle of the initial object

Ok, so, i've been stuck on this for ages. Im working on an AI that will navigate a tank to a waypoint, defined as a Vector3. the position of the tank is also defines as a Vector3, both these have their Y position set to 0, as to ignore terrain elevation, the current rotation of the tank is also a Vector3, though only the Y rotation is needed, as i'm effectively projecting the 3d position onto a 2d navigational grid.
The AI passes anywhere between -1 and 1 into the control for the tank, which then handles the physics operations. so, i need to somehow calculate the angle, positive or negative in relation to the current heading angle of the tank to the position of the waypoint, then send the rotation value to the controls. At the moment I simply cant get it working, I feel like iv'e pretty much tried everything.
This is my code currently, it doesn't work, at all, and is about the 20th revision:
void driveToTarget()
{
Vector3 target0 = driveTarget;
target0.y = 0;
GameObject current0Obj = new GameObject();
Vector3 current0 = this.transform.position;
current0.y = 0;
print(current0);
print(target0);
Vector3 current0Angle = this.transform.eulerAngles;
print(current0Angle.y);
current0Angle.x = 0;
current0Angle.z = 0;
Vector3 heading = target0 - current0;
Quaternion headingAngle = Quaternion.LookRotation(heading);
print("headingAngle" + headingAngle);
print("heading direction, allegidly: " + Quaternion.Euler(heading).ToEulerAngles());
Quaternion distanceToGo = Quaternion.Lerp(Quaternion.Euler(current0Angle), headingAngle, 0.01f);
float angle = Vector3.SignedAngle(current0, target0, Vector3.up);
float difference = Mathf.Abs(angle - current0Angle.y);
print("heading angle " + angle);
if (current0 != driveTarget)
{
steeringVal = Mathf.Abs(1.5f-(1f/Mathf.Abs(distanceToGo.y))) * -Mathf.Sign(distanceToGo.y); ;
throttleVal = 0f;
} else
{
throttleVal = 0;
}
}
--EDIT--
So, I've partially solved it, and now encountered another problem, I've managded to get the tank to detect the angle between itself and the waypoint, BUT, rather than orienting forward towards the waypoint, the right side of the tank orients towards it, so it orbits the waypoint. I actually know why this is, becasue the forward vector of the tank is technically the right vector because of unity's stupid axis ruining my blender import, anyway, heres the updated code:
void driveToTarget()
{
Vector3 target0 = driveTarget;
target0.y = 0;
Vector3 current0 = this.transform.position;
current0.y = 0;
print("Current: " + current0);
print("Target: " + target0);
Vector3 current0Angle = this.transform.rotation.eulerAngles;
print("Curret rotation:" + current0Angle.y);
current0Angle.x = 0;
current0Angle.z = 0;
Vector3 heading = target0 - current0;
Quaternion headingAngle = Quaternion.LookRotation(heading);
print("heading angle: " + headingAngle.ToEuler());
float distanceToGo = (current0Angle.y) - headingAngle.eulerAngles.y;
print("DistanceToGo: " + distanceToGo);
if (current0 != driveTarget)
{
steeringVal = 1 * -Mathf.Sign(distanceToGo);
throttleVal = 0f;
} else
{
throttleVal = 0;
}
Debug.DrawRay(current0, heading, Color.red, 1);
Debug.DrawRay(current0, this.transform.up, Color.red, 1);
}
I'm not sure exactly how your code is setup or how the steering works. You may want to look into using the Unity NavMeshAgent to simplify this.
Regardless here is some code I wrote up that takes a destination and rotates an object towards it. All you'd have to do from there is move the object forwards.
Vector3 nextDestination = //destination;
Vector3 direction = nextDestination - transform.position;
direction = new Vector3(direction.x, 0, direction.z);
var newRotation = Quaternion.LookRotation(direction);
var finalRotation = Quaternion.Slerp(transform.rotation, newRotation, Time.deltaTime); //smoothes out rotation
transform.rotation = finalRotation;
Sorry if this isn't what you needed. Have you been able to figure out which part of the code is behaving unexpectedly from your print statements?

Unity 2D Launch object twards mouse at consistent speed regardless of distance to object

I have an object that I would like to be 'launched' at the mouse position, but depending on the distance of the mouse to the object, the speed will change.
I need a consistent launch speed regardless of distance.
_destination is the mouse position
public void GoToDestination(Vector3 _destination)
{
//Vector3 rotation = Vector3.
//Debug.Log(" :" + _destination.x + " " + _destination.y);
//Debug.Log("Norm:" + _destination.normalized.x + " " + _destination.normalized.y);
//Vector3 diff = _destination - transform.position;
//Vector3 flippedDest = new Vector3(diff.x, diff.y, 0);
//rb.AddForce(flippedDest * speed);
//Debug.Log(rb.velocity);
//_destination.y = -_destination.y;
//_destination = (_destination - transform.position).normalized;
//rb.velocity = Vector3.Cross(transform.position, _destination) * speed;//(_destination.normalized - transform.position.normalized) * speed;
//rb.AddForce(_destination * speed);
//destination = _destination;
rb.velocity = (_destination - transform.position).normalized * (speed);
//destination = _destination;
}
If I understand you correctly you want to use distance as a variable for your speed calculation.
I assume this script run on a launched object.
First thing:
//distance between launched object(transform.position) and mouse position(destination).
float dist = Vector3.Distance(transform.position, destination.position);
You can calculate distance on every frame or whatever you want
Then:
You have dist variable as a float now . For example if you want to slowdown object when distance become smaller, you can simply multiply with dist like that.
The solution was to convert all Vector3's to Vector2's. The z axis was causing problems.

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.

Gameobjects position change with resolution

I have a scene with multiple GameObjects with x-y-z position. I'm in 2D so the z is not used.
For now, I worked with the resolution 1024/768 and when I add a GameObject like :
GameObject star = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Vector3 position = new Vector3 (x, y, z);
star.transform.localPosition = position;
It's ok, the GameObject is in the right position on my scene.
But nox, I'm trying to change the resolution (1920/1080) and all my GameObjects are moved far on the top right, out of my camera.
What's the problem ? How can I fix this ?
For me, when I change the resolution, the 0-0-0 change for my GameObjects....and something weird, If my GameObject has a LineRenderer with positions, they are good on all resolutions...
Edit : This is the function I use for generate my GameObjects, it's a galaxy generator :
for(int i = 0; i < numberOfStars; i++) {
bool checkPosition = false;
while (!checkPosition) {
// Choose a distance from the center of the galaxy.
float distance = Random.Range(5.0f, (float) galaxySize / 2 - 5);
// Choose an angle between 0 and 2 * PI.
float angle = Random.Range(0.0f, 100.0f) * 2 * Mathf.PI;
Vector3 position = new Vector3 (Mathf.Cos (angle) * distance, Mathf.Sin(angle) * distance, 9);
if (! Physics.CheckSphere(position, 1)) {
GameObject star = GameObject.CreatePrimitive(PrimitiveType.Sphere);
star.AddComponent<SolarSystem>();
star.name = i + "_" + PlanetNameGenerator.GenerateName();
star.GetComponent<SolarSystem>().name = i + "_" + PlanetNameGenerator.GenerateName();
star.transform.parent = GameObject.Find ("Targets").transform;
// On change le scale en random
float randomScale = Random.Range (0f, 0.5f);
star.transform.localScale += new Vector3(randomScale,randomScale,randomScale);
star.transform.localPosition = position;
star.tag = "SolarSystem";
checkPosition = true;
}
}
}
This is the scene I see in 1024/768, with my Sphere GameObjects and in pink LineRenderer between them :
This is what I see in 1920/1080, LineRenderer are always in the same position, but GameObjects move away :
The problem was this line :
star.transform.parent = GameObject.Find ("Targets").transform;
I moved the parent out from Canvas, chnage x-y-z positions of "Targets" to 0 et it's ok.