IsPointerOverGameObject always returns false for touch - c#

IsPointerOverGameObject always returns false for touch.
I have tried all solutions that I could find.
It works perfectly in Editor - clicks are blocked from falling through UI, but no a mobile this method always returns false.
Here is my code:
private static bool IsPointerOverGameObject()
{
bool isPointerOverGameObject = EventSystem.current.IsPointerOverGameObject();
for (int i = 0; i < Input.touchCount; i++)
{
Touch touch = Input.touches[i];
if (touch.phase != TouchPhase.Canceled && touch.phase != TouchPhase.Ended)
{
if (EventSystem.current.IsPointerOverGameObject(Input.touches[i].fingerId))
{
isPointerOverGameObject = true;
break;
}
}
}
return isPointerOverGameObject;
}
public void OnMouseDown()
{
if (IsPointerOverGameObject())
{
return;
}
// code
}

This fix works from me:
private bool IsPointerOverUIObject() {
PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
return results.Count > 0;
}
Got it from:
http://answers.unity.com/answers/1115473/view.html

According to the unity's help forum here.
The EventSystem.current.IsPointerOverGameObject() requires the touch id in the parameter to be passed. Try to pass Input.touches[i].fingerId as the parameter for it work in mobile devices and for the editor you need to leave it empty.
Try this EventSystem.current.IsPointerOverGameObject(Input.touches[i].fingerId)
edit: My bad, I didn't see that you already were passing the touch id in the code I saw the first line and thought that was missing.

Related

my c# code works when i replace obj.SetActive(true) with Debug.Log("hit"); Why?

I am trying to make it so when you get in a certain range of the GUI it activates. It was working perfectly when I was testing with Debug.Log("hit") however I changed it to obj.setActive and it stops working. I don't understand why this is?
here's the code:
private void Update()
{
if (IsInRange())
{
canvas.SetActive(true);
} else
{
canvas.SetActive(false);
}
}
private bool IsInRange()
{
origin = canvas.transform.position;
direction = canvas.transform.forward;
Collider[] hitColliders = Physics.OverlapSphere(origin, range, playerLayer);
foreach (var hitCollider in hitColliders)
{
if (hitCollider.name == player.name)
{
playerInRange = true;
playerInRangeF1 = true;
}
else
{
count += 1;
}
}
if (count != hitColliders.Length)
{
return true;
} else
{
return false;
}
}
I have finally figured out the answer to my problem. The script I was running was a component of the game object I was trying to hide and show. When you hide a game object it obviously stops all of its components from working. All I had to do was place the script on an object that would not be hidden.

Disabling colliders for a specified amount of time in Unity2D

I am very new to programming and Unity so please have patience. I am trying to disable a collider for a specified amount of time upon pressing a button (In this case, the button "s"). I have been trying to do this by using the "WaitForSeconds" command but I have never used it before and I don't know it works, but I tried anyway and as I expected it didn't work. I have to mention that the simulation does run with no errors but when I press "s" the collider doesn't disable at all. As I have mentioned I am very new to programming and Unity so I apologize if I don't understand some solutions you may suggest. Anyways here is the code
{
public bool IsFacingR = true;
public bool IsFacingL = false;
public Rigidbody2D RB;
public BoxCollider2D m_col;
void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
IsFacingR = true;
IsFacingL = false;
}
if (Input.GetKeyDown(KeyCode.A))
{
IsFacingR = false;
IsFacingL = true;
}
if (Input.GetKeyDown(KeyCode.S))
{
Slider();
StartCoroutine(SlideCol());
m_col.enabled = false;
}
}
void Slider()
{
if (IsFacingR == true)
{
RB.AddForce(Vector2.right * 9999f);
}
if (IsFacingL == true)
{
RB.AddForce(-Vector2.right * 9999f);
}
}
IEnumerator SlideCol()
{
yield return new WaitForSeconds(1);
m_col.enabled = true;
}
}
Well i tried your code in my project and it works fine. I can see collider disable for one second. Maybe there is someting that makes your collider always enable.

