How do I set the view angle of a sphere cast and also read the angle at which the objects are present in front of it? - unity3d

this is what i want to achieve
I am currently trying to build a RADAR sensor on unity. I am currently using spherecast. How do i set the view angle of the sphere cast and also how do i read the angle at which an object is present in front of it.
What i have used now is Vector3.angle but this shows 160 degrees if the object is directly infront of the radar instead it should be showing 90 degrees.
Ill paste the code that i have implemented below
Any guidance is appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spherecast : MonoBehaviour
{
Rigidbody rb;
public List<GameObject> CurrentHitObjects = new List<GameObject>();
//public GameObject curobject;
public float radius;
public float maxdist;
public LayerMask layermask;
public float velocity;
public Time deltatime;
public Vector3 previous;
private Vector3 origin;
private Vector3 direction;
private float hitdist;
// Use this for initialization
void Start()
{
foreach (GameObject cur in CurrentHitObjects)
{
previous = cur.transform.position;
}
}
// Update is called once per frame
void Update()
{
origin = transform.position;
direction = transform.forward;
hitdist = maxdist;
CurrentHitObjects.Clear();
RaycastHit[] hits = Physics.SphereCastAll(origin, radius, direction, maxdist, layermask, QueryTriggerInteraction.UseGlobal);
foreach (RaycastHit hit in hits)
{
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
if (GeometryUtility.TestPlanesAABB(planes, hit.collider.bounds))
{
float angle = Vector3.Angle(transform.forward, hit.point.normalized);
float degree = Mathf.Acos(angle) * Mathf.Rad2Deg;
Vector3 pos = hit.point;
Debug.Log(hit.collider.name + "position =" + pos);
CurrentHitObjects.Add(hit.transform.gameObject);
hitdist = hit.distance;
Debug.Log(hit.transform.name + "Distance ="+ hitdist);
Debug.Log(hit.collider.name + "Angle = " + angle);
velocity = ((hit.transform.position - previous).magnitude) / Time.deltaTime;
previous = hit.transform.position;
Debug.Log(hit.transform.name + "Velocity =" + velocity);
}
else
{
return ;
}
}
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Debug.DrawLine(origin, origin + direction * hitdist);
Gizmos.DrawWireSphere(origin + direction * hitdist, radius);
}
}

As far as I can tell your code doesn't do anything. My first tip would be to remove all of your commented out code, but after that here is why your code does nothing at all:
You pass an array of objects to your script. Fine so far.
You take this entire array of objects 'CurrentHitObjects' and pass the transform.position of every single object to a single vector3. This means that all the values are overwritten except for the last one. This would be a big problem if you were trying to find the position of every single object. This would instead require vector3[]. But there is another bigger problem.
'previous', which holds transform.position of the objects is not used anywhere. So you are not actually finding the location of anything.
You use start() (which only runs once by the way) to iterate through your object array, but then you clear, CurrentHitObjects.Clear();, right at the beginning of update() (which runs many times per second by the way). The problem here, is that if you hoped to use CurrentHitObjects for anything in your code, you can't because you have wiped it before you even start doing anything with it.
Your raycast[] is shooting towards nothing. Seems to me like it just shoots forward.
You are finding the angle between the forward direction and the forward direction?
Honestly there are a lot of major problems with this code. I don't mean to be harsh, but it looks like you copy and pasted someone else's code and don't know how to use it. This needs a complete rework. If you know how to code I would throw it out and start over again. See my comment on your answer for a better way to do what you want.
If you don't know how to code, you should not be asking for freebie working code on stackoverflow. Try a unity forum instead. If you are trying to get better, see my above comments.

Related

How do i make a stickman's arms reach out to the mouse cursor?

