Destroying objects with clicking - c#

Trying to figure out how to destroy an object by clicking on it. I have tried using
public void Destroy()
{
if (Input.GetMouseButton(0))
Destroy(GameObject);
}
but realise that this will destroy all gameobjects the script is attached to instead of the one I am clicking on.

Try this one:
public void OnMouseDown() => Destroy(gameObject);

Definitely the best way is to implement IPointerClick interface,
using UnityEngine;
using UnityEngine.EventSystems;
public class ClickDestroy : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
GameObject.Destroy(gameObject);
}
}
This will work both for UI and for 3D Objects, as long as your camera has PhysicsRaycaster and an EventSystem exists on scene

You can get the mouse position on the screen and fire a raycast from that location. If it hits a gameobject then you can pass it to a function to delete it.
void Update {
//Check for mouse click
if (Input.GetMouseButton(0))
{
//Create a ray from mouse location
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit = new RaycastHit();
//Check if the ray hit a gameobject, gameobject will likely need a collider
//for this to work
if (Physics.Raycast(ray, out hit))
{
//If the ray hit a gameobject, destroy the gameobject
Destroy(hit.gameobject)
}
}
}
When destroying gameobjects, make sure your specifying the gameobject component and not the script or another component of the gameobject.
This code can be improved by defining a camera object in your code and assigning a camera to it in the inspector instead of it defaulting to the main or setting up full player controls in unity (Which I can't remember how to do off the top of my head I'm afraid)

Related

Unity touch/mouse collide instead of MouseDown()

I have a sprite which at the moment I detect the mouse click on it.
However I really need to detect when the finger or mouse touches or moves across the sprite because the finger/mouse click event will occur somewhere else on the screen and not on top of the sprite.
public class Hand : MonoBehaviour
{
private void OnMouseDown()
{
if (Input.GetMouseButtonDown(0))
{
this.transform.gameObject.SetActive(false);
}
}
}
Update:
I tried to detect both touching the sprite and the mouse is down but I dont get the button clicked. I can remove the && Input.GetMouseButtonDown(0) and it will work if the mouse moves over but I want both mouse/finger over the sprite and the pressed down.
private void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000) && Input.GetMouseButtonDown(0))
hit.collider.GetComponent<Button>().onClick.Invoke();
}
There is 2 possible solution :
First: Instead of just using sprites, use button and assign it to world space canvas, in
this case touch should work if you assign canva's event camera to main camera.
2nd :If u just want to use sprites, then assign a collider to it, and use raycast
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
if (Physics.Raycast(ray,out hit,1000))
hit.collider.gameobject.GetComponent<Button>.onClick().Invoke();
Edit : The above code will work if you have a button component attached to your sprite. if not
Just call something like this
if(hit.collider.gameobject.GetComponenet<Sprite>())
DoWhateverYouWant()
Use the EventSystem interfaces to detect any kind mouse interaction with UI elements.
The EventSystem interfaces are listed here.
For example, if you want to detect when the mouse hovers over a sprite, you would add a script to the sprite object like so:
using UnityEngine.EventSystems;
using UnityEngine;
public class MouseOverHandler: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public void OnPointerEnter(PointerEventData data){
Debug.Log("MouseEnter");
}
public void OnPointerExit(PointerEventData data){
Debug.Log("MouseExit");
}
}
Note that the EventSystem works with the raycaster on the associated sprite's canvas. So if sprites are sitting on top of eachother, they can block raycasts and so the PointEnter event only gets triggered on the topmost sprite

Attached script that uses RayCast to an empty game object and now it's not working, why?