Tiles not following input in a branching board game path

I'm making a board game in Unity with multiple branching paths where the players can decide which one to follow. (Think the Mario Part game board) But the player input on which path to follow isn't working.
So I have a script that has the tokens follow a set path and (Linked List for the path) with a for loop to have the tokens move their allocated amount. Within the loop, I have an If statement that checks how many paths the tile has and if there are more than one if runs a separate script that pauses the game and offers a menu prompt for the players to pick one path or the other.
I've tried tossing in a few contitions for continuing the game within the loop but they either ignore the player input, are an input behind or just break the code.
`for (int i = 0; i < spacesToMove; i++)
{
if (final_Waypoint == null)
{
final_Waypoint = Starting_Waypoint;
}
else
{
if (final_Waypoint.Next_Waypoint == null || final_Waypoint.Next_Waypoint.Length == 0)
{
//we are overshooting the final waypoint, so just return some nulls in the array
//just break and we'll return the array, which is going to have nulls at the end.
Debug.Log(Current_Waypoint);
break;
}
else if (final_Waypoint.Next_Waypoint.Length > 1) // && if playerID == 0 so it only appears for players.
{
menu.Pause_for_Choice();
//if (menu.ButtonPress == true)
final_Waypoint = final_Waypoint.Next_Waypoint[menu.choice_int];
//***There's a bug here. It calls menu as per normal, and the game pauses.
//But when I click 'no', choice_int isn't updated first: this function finishes first,
//so this function gets old choice_int. THEN the button function executes.
Debug.Log("test 3 " + menu.choice_int);
}
else
{
final_Waypoint = final_Waypoint.Next_Waypoint[0];
}
}
listOfWaypoints[i] = final_Waypoint;
Debug.Log("i:" + i);
}
return listOfWaypoints;
}`
`{
public GameObject choice_Menu;
public bool isPaused = true;
public int choice_int=0;
public int choice_placeholder = 0;
public void Pause_for_Choice()
{
isPaused = true;
choice_Menu.SetActive(true);
Time.timeScale = 0;
}
public void Yes()
{
choice_placeholder = 0;
UnPause_Game();
}
public void No()
{
choice_placeholder = 1;
UnPause_Game();
}
public void UnPause_Game()
{
isPaused = false;
choice_Menu.SetActive(false);
Time.timeScale = 1;
}
}`

.SendMessage Crashes Unity C#

I am using a OverlapSphere to detect all colliders within a certain radius of my object. I then filter out a few I don't care about. With the remaining few, I attempt to send a message to those objects to update their render color. Whenever it sends the message, unity freezes. I tried to do some research and the best thing i could find is that infinite loops can freeze it. But i don't see a potential for that. Here is the code:
Object to send the message:
void sendmyMessage(bool status)
{
Collider[] tiles = Physics.OverlapSphere(gameObject.transform.position, 10);
int i = 0;
while (i < tiles.Length)
{
if(tiles[i].tag == "Tile")
{
//turn light on
if (status == true)
{
tiles[i].SendMessage("Highlight", true);
i++;
}
//turn light off
if (status == false)
{
tiles[i].SendMessage("Highlight", false);
i++;
}
}
}
}
Object Receiving Message:
void Highlight(bool status)
{
//turn light on
if(status == true)
{
gameObject.GetComponent<Renderer>().material.color = new Color(0, 0, 0);
}
//turn light off
if(status == false)
{
gameObject.GetComponent<Renderer>().material.color = new Color(1, 1, 1);
}
}
Any help is much appreciated!
It freezes because of logic if(tiles[i].tag == "Tile") here's your answer. Now imagine that object that you collide with has tag "not a tile"? then the loop never ends.
foreach(var tile in tiles) {
if (tile.tag == "Tile") {
tiles[i].SendMessage("Highlight", status);
}
}
while (i < tiles.Length)
{
if(tiles[i].tag == "Tile")
{
//snip
}
// else - loop forever?
}
Here's your problem. If the tag != "Tile" then you never increment i.

