I've tried Atan2, I've tried whatever is euler angles, I've tried everything Unity3d's site, and I get three results:
I can move my mouse slowly, I can move it at the speed of light, the rotation of the player is fixed, either looking up, or down.
The player rotates, not looking at the mouse though. It's as though it's doing it's own thing.
It rotates on anything but the z axis.
I'm completely out of ideas, completely out. I've tried everything, including downloading several slither.io knockoff projects to figure out how they accomplish the task, but none of them work.
If you're having trouble grasping what I need to achieve, well, I have no code at this moment. But there's a website with the same thing I'm trying to accomplish.
Play surviv.io Look at how the player rotates in accordance with the mouse. That's what I'm trying to accomplish.
I didn't test this, but....
The code below should work if you have a background screen that can be raycasted against so the ray collides with it. Then play around a bit with the coordinates in the Transform.LookAt().
Basically it does these steps.
1 - Fire a ray from the screen to the mouse position, save a reference to whatever is hit in the 'Hit' variable.
2 - If anything was hit, rotate the players transform to look where it hit.
public LayerMask RaycastCollidableLayers;
public RaycastHit Hit;
public float CheckDistance = 200f;
public Transform Player;
void PerformRaycast(){
//Set up ray
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//Fire ray
Physics.Raycast(ray, out Hit, CheckDistance + 0.1f, RaycastCollidableLayers);
if (Hit.collider == null)
{
//Debug.Log("Raycast hit nothing");
return;
}
else //Ray hit something
{
//Look at Hit.point on x and y axes.
Player.LookAt(new Vector3(Hit.point.x, Hit.point.y, 0f), Vector3.up); //Ignoring z axis, may need to be another axis. Vector3.up sets the up direction.
}
}
Sources:
Transform.LookAt: https://docs.unity3d.com/ScriptReference/Transform.LookAt.html
Camera.ScreenPointToRay: https://docs.unity3d.com/ScriptReference/Camera.ScreenPointToRay.html
Let me know how it works for you.
Related
I am trying to freeze the position of a GameObject towards the z-Axis but when turning the GameObject the z-Axis should turn with it (or atleast the freeze Position)
So basically I want my object to only be able to move forward, backwards and up and down, no matter what direction it is facing.
A RigidBody freeze Position is in relation to the world axis and not the rotated axis of the object.
Appreciate the help, thank you
Top Down View of Object, before rotation and after
You can get the GameObject's "z-axis" with transform.forward. If this isn't the axis you want, try transform.right or transform.up.
It's unclear what you're asking for. Here are two cases that might answer your question:
To confine velocity to the "z-axis":
//reference to the Rigidbody to restrict
private Rigidbody rig;
void Start(){
//find the Rigidbody attached to this GameObject
rig = GetComponent<Rigidbody>();
}
//Updates every physics frame
void FixedUpdate(){
//set the velocity to the component of the velocity that is parallel to the forward direction
rig.velocity = transform.forward * Vector3.Dot(transform.forward, rig.velocity);
}
If you don't want any movement in the "z-axis", replace the rig.velocity = ... line with rig.velocity -= ...
Put this code in a MonoBehaviour (script) attached to your GameObject.
Note that if the GameObject is physically hit, it might spin, causing the "z-axis" to rapidly change. To prevent this, you could use the Rigidbody freeze rotation.
Some background: My camera is set to a position of 5 in the y axis and -10 in the z axis with a rotation of 22.5.
Does the position and rotation of the camera affect how accurate the raycasting behaviour will be? I ask because there are clickable objects in my scene which detect if they've been clicked on, and it more or less works. I mean it works, but it's not perfect.
If I click somewhere on the object, it's likely to register the click, but if I go to test the boundaries, something interesting occurs. There is an area of several pixels under the object which registers a click even though it isn't physically a part of the object. Likewise, there is an area of several pixels on the top of the object (within the object) which does not register a click even though it is a part of the object. Does this have something to do with the angle formed by the ray between the camera and the screen point? My project is more or less bare, so I'm pretty certain that the issue must be caused by the camera's transform and my click script which is really simple at the moment.
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.transform == gameObject.transform)
{
Debug.Log(gameObject.name);
}
}
}
}
I'm trying to create a Pong clone for practice. I setup my project in 2D.
The paddle has the following components:
-Rigidbody2D (set to kinematic)
-BoxCollider2D (is a trigger)
The ball has the following components:
-Rigidbody2D (set to kinematic)
-CircleCollider2D (is a trigger)
The paddle is controlled via dragging (user dragging finger on screen left/right). I used the EasyTouch plugin for this.
Then I move the ball with this script:
void Update () {
transform.position += new Vector3(xSpeed * Time.deltaTime, ySpeed * Time.deltaTime);
}
This is how I detect collisions and redirect the ball once it hits something (Horizontal objects are the top/bottom/paddle while Vertical objects are the left/right screen border):
void OnTriggerEnter2D(Collider2D c)
{
if(c.gameObject.tag.Equals("Horizontal"))
{
ySpeed *= -1;
}
else if(c.gameObject.tag.Equals("Vertical"))
{
xSpeed *= -1;
}
}
The problem is sometimes the ball goes through the paddle which can look glitchy to the end-user. I've searched about this online and I've tried to set the rigidbody's Collision Detection property to Continuous instead of Discrete. But the ball still goes through the paddle at certain times.
Anyone know how to solve this? What am I doing wrong with how I setup/coded my game?
Thanks
You have a very simple concept error.
OnTriggerEnter2D(Collider2D) is to get if the collider has entered other collider. In other words you can go through the object.
you need to use this function instead:
OnCollisionEnter2D(Collision2D coll)
I suggest you to watch this Unity tutorial because it explains all this really good: https://unity3d.com/learn/tutorials/modules/beginner/physics/colliders
Additional info : http://docs.unity3d.com/ScriptReference/Collider2D.html
Thanks.
As the code shows, the transform is controlled by yourself while the continuous detection requires control of physics engine, so try to control the gameObject with physics engine instead give it a position modified by your own code.
I am creating a 3rd person action game where the player is a helicopter and he can shoot other objects while moving. The problem is I am trying to find the enemy objects who are inside a circle in the center of the camera and I need to track them and shoot them.
Raycast wouldn't help as i need a thicker raycast and so I tried spherecast and capsulecast.
I have a GUI element which gives the player idea on where he can shoot.When using Spherecast or Capsulecast, It is working when the enemy is near but when the enemy is far behind I guess the spherecast becomes small while traveling along z and doesn't hit the object most times.
if (Physics.SphereCast (startPoint, 1f, transform.forward, out hit)) {
if (hit.collider.CompareTag ("Shootable") ){
Debug.Log(hit.collider.name);
Destroy(hit.collider.gameObject);
}
}
I have seen raycast from camera and so i was wondering if there is something to do like circlecast from the camera which would be appropriate for this. If not how can I proceed?
Any help is really appreciated.
If you want to detect whether enemies lie within a conical area in front of your camera, using a SphereCast or RayCast will not be able to meet your needs.
Instead, you might consider checking the angle between an enemy's relative position and your camera's forward vector, to see if it is below a particular value, and hence within the cone.
For a 60-degree field of view, and assuming you store your enemy Transform components in an array/List, your code might look like:
foreach (Transform enemy in enemies){
if (Vector3.Angle(transform.forward, enemy.position - transform.position) < 30){
Destroy(enemy.gameObject);
}
}
Hope this helps! Let me know if you have any questions. (Answer adapted from this Unity question.)
Looking at various bulletin boards, this is a common problem, yet I could not find any good answers online.
My project has a first-person car that moves via the arrow keys. I want a gun mounted on the car to be able to shoot via crosshair that can aim anywhere on the current screen. Right now the bullets just shoot right through the middle all the time, except for the times when I click on the screen and nothing happens (which is about 50%). Here is the code which I got via various scripts on the web:
var speed = 20;
var bullet: GameObject;
function Update () {
var hit : RaycastHit;
if(Input.GetButtonDown("Fire1")){
var ray = Camera.main.ScreenPointToRay (Input.mousePosition); //ray from
// through the mousePosition.
if(Physics.Raycast(ray, hit, 1000)) { //does the ray collide with
// anything.
//add stuff here for finding type of object and such.
Debug.Log("Hit Something at mouse position");
Debug.DrawRay (ray.origin, ray.direction * 10, Color.yellow);
//Display the ray.
var projectile:GameObject = Instantiate(bullet,transform.position,transform.rotation);
projectile.rigidbody.velocity = transform.forward * speed;
}
}
}
If anyone could help, it would be very much appreciated.
Your ray is correct (pointing to middle of screen), but it has nothing to do with the way your making the bullet travel. The bullet travels based on a transform.forward * speed. What you need to do is get the hit point of your ray, then get a direction from your bullets origin to that point.
Vector3 direction = hit.point - projectile.transform.position;
projectile.rigidbody.velocity = direction * speed;
1000 is pretty low for a screenPointToRay, so you might want to up that by a lot if you want to avoid future problems.
Also rigidbody has been deprecated, im not sure if you should be doing a (GameObject).rigidbody directly like that
http://docs.unity3d.com/ScriptReference/GameObject-rigidbody.html
Without actually posting you any code, I can tell you that what you should probably be looking into is why your projectile is setting its rotation from the transform's rotation instead of the rotation of your ray if I understand your attempt.
The projectile is clearly gaining all of it's properties (including those which are supposed to be detached from the origination) from the vehicle and just following along accordingly.
Try setting your projectile's rotation to that of your ray.
Also, your ray is more than likely only ever hitting half of the time because of your amount of distance to test. Try upping that number, or creating walls for it to collide with at shorter range.