I want to shoot a raycast out of the tip of enemies gun and see if it hits the player. To do this I created an empty game object placed inside of the gun in the hierachy and moved the empty game object which I called TipOfGun not I attached script to TipOfGun called Gun with rayCast but it does nothing as far as I'm concerned and after all the testing I've done. I can't figure out why raycast never hits anything. Below is my code and i'm also posting a picture of my hierarchy.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gun : MonoBehaviour
{
private ParticleSystem muzzleFlash;
Vector3 tipOfGun = new Vector3(0.009f, 0.329f, 0.017f);
// Use this for initialization
void Start()
{
GameObject muzzleFlashObj = GameObject.Find("muzzleFlash");
muzzleFlash = muzzleFlashObj.GetComponent<ParticleSystem>();
}
public void ShootWeapon()
{
muzzleFlash.Play();
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
if (Physics.SphereCast(ray, 0.75f, out hit))
{
Debug.Log("Name of component hit:" + hit.collider.gameObject.name);
GameObject hitObject = hit.transform.gameObject;
if (hitObject.GetComponent<PlayerController>())
{
muzzleFlash.Play();
}
else
muzzleFlash.Stop();
}
}
}
You are using Physics.Spherecast which isn't what you are looking for.
From your description I think you should use Physics.Raycast
Try something like this instead of Spherecast:
if (Physics.Raycast(transform.position, transform.forward, out hit))
Give it a try.
After breaking my head a few hours in between days I decided to see if I can see the actual Raycast to determine why it was not hitting my player. I should've thought of this way before for those of you that run into a similar problem you can always draw the actual ray and view it in the scene, with something similar to this.
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
Debug.Log("Did Hit");

Move Object Along Raycast

I have made a Raycast that goes from my camera to the point of the object clicked. However, I am trying to make an object (in this case a bullet) to fly along the path of the ray. At the moment it flies straight forwards from the camera no matter where on the object you click because of the vector 3. How would I get it to follow the Ray?
C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RaycastShot : MonoBehaviour {
public Camera camera;
private Ray ray;
private RaycastHit hit;
public GameObject bullet;
private GameObject createBullet;
private Collider collider;
void Update () {
if (Input.GetMouseButtonDown (0)) {
ray = camera.ScreenPointToRay (Input.mousePosition);
createBullet = Instantiate (bullet, camera.transform.position, bullet.transform.rotation);
createBullet.AddComponent<Rigidbody>();
createBullet.GetComponent<Rigidbody>().AddRelativeForce (new Vector3(0, 1500, 0));
createBullet.GetComponent<Rigidbody>().useGravity = false;
collider = createBullet.GetComponent<Collider> ();
Destroy (collider);
if (Physics.Raycast (ray, out hit)) {
}
}
Debug.DrawLine (ray.origin, hit.point, Color.red);
}
}
You would want to use ray.direction property instead of (0,1500,0) as the direction of the force.
The add force should occur in FixedUpdate, and should only occur if the Ray hits something. Where you have it now is probably not the best spot.
Of course, make sure the bullet gets instantiated at the camera's location first.
Ray.direction gives you the vector3 direction of the ray object. If you need the distance at which it hit, you could also use ray.distance.
Edit: I'm near my computer now, so here's a more detailed answer relating to your comments.
First off: Here's the way I set up the test Project:
I Created a prefab bullet. This is just a sphere with a rigidbody, with my "BulletController" script attached to it. The point of prefabs is to avoid all of those lines where you have to add components. For testing purposes I set the rigibody to ignore gravity and its mass to 0.1.
Next, I created the BulletController script, which will be attached to the bullet prefab.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletController : MonoBehaviour {
Rigidbody rb;
public float bulletForce;
bool firstTime = false;
Vector3 direction;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody> ();
}
public void SetDirection (Vector3 dir) {
direction = dir;
firstTime = true;
}
void OnCollisionEnter () {
//code for when bullet hits something
}
void FixedUpdate () {
if (firstTime) {
rb.AddForce (direction * bulletForce);
firstTime = false;
}
}
}
This script is is charge of controlling bullets. The (later on) script that will create the bullets doesn't really care what happens to them afterwards, since its job is just to create bullets. This BulletController script is in charge of dealing with bullets once they're created.
The main parts are the SetDirection method which tells the bullet which direction to travel in. Also it adds a one-time force in its FixedUpdate method that pushes it in the direction you just set. FixedUpdate is used for physics changes like adding forces. Don't use Update to do this kind of thing. It multiplies the force by a force that you set called "bulletForce".
Finally the BulletListener Script, which is simply attached to an empty game object in the scene. This script is in charge of listening for mouse clicks and creating bullets towards them.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletListener : MonoBehaviour {
public Camera mainCamera;
public BulletController bulletPrefab;
void Update () {
if (Input.GetMouseButtonDown (0)) {
//create ray from camera to mousePosition
Ray ray = mainCamera.ScreenPointToRay (Input.mousePosition);
//Create bullet from the prefab
BulletController newBullet = Instantiate (bulletPrefab.gameObject).GetComponent<BulletController> ();
//Make the new bullet start at camera
newBullet.transform.position = mainCamera.transform.position;
//set bullet direction
newBullet.SetDirection (ray.direction);
}
}
}
In the inspector for this empty game object, I added this script, and then dragged the camera, and the bulletPrefab into the appropriate fields. Be sure to drag the prefab from the FOLDER, not from the SCENE. Since this will use the prefab, not an object in the scene.
Now click around and you'll see the bullets flying! Note that using a low force is good to test, and then increase it later.
The main things to take away from this is to split up your logic. A script should only be in charge of one thing. For example, your enemies might also fire bullets. You can now reuse your bulletController script for those bullets as well. Also, say you have different sized or shaped bullets, you can just drag the bulletcontroller script onto the different prefabs you've made for your bullets. This will not affect your listener script which will still create bullets where you click.
If you have the end point then you can move along the vector with MoveTowards:
Vector3 target = hit.point;
StartCoroutine(MoveAlong(target));
private IEnumerator MoveAlong(Vector3 target){
while(this.transform.position != target){
this.transform.position = MoveTowards(this.transform.position, target, step);
yield return null;
}
}

