I'm making an FPS game, but the bullets are not hitting in the right spot sometimes the bullets are below the crosshair but the next time it will be way off to the left.
I tried moving the gun tip (aka the thing that spawned the bullets) to aim at the center of the screen but then the bullets just went way of track. The code for launching the bullets is simple. If you can help me make the bullets land where the crosshair is, thank you if not thanks for reading this.
The Code
if(Input.GetMouseButton(0) && Time.time >= nextTimeToFire)
{
Rigidbody rb = Instantiate(Bullet, GunTip.position, Quaternion.identity).GetComponent<Rigidbody>();
rb.AddForce(GunTip.forward * 500f, ForceMode.Impulse);
}
Difficult to tell what the problem is straight off the bat. Can you share the entire project somewhere? I tried to do this on my own computer and it seems to be working fine for me. One think which comes to my mind is that your GunTip may not necessarily point at the crosshair and so your bullets go off course.
If you draw a triangle (imaginary, right now) between the weapon tip, the crosshair (for simplicity, take it if the weapon tip is right under the crosshair), and the target at which the crosshair points, you'll see a different triangle when the target is 10m away, or 100m.
Based on that, I would do a Raycast "from the" crosshair (in this case, from camera position to camera forward). From that, you'll get where should your bullet arrive, and you can add the force something like that (half pseudo):
[SerializeField] private Transform _camera;
[SerializeField] private Transform _weaponTip;
[SerializeField] private LayerMask _bulletLayerMask;
[SerializeField] private float _range;
[SerializeField] private float _bulletInitSpeed;
private void Update()
{
if (<can shoot checks>)
{
if (Physics.Raycast(_camera.position, _camera.forward, out RaycastHit hit, _range, _bulletLayerMask)
{
Rigidbody bullet = <instantiate stuff>;
// calculating the direction from the weapon tip to the impact point
bullet.AddForce((hit.point - _weaponTip.position).normalized * _bulletInitSpeed, ForceMode.Impulse);
}
}
}
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.
I have a problem with physics. It is my first time doing in 3D, so it may be just a beginner mistake.
I just wanted to create a simple player controller and make it so that it can not pass trough cubes.
The problem is that when going straight into the cube, part of the player is in the cube itself. When stop moving, it pushes me, so they are not intersecting (that makes sense).
I tried moving the player using .Transalte, .MovePosition and by changing the velocity of rigidbody itself. None of it change anything. The player can always move a part of him into the cube.
Any ideas how to solve this?
My player controller:
(The 2 lines commented out in Move() are just other ways to move the player.)
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float movementSpeed;
private Vector3 input;
private void Update()
{
GetInput();
}
private void FixedUpdate()
{
Move();
}
private void GetInput()
{
float inputHorizontal = Input.GetAxisRaw("Horizontal");
float intputVertical = Input.GetAxisRaw("Vertical");
input = Vector3.ClampMagnitude(new Vector3(inputHorizontal, 0, intputVertical), 1);
}
private void Move()
{
GetComponent<Rigidbody>().velocity += input * movementSpeed;
//GetComponent<Rigidbody>().MovePosition(GetComponent<Rigidbody>().position + input * movementSpeed * Time.deltaTime);
//transform.Translate(input * movementSpeed * Time.deltaTime, Space.World);
}
}
Player is standing still
Player is moving towards cube
Settings of the Game Objects itself
Now I think I understand your problem.
The collider is a geometric shape that is checked but the outcome wont take place until the collision has actually taken place, this means, one geometric shape being inside the other. By this I mean, that what you are experiencing is the normal behaviour of the collision. If both elemnts are rigid bodies, both will move and your problem wont be perceivable, but if your cube is not a rigid body or is kinematic, will stand still in the same position, and depending on the other object speed, its normal that an invasion/superposition of the elements is perceivable, because that is the frame were the collision took place, and were your element needs to be moved back because it has collided.
Consider that if the speed is high enough, and the position from one frame to another varies enough, the collision might not even take place, because the geometric parts do not interfere between frames, as the position variation might be bigger than the bounds of the collider itself. The collision check at the end of the day, is dicrete, and not continuous (even you can set it as continuous to be as frecuent as possible).
To solve or improve that, you can adjust the speeds to avoid that being perceivable + adjust your collider to make it react before the graphic superposition occurs. This means making the capsule or the cube collider bigger than the graphic element itself. You can even calculate , to make it as bigger as much as your your speed * Time.deltaTime result or speed * FixedTimeStep result, depending on your safety distance needs. I think one of those should be the safety distance you need to take into account before the graphic collision occurs.
Another thing you can do is tight more the times physics calculations are done.
https://docs.unity3d.com/Manual/class-TimeManager.html
But need to be careful with this as this can be a performance devourer and need to be handled with care. You can make some trials with that and check your problem can improve.
Hope that helps
You can increase the scale of your player's collider from the Collider component attached to it. You can check how big the collider is from the editor scene view.
Edit: The issue might be that your movement or collision code is called in Update instead of FixedUpdate. When working with rigidbodies, you want to call the physics calculations inside FixedUpdate.
remove rigidbody from the cube, you can click on 'Gizmos' in the top right of the editor and make sure the colliders are at the edges of the objects.
I have bunch of Cylinders connected with Hinge joints, as per a youtube tutorial. Now the hinge joints move when an ExplosionForce is applied to them, but I want them to 'swing' back and forth when they are moved via the animation.
So I have the top Cylinder's RigiedBody set to Kinematic, and I animate that along the X axis to the right. Then it stops abruptly, and i want the bottom or the rest of the 'rope' to swing a bit further to the right then back again like a rope would. Ultimately I want to attach a spotlight to this rope and light up my scene. But I can't get the rope to swing, it just stays static.
I've exported the scene as a package, you can download it here:
https://www.pastefile.com/Up59SO
Here is an animation of the rope not swinging:
Please help. This is really annoying and I cannt see why it shouldnt be working!
Firstly make sure all rigidbodies are in the root of the scene; not parented to anything. Secondly, you have to use physics forces to get the elements to swing. However, you can't apply forces to kinematic objects. So what I would advise is instead of setting the root of the rope as kinematic to freezing its position on the Y axis.
public class Movement : MonoBehaviour
{
[SerializeField] Rigidbody rigidbody;
[SerializeField] float power = 25;
[SerializeField] float speed = 5;
void FixedUpdate()
{
rigidbody.AddForce(Vector3.right * Mathf.Cos(Time.time * speed) * power);
}
}
Maybe something like this could help, https://answers.unity.com/questions/1244519/how-to-randomly-set-the-direction-of-an-object-and.html?_ga=2.69603664.1732232616.1585344454-527098876.1571345094
Try thinking of it like wind.
So im creating a simple game and one component of the game is a greendot following the outside of the level. I got this working using a raycast in the middle which rotates and gives the position of collision the the gameobject.
game overview
The problem is that the speed is inconsistant at the moment since the distance between two collisions can be further distance if i have a slope. I also have the feeling that there should be a easier way to get the same result. What are your thoughts?
public class FollowPath : MonoBehaviour {
Vector3 collisionPos;
public GameObject greenDot;
void Update ()
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.up);
transform.Rotate(0.0f, 0.0f, 3);
if (hit.collider != null)
{
collisionPos = hit.point;
}
greenDot.transform.position = collisionPos;
}
}
I'm not sure if you will like this answer, as it suggests a complete departure from the way you were trying to do it.
A simple way to do this, would be to give your moving dot GameObject a Rigidbody2D component, AND a CircleCollider component.
Then, make your walls, and add to each an EdgeCollider component.
You'll probably also want to add a PhysicsMaterial2d to each GameObject with a Collider and set the friction and bounciness values for each.
Once this is setup, you can apply an initial force to the rigid body ball to get it moving, and it will bounce off the walls just like a ball does, using the Unity physics engine. No code would be needed in you update functions.
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.