Stickman
I have this stickman here in unity 2D and i want his arms to always reach out to the direction of the mouse. I have no ideas on where i should start and i'm hoping someone here could help me out. Thanks!
Foremost, you need to determine the mouse position. It can be done with the following method:
public Vector3 GetMouseWorldPosition()
{
Vector3 mouseScreenPosition = UnityEngine.Input.mousePosition;
Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(mouseScreenPosition);
return mouseWorldPosition;
}
I use Camera.main here for demonstration purposes. In sake of performance it will be better to cache it as a field in your class.
Now, when you have the target coordinates, you can rotate the hand. Here is an example method:
public void RotateLimb()
{
Vector3 rotationTargetPosition = GetMouseWorldPosition();
Vector3 directionVector = (rotationTargetPosition - _limb.transform.position).normalized;
float angleInRad = Mathf.Atan2(directionVector.y, directionVector.x);
Vector3 targetAngle = _limb.transform.eulerAngles;
targetAngle.z = angleInRad * Mathf.Rad2Deg;
_limb.rotation = Quaternion.Euler(targetAngle);
}
Method RotateLimb() can be called in Update or a coroutine.
All the variables of this method can also be stored as private fields in your class.
_limb must contain Transform of your hand GameObject and you can assign it as SerializeField
[SerializeField] private Transform _limb;
_limb will rotate around its pivot. Therefore, pivot must be in the center of the shoulder. In order to achieve it, you can place all the graphics of your hand as a child of _limb and adjust it accordingly.
This seems like the most straightforward way to do it.

turning towards an object in Unity

Good times. How do I implement the NPC rotation towards the selected object?
public GameObject BufferObject;
public float MoveSpeed = 1f;
void Update()
{
float step = MoveSpeed * Time.deltaTime;
transform.position = Vector2.MoveTowards(transform.position, BufferObject.transform.position, step);
}
Here is the script for moving the NPC to the selected object (Buffer Object) and the movement works perfectly, but the implementation of the rotation causes Me difficulties, please advise.
For Unity2D.
Simply get the desired direction
var direction = (BufferObject.transform.position - transform.position).normalized;
and then the desired rotation using Quaternion.LookRotation like e.g.
var targetRotation = Quaternion.LookDirection(direction);
Then either apply it directly if you want it immediately
transform.rotation = targetRotation;
Or if you want it smooth you could use e.g. Quaternion.RotateTowards like
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, anglePerSecond * Time.deltatime);
Have in mind though that it might look awkward if the rotation is too slow since your NPC could move back/sidewards already while still not fully looking towards the target ;)
So you might want to wait until
if(Quaternion.Angle(targetRotation, transform.rotation) <= certainThreshold)
{
... your movement code
}
So the answer and the solution from Me, albeit stupid, but working. In order to reflect the sprite, you need to get a variable, either 1 or -1 (For Scale). This code will show the distance from one NPC to the object:
BufferObject.transform.position.x - transform.position.x
And here I get a lot of values as if to the left of the NPC, then -x... , and if to the right, then x... thereby it is possible to determine which side of the object, so also level the value from here (Optional) to 1 or -1 and apply this result to transform.localScale and thereby solve the problem of how to reflect (Rotate the sprite) towards the object. Use it for your health :)
Complete code:
float localPositionAmount = BufferObject.transform.position.x - transform.position.x;
if (localPositionAmount >= 1)
{
gameObject.transform.localScale = new Vector3(1, transform.localScale.y, transform.localScale.z);
}
if (localPositionAmount <= -1)
{
gameObject.transform.localScale = new Vector3(-1, transform.localScale.y, transform.localScale.z);
}
if (localPositionAmount == 0)
{
gameObject.transform.localScale = new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z);
}
Yes, the code is the simplest and without enumerations and other things, but it works perfectly. I still had to figure it out myself...

How to make a player only move in 1 direction (Unity)