How can I detect when a gameobject enters the area of another gameobject?

I have a script that make a gameobject to move in some height for example at 200.
On a terrain i have another gameobject. I want that when the first gameobject that move when he start entering the other gameobject area do something.
Like
void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "Base")
{
}
}
But this is not working since there is no physical collide between the transform and the "Base". transform is at height 200.
I also tried to use Raycast hit.
In the top of the script i added:
Collider col;
Then in the Update
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (col.Raycast(ray, out hit, 100.0F))
{
Debug.Log("Hit !");
}
But again the transform is in the air.
The idea is to do something once the transform start entering the Base area.
Simple way to achieve that:
Make a child game object of the base, with only a Box Collider component (isTrigger set to true)
Extend the collider of this game object on the y axis (think of it as a pillar), like this:
Attach a script to your moving game object, with this code:
using UnityEngine;
public class CheckBaseCollider : MonoBehaviour {
public GameObject baseCollider;
private void OnTriggerEnter(Collider other) {
if (other.gameObject == baseCollider) {
Debug.Log("Entered");
}
}
}
And you're good to go.

I am using Raycast in unity and i want to get the position of an object when i click on it but i does not work and i don't know what i am doing wrong

So when I am clicking on the object in the game I get this error...
NullReferenceExceptionm : Object reference not set to an instance of an object
JumpDestination.Update () (at Assets/Scripts/JumpDestination.cs.:12)
I don't know what I am doing wrong,how can I fix it?
I want to get the position of the hited object.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class JumpDestination : MonoBehaviour {
private RaycastHit hit;
public float jumpMaxDistance;
void Update(){
Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit, jumpMaxDistance);
if (hit.collider.gameObject.tag == "RichPoint") {
print (hit.collider.transform.position);
}
}
}
I don't know what I am doing wrong,how can I fix it? I want to get the
position of the hited object.
3 things you did wrong:
1.You did not check if mouse is pressed before raycasting.
2.You did not check if Physics.Raycast hit anything before printing the object's position.
3.You defined the hit variable outside a function. Not a good idea because it will still store the old object the mouse hit. Declare that in the update function.
FIX:
void Update()
{
//Check if mouse is clicked
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
//Get ray from mouse postion
Ray rayCast = Camera.main.ScreenPointToRay(Input.mousePosition);
//Raycast and check if any object is hit
if (Physics.Raycast(rayCast, out hit, jumpMaxDistance))
{
//Check which tag is hit
if (hit.collider.CompareTag("RichPoint"))
{
print(hit.collider.transform.position);
}
}
}
}
Regardless, this answer was made to show you what you did wrong. You should not be using this. Use Unity's new EventSystems for this. Check the 5.For 3D Object (Mesh Renderer/any 3D Collider) from this answer for proper way to detect clicked object.

Categories