- Home /
Ignore Touch
In the mobile 2D game that I'm developing the user touches the screen to shoot. So my code for that is basically:
function Update(){
for (var touch : Touch in Input.touches) {
if (Input.touchCount > 0 && touch.phase == TouchPhase.Began && Time.time >nextFireTime){
//Raycast Bullet, Fire Sound, Whatever
}
}
Now when I want to do something like open a door I'd touch that and it would open. But the problem is that I also have my function to fire every time the user touches the screen. So whenever the user touches to open a door, touches a gun icon to reload, or anything else in that manner -(I'll call them "None firey stuff" for the sake of this question)- a bullet is fired when It really isn't appropriate to.
So want to have the script not fire when "None firey stuff" is touched but I can't figure it out.
I've tried boolean's that sets to true when the "None firey stuff" is touched but by the time the firebullet script notices it it's to late and the bullet has already been fired.
Then I've tried, and currently working on, using raycasts to ignore layers and only fire when it has hit a layer that is not ignored. Here's what my script basically looks like for that:
for (var touch : Touch in Input.touches) {
if (Input.touchCount > 0 && touch.phase == TouchPhase.Began && Time.time > nextFireTime) {
var hit : RaycastHit;
var ray = Camera.main.ScreenPointToRay (touch.position);
if (Physics.Raycast(ray,Mathf.Infinity,layerMask2)) { //This part makes sure that the user is touching a "Fire Friendly" area
//Play Sound
nextFireTime = Time.time + shotInterval; //nextFireTime and shotInterval is a var
if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.forward), hit, 1000, layerMask)) { //Shoots ray for Raycast Bullet
// If hit Gives damage, instantiates blood, whatever
}
}
}
}
But this doesn't work either because if the player touches my little gun reload icon, which is a gui element, the raycast doesn't even see it so I get firing while reloading. To try to fix this I tried putting a collider in the position of the reload icon on the screen and put the layer to that of "None firey stuff" but that doesn't work at all.
So, how would you make it so it doesn't shoot when a "None firey" object is touched.
Thank You for the help, you have no idea how much i appreciate it. .......................................................................................................................................................................................................
Edit: Don't have to look at it, just posting it if it helps
I might get asked this later so here's what a fraction of my actual script I'm using for Firing pretty much looks like. :
function FixedUpdate(){
if (alive){
for (var touch : Touch in Input.touches){
var playerPlane = new Plane(Vector3.up, transform.position);
var ray = Camera.main.ScreenPointToRay (touch.position);
var hitdist = 0.0;
if (playerPlane.Raycast (ray, hitdist))
{
var targetPoint = ray.GetPoint(hitdist);
var targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotateSpeed * Time.deltaTime);
transform.Translate((Vector3.forward * moveSpeed) * Time.deltaTime);
}
}
}
}
function OnGUI(){
if (GunSlot == 1){
if (Weapon1 == 1){
AmmoText = CurrentBullets + "/" + TotalBullets;
if (GUI.Button (Rect (Screen.width/IconHorizontalPosition, Screen.height/IconverticalPosition, Screen.width/IconSize, Screen.height/IconSize), GunIcon, custom)){
if (GunTotalBullets >= 17){
if (GunCurrentBullets < 17){
if (!GunReloadBoolean){
StartCoroutine("ReloadGun");
}
}
}
else if (GunTotalBullets > 0){
if (GunTotalBullets < 17){
if (!GunReloadBoolean){
StartCoroutine("ReloadGunLessMag");
}
}
}
TempMag = 0;
GunMagazine = 17;
}
GUI.Label (Rect (Screen.width/HorizontalPositionAmmo, Screen.height/verticalPositionAmmo, Screen.width/SizeAmmo, Screen.height/SizeAmmo), AmmoText, custom);
for (var touch : Touch in Input.touches) {
if (Input.touchCount > 0 && touch.phase == TouchPhase.Began && Time.time > nextFireTime) {
if (GunCurrentBullets > 0){
var hit : RaycastHit;
var ray = Camera.main.ScreenPointToRay (touch.position);
if (Physics.Raycast(ray,Mathf.Infinity,layerMask2)) {
audio.PlayOneShot(Glock17ShotSound);
nextFireTime = Time.time + ShotInterval1;
if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.forward), hit, 1000, layerMask)) {
var gunProjectile : Rigidbody = Instantiate(projectile, transform.position, transform.rotation);
gunProjectile.velocity = (hit.point - transform.position).normalized * 200;
gunProjectile.transform.rotation = Quaternion.LookRotation(glock17Projectile.velocity);
var otherObj : GameObject = hit.collider.gameObject;
if ((otherObj.tag == "Zombie") || (otherObj.tag == "MediumZombie") || (otherObj.tag == "FastZombie")) {
var healthScript : ZombieHealth = otherObj.GetComponent("ZombieHealth");
if (healthScript.angle < 8.0){
var head = otherObj.transform.Find("Head");
Instantiate(bloodSplatter, head.position, Quaternion.LookRotation(hit.normal));
}
healthScript.HealthDamage(Damage);
}else{
Instantiate(gunShotParticle, hit.point, Quaternion.LookRotation(hit.normal));
}
}
GunCurrentBullets--;
}
}
}
if (GunCurrentBullets < 1){
if (GunTotalBullets >= 17){
if (!Glock17ReloadBoolean){
StartCoroutine("ReloadGlock17");
TempMag = 0;
GunMagazine = 17;
}
}
else if (GunTotalBullets > 0){
if (GunTotalBullets < 17){
if (!GunReloadBoolean){
StartCoroutine("ReloadGunLessMag");
TempMag = 0;
GunMagazine = 17;
}
}
}
}
}
}
}
}
Answer by japanitrat · Sep 11, 2011 at 11:28 PM
Okay, "opening a door" is probably not a thing you can do from 20 ft away (so your first solution won't be nice anyway). It is something you want to do only when you are in front of a door and actually facing it.
So here is what you do (there is even a similar tutorial on unity3d.com if I remember right):
- on each update, do a ray cast with finite length (the length might be "2") torwards the character's viewing direction.
- if there is anything "no firey" hit by the ray, set a your "do not shoot" boolean to true. if there is no "no firey", set it false likewise
- when processing your input for shooting (either touches or gui), check for that boolean.
- be happy and move on with your awesome game :)
Using a raycast to detect if a certain object is in front of you poses an array of problems like: the player has to be SUPER close to the door or an enemy could get in the way of the raycast and if the player is facing the door and is in the $$anonymous$$imal distance but they have an enemy by them and they want to shoot right then, they can't. Plus this is a 2D game I'm making so i don't need the player to be looking strait at the door, I just need it to be in the right amount of distance from the door.
The problem with "opening the door form 20 ft away" had already been taken care of long before this question. I used Vector3.Distance() to deter$$anonymous$$e the distance between the player and the door, which is more efficient then shooting raycasts in front of you. It also gives you some leeway so the player doesn't have to be face first on the door. The boolean wouldn't work for any gui, specifically the reload icon I mentioned, because both the gui and the fire script are called every frame. Unity can only tell everything that a boolean has been changed the frame after it switches and by then the bullets already been fired.
Thanks for the answer though.
humm, I did not see anything about a call of Vector3.Distance() .. furthermore, there is no need to be grumpy, i did not try to mock or offend you.
you also did not mention that a player also has to open doors that are behind him (a design thing) - otherwise you'll always have the problem of having enemies between the player and the door. The thing with the boolean in the calculation is, that the "is set the same frame" thing only happens once: the frame when the door enters to be in the hitzone. in every frame after this point, this boolean is still set in your component, thus it does not matter in which function you check for it's value.
I said in my question that it was the basic script for shooting, not opening the door. The opening door from far away wasn't really part of the question to begin with. And i was just addressing your question, not trying to be grumpy. Sorry :( Again thanks for the answer.
Answer by Jeston · Sep 12, 2011 at 07:03 AM
I don't see why ray casting isn't appropriate ? You need to make your touch handler work in layers...
Process all world touchables first, then process your non world touched messages next. Or if you do it the other way, check gui items first then world items.
I would first tag all items you want touchable as touchable. Then use gameobject.FindObjectsWith tag and transform all their bounding boxes to screen space. Loop through the bounding boxes and if one is touched, then handle the touch as you see fit: dispatched message, direct function call to a game manager, etc....
I'm already using layers with my raycast touch handler and all my layers are already tagged. I mentioned it in the second example script in my question. Booleans don't work in realtime when the gui and the touch.began are updated in the same frame, in the same script. I've tried what your saying and I mentioned it in the things I've tried in my question. It doesn't work. What I think I may need to do is use Rect.contains for my reload gui ins$$anonymous$$d of OnGui itself.
Your answer
![](https://koobas.hobune.stream/wayback/20220612210950im_/https://answers.unity.com/themes/thub/images/avi.jpg)