I am trying to create a game in Unity where the player can only move in the direction it is facing, but the following code allows the player to move in all 4 directions.
(This is for a 3D project)
Any help would be appreciated! Thanks!
public class PlayerController : MonoBehaviour {
public float speed;
private Rigidbody rb;
void Start() {
rb = GetComponent<Rigidbody>();
}
void FixedUpdate() {
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
rb.AddForce(movement * speed);
}
}
So I didn't get what you wanted: first you said you wanted it to move only forward, then the only thing you have to do is get when he pressed a key and move forward while is not unpressed.
If you wanted to say that it can move all directions BUT only one at a time, the you will have to put the same code but with some changes:
First of all to make it move forward you have to get the forward of the transform, otherwise it will move in the same direction if you rotate it (you don't want that, no?).
Vector3 moveDirection = (transform.forward * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal")).normalized;
moveDirection.y = 0;
rb.velocity = moveDirection;
Then, to make that it ONLY moves to one direction at a time, you have to put the priority of the greatest axis number and if it's equal then you should think if you want to move forward or right (with it's axis value).
From the code you posted, I'm not sure where you are storing the player's facing-direction. However, I presume that it is stored as a Quaternion. If you have a player rotation quaternion called playerRotation, then you could do this (warning - untested):
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 normal = playerRotation * Vector3.forward;
Vector3 movement = Vector3.Dot(normal, input) * input;
If the game is first-person, then you can take a shortcut and just use Camera.current.transform.forward instead of the normal vector.
This will project the input direction onto the normal with the player's facing direction so that your movement force can only be in that direction.

RigidBody moving automatically to upper left in Space Shooter tutorial

I am following the space shooter tutorial on Unity website.
I have completed upto movement actions of the player object.
When I start my game, the spaceship automatomatically moves to the upper left corner even when no input is given.
I have followed the tutorial exactly as it is. Even the completed scene that is available in the Asset Store is having the same problem.
I am using Unity 5.3.
PlayerController.cs
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float xMin, xMax, zMin, zMax;
}
public class PlayerController : MonoBehaviour {
public float speed;
public Boundary boundary;
public float tilt;
// Use this for initialization
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
GetComponent<Rigidbody>().velocity = movement * speed;
GetComponent<Rigidbody>().position = new Vector3(
Mathf.Clamp(GetComponent<Rigidbody>().position.x,boundary.xMin, boundary.xMax),
0.0f,
Mathf.Clamp(GetComponent<Rigidbody>().position.z, boundary.zMin, boundary.zMax));
GetComponent<Rigidbody>().rotation = Quaternion.Euler(0,0, GetComponent<Rigidbody>().velocity.x * -tilt);
}
}
Your code seems correct and since you say that the demo scene does the same, I suppose that the problem comes from your Axis input: The lines taht add movement
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Uses the Axes called Horizontal and Vertical. It is possible that on your instance of unity, these input are linked to a device that sends events (you maybe have a controller plugged...)
To test this, You can add the following line below reading the input:
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Debug.Log("Movement: " + moveHorizontal + ", " + moveVertical); // <-- add this
This will write the values you get as input. If you don't touch anything, they should be zero. If they are not zero, Go to Edit -> Project Settings -> Input, You will see how your keyboard, mouse and other controllers are linked to events in Unity such as Horizontal and Vertical
See http://docs.unity3d.com/Manual/class-InputManager.html for more info on Input Manager
Good luck!

Firing on both side Unity 2D

I am trying to make a 2D platformer but my player is not firing on both side I don't know what is wrong with my script.
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour
{
public float bulletSpeed;
public GameObject bullet;
public Transform bulletX;
GameObject clone;
void Update ()
{
if (Input.GetKeyUp ("space"))
{
clone = Instantiate(bullet,new Vector3(bulletX.position.x,bulletX.position.y+0.1f,0f),Quaternion.identity) as GameObject;
if (GameObject.Find ("Player").GetComponent<Player> ().left == true)
bulletSpeed = -30f;
else
bulletSpeed = 30f;
}
bullet.rigidbody2D.velocity = new Vector2(bulletSpeed * 0.5f, 0f);
Destroy (clone, 1f);
}
}
I tried to increase velocity inside the if condition but bullet was moving faster than I needed.
I think your question was very hard to understand what you want to accomplish, but I can see some errors in your code that will render the "clone" you are creating, useless.
The update loop is continuously executing, and you have placed the destroy outside your "Press space" code block. Unity tries to destroy it every frame. Place it inside the space.
I feel it should look more like this:
if (Input.GetKeyUp ("space"))
{
clone = Instantiate(bullet,new Vector3(bulletX.position.x,bulletX.position.y+0.1f,0f),Quaternion.identity) as GameObject;
if (GameObject.Find ("Player").GetComponent<Player> ().left == true)
bulletSpeed = -30f;
else
bulletSpeed = 30f;
bullet.rigidbody2D.velocity = new Vector2(bulletSpeed * 0.5f, 0f);
Destroy (clone, 1f);
}
This might not answer your question, but could you specify more what behaviour you are after? And what object is this script running on? (It is called Bullet with a field referance to another bullet ?)
Debug.Log your bulletSpeed * 0.5f
If I am correct. Even if your Player is Looking at the other way. It is returning
an ABS number meaning (bulletSpeed = -30f & 0.f is != -44954 something but == 44954).
Alternatively you can use AddForce instead of Velocity. It is easier to control.
QUESTION. Why not use Instantiate Vector2?