play if the player click in a blank space unity 2d - c#

I'm making a 2d game for mobile and created a pause button on the canvas. the problem is that when i click the pause button the player shoots. I wish there was a way to block the shot when the touch is on an element of the UI.
is there any simple way to do this?
this is the code I wrote to detect clicks:
if(Input.touchCount > 0)
{
touch_ = Input.GetTouch(0);
if(touch_.phase == TouchPhase.Began)
{
touching = true;
touch_began_fun();
}
if(tocando)
{
toching_fun();
}
if(touch_.phase == TouchPhase.Ended)
{
touching = false;
touch_ended_fun();
}
}

Check the current selected game object of the EventSystem is null. If it is not null, the touch is on a UI element.
if(Input.touchCount > 0)
{
touch_ = Input.GetTouch(0);
if(touch_.phase == TouchPhase.Began && EventSystem.current.currentSelectedGameObject == null)
{
touching = true;
touch_began_fun();
}
if(tocando)
{
toching_fun();
}
if(touch_.phase == TouchPhase.Ended)
{
touching = false;
touch_ended_fun();
}
}

Related

How to disable Prefabs in Unity 2D?

Im working on an 2d local multiplayer platformer Game. In the game are obstacles (Spikes), when the player collides with them the player will die. I want the Players of the game to decide if they would like to enable or disable the Spikes (the link leads to an image that will help understanding my problem)by pressing a Key. I already wrote a script for that and added it to my dontdestroyOnLoad GameManager. So all my spikes I built are the same Prefabs. My idea was to disable the main Prefab from the Project folder to disable all the spikes in every scene, until you press a Key to reactivate them again. The Problem is, that only the texture itself in the Project Panel disables and not the Spikes Prefabs in the Hierarchy, because the prefabs turn into regular gameObjects. How can I fix this?
My Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//using System.Threading;
public class DisableSpikes : MonoBehaviour
{
[Header("Spikes")]
public KeyCode disableSpikes;
public float time;
public GameObject prefabSpikes;
public bool toggleSpikes = true;
[Header("Player Green")]
public KeyCode disableGreen;
public GameObject prefabGreen;
public bool toggleGreen = true;
[Header("Reset Score")]
public KeyCode resetScore;
// Start is called before the first frame update
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(disableSpikes) && toggleSpikes == true)
{
prefabSpikes.SetActive(false);
Debug.Log("Disable");
//Thread.Sleep(1000);
Invoke("SetFalse", time);
}
if (Input.GetKeyDown(disableSpikes) && toggleSpikes == false)
{
prefabSpikes.SetActive(true);
Debug.Log("Anable");
//Thread.Sleep(1000);
Invoke("SetTrue", time);
}
if (Input.GetKeyDown(disableGreen) && toggleGreen == true)
{
prefabGreen.SetActive(false);
Debug.Log("Disable");
//Thread.Sleep(1000);
Invoke("SetFalse", time);
}
if (Input.GetKeyDown(disableGreen) && toggleGreen == false)
{
prefabGreen.SetActive(true);
Debug.Log("Anable");
//Thread.Sleep(1000);
Invoke("SetTrue", time);
}
if (Input.GetKeyDown(resetScore))
{
ScoreScriptBlue.scoreValueBlue = 0;
ScoreScriptRed.scoreValueRed = 0;
ScoreScriptGreen.scoreValueGreen = 0;
RoundScript.scoreValueRound = 0;
TimeScript.scoreValueTime = 0;
}
}
public void SetFalse()
{
toggleGreen = false;
toggleSpikes = false;
}
public void SetTrue()
{
toggleGreen = true;
toggleSpikes = true;
}
}
void Update() {
if (Input.GetKeyDown(disableSpikes) && toggleSpikes == true){
// show
// renderer.enabled = true;
gameObject.GetComponent<Renderer>().enabled = true;
}
if (Input.GetKeyDown(disableSpikes) && toggleSpikes == false) {
// hide
// renderer.enabled = false;
gameObject.GetComponent<Renderer>().enabled = false;
}
}

