tap detection on a gameobject in unity [duplicate] - c#

This question already has answers here:
How to detect click/touch events on UI and GameObjects
(4 answers)
Closed 4 years ago.
i'm currently making a soccer game.
In this mini-game, when the player touch the ball, it adds force, and the goal is to make the higher score.
So i wrote:
void Update()
{
if(Input.touchCount == 1 && Input.GetTouch(0).phase== TouchPhase.Began)
{
AddForce, and playsound ect...
}
}
With this, when i touch anywhere on the screen, it adds force, but i just want to add force when i touch my gameobject (the ball).
How can i do that?
Thanks! :)

With this, when i touch anywhere on the screen, it adds force, but i
just want to add force when i touch my gameobject (the ball).
To detect tap on a particular GameObject, you have to use Raycast to detect click on that soccer ball. Just make sure that a collider(eg Sphere Collider) is attached to it.
void Update()
{
if ((Input.touchCount > 0) && (Input.GetTouch(0).phase == TouchPhase.Began))
{
Ray raycast = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
RaycastHit raycastHit;
if (Physics.Raycast(raycast, out raycastHit))
{
Debug.Log("Something Hit");
if (raycastHit.collider.name == "Soccer")
{
Debug.Log("Soccer Ball clicked");
}
//OR with Tag
if (raycastHit.collider.CompareTag("SoccerTag"))
{
Debug.Log("Soccer Ball clicked");
}
}
}
}

Use OnMouseDown() in your script. Here is an example:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
void OnMouseDown() {
Application.LoadLevel("SomeLevel");
}
}
P.S : remove that previous code from Update() method.
EDIT : Alternative code for mobile devices
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class OnTouchDown : MonoBehaviour
{
void Update () {
// Code for OnMouseDown in the iPhone. Unquote to test.
RaycastHit hit = new RaycastHit();
for (int i = 0; i < Input.touchCount; ++i) {
if (Input.GetTouch(i).phase.Equals(TouchPhase.Began)) {
// Construct a ray from the current touch coordinates
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
if (Physics.Raycast(ray, out hit)) {
hit.transform.gameObject.SendMessage("OnMouseDown");
}
}
}
}
}
Attach the above script to any active gameObject in the scene and OnMouseDown() will work for mobile devices as well.

You need to do several items here
you need to raycast the touch to determine if the ball is touched
you need to increment the power on the duration of the touch
you need to fire the ball and reset the power on release of the touch
The code example here shows how to handle the rayCast
the code example here should help you with part 2
3 is nice and simple you just need to trigger your launch code an reset on Ended
put them together and you will get something like this
public class ExampleClass : MonoBehaviour {
void FixedUpdate() {
for (int i = 0; i < Input.touchCount; ++i) {
Ray camRay = Camera.main.ScreenPointToRay (Input.GetTouch(i).Position);
RaycastHit ballHit;
if(Physics.Raycast (camRay, out ballHit, camRayLength, ballMask))
{
if (Input.GetTouch(i).phase == TouchPhase.Stationary) {
power += speed + Time.deltaTime;
}
else if (Input.GetTouch(i).phase == TouchPhase.Ended) {
LauchBall(power);
power = 0;
}
}
}
}
}
NOTE:code is for example only it has not been tested and is not complete
this uses the physics update as the trigger you can instead link directly to an objects triggers as suggested by some of the other answers

Take Touch Event using Co-Rouitne will be good for you. If you will not use
coroutine, then it constant check for touch event in OnUpdate. Its better to take
touch event in co-routine.
This is my link in which you can check how to use it.
http://unitycodestuff.blogspot.in/2017/11/how-to-use-co-routine-for-taking-touch.html

Related

How do I call the "Movement" method of an object in another script? Unity

