The following code below shows what I made. (Pooled square is a game object I set up in another c# file)
[SerializeField] private Camera mainCamera;
private List<GameObject> PooledSquares = new List<GameObject>();
private Camera cam;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0)) {
Vector3 MousePosition = mainCamera.ScreenToWorldPoint(Input.mousePosition);
GameObject pooledSquare = ObjectPool.SharedInstance.GetPooledObject();
if (pooledSquare != null)
{
pooledSquare.SetActive(true);
pooledSquare.transform.position = MousePosition;
}
}
}
There are no syntax errors or node errors, and all the physics work such as Rigidbody, the objects are just not visible. Then I realized I didn't have a prefab. So I made a prefab. Still the same issue. If you need any more information contact me.
Thanks for your help.
var mousePosition = Input.mousePosition;
mousePosition.z = 5f; // world position from the camera.
You should give a z position otherwise it is 0 which means the object is put at the position of the camera.
Related
I have created a player prefab (called Tim in my project) and am trying to make all the references to gameObjects and transforms directly from the one of the players scripts which is actually attached to a gun object which is a child of the player prefab.
The issue is I cant manage to reference the camera in the script although I've looked and tried many different methods, none of them seemed to work. Unity prints this error in the console though : "NullReferenceException: Object reference not set to an instance of an object". And here is the script :
public class Gun_Control : MonoBehaviour
{
// References for GameObjects
[SerializeField] private Rigidbody2D rb;
private GameObject Player;
[SerializeField] private Transform PlayerTransform;
private GameObject Gun;
[SerializeField] private Transform GunTransform;
private Camera MainCamera;
private GameObject firePoint;
[SerializeField] private Transform firePointTransform;
[SerializeField] private GameObject bulletPrefab;
// Variables for Shooting
private Vector2 mousePos;
private float bulletForce = 20f;
// Start is called at the beginning
void Start()
{
Debug.Log("Starting");
Player = GameObject.FindWithTag("Player");
PlayerTransform = Player.transform;
Gun = GameObject.FindWithTag("PlayerGun");
GunTransform = Gun.transform;
MainCamera = GameObject.FindWithTag("Camera").GetComponent<Camera>();
firePoint = GameObject.FindWithTag("PlayerFirePoint");
firePointTransform = firePoint.transform;
}
// Update is called once per frame
void Update()
{
// Get mouse position
mousePos = MainCamera.ScreenToWorldPoint(Input.mousePosition);
// Run shoot function on left click
if(Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
// Update is called on every physics frame
void FixedUpdate()
{
// Set gun position to player position
GunTransform.position = PlayerTransform.position;
// Set gun rotation to mouse position
Vector2 lookDir = mousePos - rb.position;
float angle = Mathf.Atan2(lookDir.y ,lookDir.x) * Mathf.Rad2Deg - 180f;
rb.rotation = angle;
}
void Shoot()
{
// Instantiate a bullet at the firepoint and give it force
GameObject bullet = Instantiate(bulletPrefab, firePointTransform.position, firePointTransform.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePointTransform.up * bulletForce, ForceMode2D.Impulse);
}
}
Right now I have a variable, MainCamera, and when the script starts I look for a camera which has "Camera" as its tag which is set correctly.
I can add on if anyone needs more details and thank you to everyone for taking the time to help.
Edit 1 :
I tried what thunderkill suggested but it doesnt seem to work.
Here is a picture of the new code.
And when I try to use Debug.Log(Camera.main); it prints null.
here is a good example to access your main camera :
Camera m_MainCamera;
void Start()
{
//This gets the Main Camera from the Scene
if(Camera.main != null){
m_MainCamera = Camera.main;
//This enables Main Camera
m_MainCamera.enabled = true;
}
}
Camera c = Camera.main;//get the camera Tagged "MainCamera"
So you have to Check if your Camera tag is "MainCamera".
or you try :
GameObject.FindObjectOfType<Camera>();
(I don't recommend the second solution)
So I ended up finding the answer.I just deleted the camera in my scene and created a new one and then ended up using : MainCamera = GameObject.FindWithTag("Camera").GetComponent<Camera>(); which worked this time. The issue could have also been caused by errors present before in my code.
new to all this. I've tried following a few examples i've found on here but none seem to work. The best I have right now is
rb.transform.up = rb.GetComponent<Rigidbody2D>().velocity.normalized;
but this makes the rigid body rotate immediately to the new direction of travel. is there a way to make it so it rotates slower rather than jumping in one frame to the new direction of travel?
Any help would be appreciated :)
here is the code ive used to apply the force, if that matters? i got it from a tutorial to apply force based on dragging the mouse
public class DragNShoot : MonoBehaviour
{
public float power = 10f;
public Rigidbody2D rb;
public Vector2 minPower;
public Vector2 maxPower;
public TrajectoryLine tl;
Camera cam;
Vector2 force;
Vector3 startPoint;
Vector3 endPoint;
public void Start()
{
cam = Camera.main;
tl = GetComponent<TrajectoryLine>();
}
public void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPoint = cam.ScreenToWorldPoint(Input.mousePosition);
startPoint.z = 15;
}
if (Input.GetMouseButton(0))
{
Vector3 currentPoint = cam.ScreenToWorldPoint(Input.mousePosition);
currentPoint.z = 15;
tl.RenderLine(startPoint, currentPoint);
}
if (Input.GetMouseButtonUp(0))
{
endPoint = cam.ScreenToWorldPoint(Input.mousePosition);
endPoint.z = 15;
force = new Vector2(Mathf.Clamp(startPoint.x - endPoint.x, minPower.x, maxPower.x), Mathf.Clamp(startPoint.y - endPoint.y, minPower.y, maxPower.y));
rb.AddForce(force * power, ForceMode2D.Impulse);
tl.EndLine();
}
}
}
and here is script for the rotation
public class FaceDirectionOfTravel : MonoBehaviour
{
public Rigidbody2D rb;
// Update is called once per frame
void Update()
{
rb.transform.up = rb.GetComponent<Rigidbody2D>().velocity.normalized;
}
}
As you can see, I have just taken the velocity and applied that to the rotation, I guess this just immediatly changes it to match, but I want it to visibly rotate to match the rotation. I have tried some examples I have seen on here for Slerp but that only seemed to leave it in free rotation.. I must be missing something really obvious so thought I would ask on here. Thanks.
EDIT:
So I've kinda worked out a way to get it to work by creating another object on top of the object i wish to rotate and use Slerp to rotate the object on top to slowly rotate to the same as the original object which has to snap immediatly due to force applied the code is simply
public class RotateSprite : MonoBehaviour
{
[SerializeField] private Rigidbody2D rbOfTarget;
[SerializeField] private Rigidbody2D rb;
private void Start()
{
}
// Update is called once per frame
void Update()
{
rb.transform.position = rbOfTarget.transform.position;
rb.transform.rotation = Quaternion.Slerp(rb.transform.rotation, rbOfTarget.transform.rotation, 30* Time.deltaTime);
}
}
if anyone knows a better solution do let me know. Thanks.
Is your game in 3D or 2D? you keep saying it's 2D but the tag says it is 3D and if 2D you wouldn't need a Z position. and if it is in 3D you would have to change the rigidbody2D to just rigidbody.
I use Cinemachine camera collider for my project. This basically means that my entire game is inside a polygon collider.
With the following script my line renderer collides instantly with this camera collider:
[SerializeField] private float defDistanceRay = 10f;
public Transform laserFirePoint;
public LineRenderer m_linerenderer;
Transform m_transform;
private void Awake()
{
m_transform = GetComponent<Transform>();
}
private void Update()
{
ShootLaser();
}
void ShootLaser()
{
if(Physics2D.Raycast(m_transform.position, transform.right))
{
RaycastHit2D _hit = Physics2D.Raycast(m_transform.position, transform.right);
Draw2DRay(laserFirePoint.position, _hit.point);
Debug.Log(_hit.collider.name);
}
else
{
Draw2DRay(laserFirePoint.position, laserFirePoint.transform.right * defDistanceRay);
}
}
void Draw2DRay(Vector2 startPos, Vector2 endPos)
{
m_linerenderer.SetPosition(0, startPos);
m_linerenderer.SetPosition(1, endPos);
}
Can I somehow bypass this collider by setting a "tag" on it and in my code ignore colliders with that specific tag?
Anyone have a good work around for this issue?
EDIT: Forgot to mention Im looking at: https://docs.unity3d.com/ScriptReference/Physics2D.IgnoreCollision.html
But that takes in 2 colliders I just want to ignore 1.
EDIT2: I tried to set the Cinemachine camera polygon collider as a Layermask and ignore it with the following code:
public LayerMask layerMask;
void ShootLaser()
{
if (Physics2D.Raycast(m_transform.position, transform.right))
{
RaycastHit2D _hit = Physics2D.Raycast(m_transform.position, transform.right, layerMask);
Draw2DRay(laserFirePoint.position, _hit.point);
Debug.Log(_hit.collider.name);
}
else
{
Draw2DRay(laserFirePoint.position, laserFirePoint.transform.right * defDistanceRay);
}
}
EDIT 3:
RaycastHit2D _hit = Physics2D.Raycast(m_transform.position, transform.right, defDistanceRay, layerMask);
I added defDistanceRay into the Raycast and now it dosent seem to collide with the camera collider atleast! Super buggy but atleast i bypass the Cinemachine camera collider!
I'm making a top-down game where you drive a car and shoot targets at the same time. I have a script that makes a sprite of a crosshair follows the mouse cursor and I want to have it set up so that when the player presses the mouse button (the mouse button isn't in the code now) and the crosshair sprite is overlapping an enemy sprite, the enemy dies. I was following this documentation on Bounds.Intersects. Here's my code:
public class shootingScript : MonoBehaviour
{
public GameObject target, enemy;
CircleCollider2D targetCollider;
CapsuleCollider2D enemyCollider;
// Start is called before the first frame update
void Start()
{
//Check that the first GameObject exists in the Inspector and fetch the Collider
if (target != null)
{
print("targ not null");
targetCollider = target.GetComponent<CircleCollider2D>();
}
//Check that the second GameObject exists in the Inspector and fetch the Collider
if (enemy != null)
{
print("enemy not null");
enemyCollider = enemy.GetComponent<CapsuleCollider2D>();
}
}
// Update is called once per frame
void Update()
{
if (targetCollider.bounds.Intersects(enemyCollider.bounds))
{
print("hit");
Destroy(enemy);
}
}
}
In-game "targ not null" and "enemy not null" prints but when I move my cursor and the crosshair goes over the enemy "hit" is not printed and the enemy is not destroyed. I have a CircleCollider2D on the crosshair and a CapsuleCollider2D on the enemy. The script is on an empty game object. I also tried sprite.bounds but that resulted in the enemy getting killed as soon as I run the game.
EDIT:
Here's the code that keeps the crosshair sprite on the cursor. I copied it from somewhere. I set moveSpeed to 99999 since I want the crosshair sprite to be exactly where the mouse is.
public class mouseReticle : MonoBehaviour
{
private Vector3 mousePosition;
public float moveSpeed = 0.1f;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
mousePosition = Input.mousePosition;
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
transform.position = Vector2.Lerp(transform.position, mousePosition, moveSpeed);
}
}
The target sprite and enemy sprite were at different depths (z).
I currently am working on a game where I am using click to move in Unity. When I click on a spot on the map, I set that mouse's click to the destination and then use the rigidBody on the gameobject to move it using RigidBody.MovePosition(). When I do this, I am getting a lot of flicker when the gameobject reaches its destination. Any assistance is appreciated. Thanks.
// COMPONENTS
Rigidbody rigidBody;
// MOVEMENT
Vector3 destination;
Vector3 direction;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody>();
destination = transform.position;
}
// Update is called once per frame
void Update()
{
DetectInput();
}
void FixedUpdate()
{
MoveControlledPlayer();
}
void MoveControlledPlayer()
{
transform.LookAt(destination);
Vector3 direction = (destination - transform.position).normalized;
rigidBody.MovePosition(transform.position + direction * 5 * Time.deltaTime);
}
void DetectInput()
{
if (Input.GetMouseButton(0))
{
SetDestination();
}
}
void SetDestination()
{
if (!EventSystem.current.IsPointerOverGameObject())
{
Plane field = new Plane(Vector3.up, transform.position);
Ray ray;
float point = 0;
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (field.Raycast(ray, out point))
destination = ray.GetPoint(point);
}
}
I do these kind of movements with temporary joints. They are extremely accurate / configurable / embeddable.
In 2D I use a DistanceJoint2D to control distance between rigidbody points, or between a body and a world point. In 3D you could use SpringJoint or ConfigurableJoint.
Then just tween the distance basically the same way you do per frame moving now (on FixedUpdate).
Reaching a point when using a velocity-based behavior is really hard, and often results in flickering: that's because the object is always passing over his destination.
A way to fix it is to stop the movement when the object is close enought to the target.