Detect whether there is a button in Canvas when user taps on screen

I am building an AR application that spawns a 3d model when user taps the screen on to the ground plane.
But the issue I am facing is that, I have placed a button at the bottom of the screen to take a screenshot. On clicking the button,it does take screenshots,but it spawns an image below the button also.
How can I avoid this ? Can I use raycast to detect a button,and not spawn the object there ?
Below is the code I use to place objects
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.Experimental.XR;
using System;
public class ArTapToPlace : MonoBehaviour
{
public GameObject objectToPlace;
public GameObject placementIndicator;
private ARSessionOrigin arOrigin;
private Pose placementPose;
private bool placementPoseIsValid = false;
void Start()
{
arOrigin = FindObjectOfType<ARSessionOrigin>();
}
void Update()
{
UpdatePlacementPose();
UpdatePlacementIndicator();
if (placementPoseIsValid && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
PlaceObject();
}
}
private void PlaceObject()
{
Instantiate(objectToPlace, placementPose.position, placementPose.rotation);
}
private void UpdatePlacementIndicator()
{
print(placementIndicator);
if (placementPoseIsValid)
{
placementIndicator.SetActive(true);
placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
}
else
{
placementIndicator.SetActive(false);
}
}
private void UpdatePlacementPose()
{
var screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
var hits = new List<ARRaycastHit>();
arOrigin.GetComponent<ARRaycastManager>().Raycast(screenCenter, hits, UnityEngine.XR.ARSubsystems.TrackableType.Planes);
print(hits.Count);
print(hits);
placementPoseIsValid = hits.Count > 0;
if (placementPoseIsValid)
{
placementPose = hits[0].pose;
var cameraForward = Camera.current.transform.forward;
var cameraBearing = new Vector3(cameraForward.x, 0, cameraForward.z).normalized;
placementPose.rotation = Quaternion.LookRotation(cameraBearing);
}
}
}
Depending on how your UI is setup you can probably use EventSystems.EventSystem.IsPointerOverGameObject for checking if the pointer is over a UI element and skip the placing in this case
if (placementPoseIsValid && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
if(EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))) return;
PlaceObject();
}

.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.

How stop a model animation on XNA?

I do not understand how to pause an animation of XNA. I can "Start" the animation of my model but not stop it.
I use SkinningSample_4_0 sample dll
Here is my code to use.
protected override void LoadContent()
{
//Model - Player
model_player = Content.Load<Model>("Models\\Player\\models");
// Look up our custom skinning information.
SkinningData skinningData = model_player.Tag as SkinningData;
if (skinningData == null)
throw new InvalidOperationException
("This model does not contain a SkinningData tag.");
// Create an animation player, and start decoding an animation clip.
animationPlayer = new AnimationPlayer(skinningData);
AnimationClip clip = skinningData.AnimationClips["ArmLowAction_006"];
animationPlayer.StartClip(clip);
}
protected overide update(GameTime gameTime)
{
KeyboardState key = Keyboard.GetState();
animationPlayer.Update(gameTime.ElapsedGameTime, true, Matrix.Identity);
// If player don't move -> stop anim
if (!key.IsKeyDown(Keys.W) && !keyStateOld.IsKeyUp(Keys.S) && !keyStateOld.IsKeyUp(Keys.A) && !keyStateOld.IsKeyUp(Keys.D))
{
//animation stop ? not exist ?
animationPlayer.Stop();
isPlayerStop = true;
}
else
{
if(isPlayerStop == true)
{
isPlayerStop = false;
animationPlayer.StartClip(Clip);
}
}
I finally found by myself ^^
if (!key.IsKeyDown(Keys.W) && !key.IsKeyDown(Keys.A) && !key.IsKeyDown(Keys.D) && !key.IsKeyDown(Keys.S))
{
//Stop animation for player walking
animationPlayer.Update(new TimeSpan(0, 0, 0), true, Matrix.Identity);
}
else
{
//Continue the animation
animationPlayer.Update(gameTime.ElapsedGameTime, true, Matrix.Identity);
}

Categories