I am new in Unity and trying to create an Android mobile game.
First, I decided to create a script called "SelectObject" that will move the objects, provided that the object has a collider.
I add this script to the "MainCamera" components, since we need to determine if the camera ray touched the object.
Here is the script "SelectObject":
using UnityEngine;
using System.Collections;
public class SelectObject : MonoBehaviour
{
void Start() {
}
public void Update()
{
if ((Input.touchCount > 0) && (Input.touches[0].phase == TouchPhase.Began)) {
Ray ray = Camera.main.ScreenPointToRay(Input.touches[0].position);
RaycastHit hit; //Declaring the variable hit, in order to further determine if the camera's ray touhed the object
if (Physics.Raycast(ray, out hit)) {
if (hit.collider != null) { //If the ray of camera touches the collider
hit.collider.GetComponent<Move>().Movement(); //Calling the "Movement" method from script "Move" to move the object
}
}
}
}
}
The Move class is a component of the "Cylinder" object that should move when you click on it.
Here is the "Move" class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour {
public float speedModifier; //Determine the speed of movement
public Touch touch; //Using this variable, we will determine if there was at least some touch on the screen
void Start() {
speedModifier = 2.01f;
}
public void Update() {
}
public void Movement() { //Creating a "Movement" method to call it in the "SelectObject" script
touch = Input.GetTouch(0);
if(touch.phase == TouchPhase.Moved) {
transform.position = new Vector3(transform.position.x + touch.deltaPosition.x * speedModifier, transform.position.y, transform.position.z + touch.deltaPosition.y * speedModifier);
}
}
}
But when I start the game, the cylinder still doesn't move.
What am I doing wrong?
Not 100% clear on what you're trying to do but have you tried passing your location into the Movement() method? Something like this.
public void Movement(Vector3 targetLocation) {
transform.position = targetLocation;
}
Then you'd call it like this.
Movement(Input.touches[0].position);
Just a note since I noticed your speed modifier. The way your code is currently set up is going to instanly move the object to the touch location. If you would like to have it smoothly move to it at a specified speed you'll need to look up Lerping or store the previous position, current, and target position.

Unity Raycast not working from close distances

I'm trying to have various interactions take place when looking at a game object, but it doesn't seem to work when I'm too close. I'm using Unity's first person controller and the script it attached to the camera.
void Update () {
RaycastHit hit;
Vector3 forward = transform.TransformDirection(Vector3.forward) * 10;
if(Physics.Raycast(transform.position,(forward), out hit) ){
GameObject lookingAt = hit.collider.gameObject;
if (lookingAt.layer == 9)
{
Debug.Log("This doesn't always show up.");
}
}
}
I put
public LayerMask interactionLayers = ~0;
And selected the elements that should be detected in the inspector. That seemed to fix the issue.
Thanks.

Tango/Unity - UI not blocking touches on screen

We are building an example that is similar to the "Kitten - Placing Virtual objects in AR" as shown here:
https://developers.google.com/tango/apis/unity/unity-howto-placing-objects.
Basically when you touch the screen, a kitten appears on the real world plane (floor).
In our app we have a side menu, with a few buttons and each shows a different game object. We want to detect touch anywhere on the screen except where there is UI. We want the UI to block touches in Tango, and only allow touches to instantiate the related game objects on areas of the screen without UI elements.
The touch specific code is here:
void Update() {
if (Input.touchCount == 1) {
// Trigger placepictureframe function when single touch ended.
Touch t = Input.GetTouch(0);
if (t.phase == TouchPhase.Ended) {
PlacePictureFrame(t.position);
}
}
}
(The PlacePictureFrame() places a picture frame object at the touch position.)
I can't find any Tango examples which has touch and UI combined. I've tried an asset called LeanTouch to block touches behind UI elements but it doesn't seem to work with Tango specifically. Please help!
I have tried using method 5 from this:
How to detect events on UI and GameObjects with the new EventSystem API
and while it does add a PhysicsRaycaster to the TangoARCamera (which is tagged as MainCamera), the OnPointerDown method produces no debug logs no matter where you touch the screen. Tango is a special case so this is not a duplicate question. See below:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class PictureFrameUIController : MonoBehaviour, IPointerClickHandler {
public GameObject m_pictureFrame;
private TangoPointCloud m_pointCloud;
void Start() {
m_pointCloud = FindObjectOfType<TangoPointCloud>();
addPhysicsRaycaster();
}
void addPhysicsRaycaster() {
PhysicsRaycaster physicsRaycaster = GameObject.FindObjectOfType<PhysicsRaycaster>();
if (physicsRaycaster == null) {
Camera.main.gameObject.AddComponent<PhysicsRaycaster>();
}
}
public void OnPointerClick(PointerEventData eventData) {
Debug.Log("Clicked: " + eventData.pointerCurrentRaycast.gameObject.name);
PlacePictureFrame(eventData.pointerCurrentRaycast.screenPosition);
}
//void Update() {
// if (Input.touchCount == 1) {
// // Trigger placepictureframe function when single touch ended.
// Touch t = Input.GetTouch(0);
// if (t.phase == TouchPhase.Ended) {
// PlacePictureFrame(t.position);
// }
// }
//}
void PlacePictureFrame(Vector2 touchPosition) {
// Find the plane.
Camera cam = Camera.main;
Vector3 planeCenter;
Plane plane;
if (!m_pointCloud.FindPlane(cam, touchPosition, out planeCenter, out plane)) {
Debug.Log("cannot find plane.");
return;
}
// Place picture frame on the surface, and make it always face the camera.
if (Vector3.Angle(plane.normal, Vector3.up) > 60.0f && Vector3.Angle(plane.normal, Vector3.up) < 140.0f) {
Vector3 forward = plane.normal;
// Vector3 right = Vector3.Cross(plane.normal, cam.transform.forward).normalized;
// Vector3 forward = Vector3.Cross(right, plane.normal).normalized;
Instantiate(m_pictureFrame, planeCenter, Quaternion.LookRotation(forward, Vector3.up));
} else {
Debug.Log("surface is not steep enough for picture frame to be placed on.");
}
}
public void DeleteAllFrames() {
GameObject[] frames = GameObject.FindGameObjectsWithTag("Frame");
if (frames == null) {
return;
}
foreach (GameObject frame in frames) {
Destroy(frame);
}
}
}
If you want to detect a click anywhere on the screen except for where there is a UI control/component, you have to check if the pointer is over the UI with EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId).
If on desktop, use EventSystem.current.IsPointerOverGameObject(). You are using Tango so EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId). should be used.
void Update()
{
if (Input.touchCount == 1)
{
//Trigger placepictureframe function when single touch ended.
Touch t = Input.GetTouch(0);
if (t.phase == TouchPhase.Ended)
{
//Make sure that pointer is not over UI before calling PlacePictureFrame
if (!EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
PlacePictureFrame(t.position);
}
}
}
}
Edit:
It seems like this works with TouchPhase.Began only.
Change t.phase == TouchPhase.Ended to t.phase == TouchPhase.Began and this should work as expected. Make sure to test with a mobile device/tango instead of your mouse.