Unity timer issue

I'll explain what I'm trying to do first of all.
I have an object with a material attached to it. From my camera I have a ray being projected and when it collides with my object I'm wanting the material of that object to be placed onto another, second object. This is what I have working.
Now I am trying to expand this by having the user hold the ray over the object for a protracted period of time before the material is taking off object 1 and placed on object 2. And I'm having some issues.
When my timers gets close to the allotted time, my ray seems to stop hitting it and the highlight (which appears when the ray touches it object) disappears. Then when I look away and back at the object, instead of resetting the time, the material instantly appears on my other object. So I think I might not be resetting my timer properly.
Infact I'm positive this is to do with my timer as even when my ray isn't hitting anything, it seems to trigger my change material event.
Could someone take a look at my code and tell me?
method which checks what object has been hit with a ray and casts its material onto the correct object
void CastRay()
{
if(hit.collider.gameObject.tag == "Colour1" && change_material == true)
{
new_colour1.ChangeObjectMaterialColour(hit.collider.gameObject.renderer.material.color);
var colums = GameObject.FindGameObjectsWithTag("column");
foreach( GameObject c in colums)
c.GetComponent<MeshRenderer>().materials[1].color = new_colour1.orignalMaterial;
}
}
void ResetTimer()
{
start_time = Time.time;
running_time = 0f;
track_timer = false;
}
Code that cast the highlights the object my ray has hit:
void HighLight(GameObject nextHitObject)
{
// Case1: Last ray and new ray both hit objects
if(lastHitObject != null && nextHitObject != null)
{
//1a: same objects, do nothing
if(lastHitObject.tag == nextHitObject.tag)return;
{ //1b: different objects, swap highlight texture
lastHitObject.renderer.material = oldMat;
lastHitObject = nextHitObject;
oldMat = lastHitObject.renderer.material;
lastHitObject.renderer.material = highlight_material;
track_timer = true;
return;
}
}
// Case2: Last ray hit nothing, new ray hit object.
if(lastHitObject == null && nextHitObject != null)
{
ResetTimer();
lastHitObject = nextHitObject;
oldMat = lastHitObject.renderer.material;
lastHitObject.renderer.material = highlight_material;
track_timer = true;
if(spawned_amount == 0)
{
StatusBar();
}
return;
}
// Case3: Last ray hit something, new ray hit nothing
if(lastHitObject != null && nextHitObject == null)
{
lastHitObject.renderer.material = oldMat;
lastHitObject = null;
track_timer = false;
return;
}
else
{
spawned_amount = 0;
Destroy (GameObject.FindWithTag("StatusBar"));
change_material = false;
}
}
Timer code
void Check(bool updateTimer)
{
if(updateTimer)
{
start_time = Time.time - end_time;
running_time += Time.deltaTime;
if ( running_time >= end_time )
{
track_timer = false;
}
}
else
end_time = Time.time;
}
My last method that should be set my change material bool to true once start_time is over 4 seconds.
void StatusBar()
{
if(start_time >= 4)
{
spawned_amount = 0;
Debug.Log("status bar function");
change_material = true;
Debug.Log("chaging amterial");
}
else
{
change_material = false;
ResetTimer();
Debug.Log("resetting timer");
}
}
Try working with this timer functionality instead:
float? start_time;
void ResetTimer()
{
start_time = null;
}
bool IsTimerDone()
{
if (start_time == null)
start_time = Time.time;
else if ((Time.time - start_time) >= 4)
{
ResetTimer();
return true;
}
return false;
}
It stores your data in a single float? start_time. If the value is null, you aren't timing anything. If it has a value, the timer is active. To start it or check on it, you use IsTimerDone(): the first time it is called 4 or more seconds after it starts, it will return true and reset the timer.

Categories