Unity - Raycast not working when more than one prefab on Scene

I created a script that uses RayCasting for detecting two Prefabs - One prefab has a tag called "target" and the second prefab has a tag called "unTarget". On click on prefab 1 with "Target" tag its supposed to increment count and when clicking on prefab 2 with "unTarget" tag its supposed to decrement the count. This seems to work when only one Prefab is in the scene. It will increment/decrement when only one is added and clicked. When both prefabs are in the Scene both prefabs will increment. I am not sure why this is happening. Any Help or Ideas? Sorry if my code is a bit messy.
using UnityEngine;
using System.Collections;
public class clicks : MonoBehaviour
{
public int score;
void Start()
{
score = 0;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown (0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit,200))
{
if (GameObject.FindGameObjectWithTag ("target"))
{
score++;
}
else
{
score--;
}
}
}
}
The GameObject.FindGameObjectWithTag method is going to look at your entire scene for an object with target as the tag. Since you have one in the scene that will always return true, if you hit something.
You need to look at the properties on the RaycastHit and pull the tag from there.
if (hit.collider.tag == "target")
{
score++;
}
else
{
score--;
}

Unity Check if object is clicked

Please keep in mind that I'm new to unity. I created an 2D android game app.
I created a start button( from an image) and attacted a Box colider, and a C# script to it.
When I click the "button" I want the program to move to the next "Level", that Works except that I want it to only Work if i click the object and not everywhere on the game.
This is the C#:
using UnityEngine;
using System.Collections;
public class StartGame : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0)) {
Application.LoadLevel("Game");
}
}
}
I searched alot about this and maybe people say that to solve this you have to use, Ray and RaycastHit But I cant get that to Work either.
Here is what I tried to with Ray & RaycastHit
// Update is called once per frame
void Update () {
if ((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) || (Input.GetMouseButtonDown(0)))
{
RaycastHit hit;
Ray ray;
#if UNITY_EDITOR
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
#elif (UNITY_ANDROID || UNITY_IPHONE || UNITY_WP8)
ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
#endif
if(Physics.Raycast(ray, out hit))
{
Application.LoadLevel("Game");
}
}
}
Any help would be so appriciated.
Probably the easiest way is to add box collider and script component including function below to the gameobject.
void OnMouseOver()
{
if (Input.GetMouseButtonDown(0))
{
Application.LoadLevel("Game");
}
}
Edit:
I'm guessing that the original code is not working on your scene, because you are using box collider 2d. Physics.Raycast is testing against 3D colliders. When I run it with the 3D version box collider it works fine.

Categories

Resources