I'm trying to detect collision in some cases, headshot, not headshot, missing the target.
Here is how I tried to achieve it:
private void OnCollisionEnter(Collision collision)
{
if (interations.won && interations.currentlyPickedUpObject == null)
{
if (collision.collider == head)
{
Debug.Log("HeadShot");
}
if (collision.collider == body || collision.collider == feet)
{
Debug.Log("Not a HeadShot");
}
else
{
Debug.Log("You've missed the target");
}
}
}
The issue I'm facing is that the if and the else both get executed! shouldn't the else block get executed only if the if conditions are not met? why is this happening? I want to execute the else part only if the two conditions are false!
enter image description here
Try this:
private bool hasCollided = false;
private void OnCollisionEnter(Collision collision)
{
if (interations.won && interations.currentlyPickedUpObject == null && !hasCollided)
{
hasCollided = true;
if (collision.collider == head)
{
Debug.Log("HeadShot");
}
if (collision.collider == body || collision.collider == feet)
{
Debug.Log("Not a HeadShot");
}
else
{
Debug.Log("You've missed the target");
}
}
}
Try to change the second if with else if, like this
else if (collision.collider == body || collision.collider == feet)
In your code, the else condition is linked only with the second if condition, and not the first if.
They are both executed, because you got two if statements. Your first if statement is separate from the else, which in turn is tied to the second if.
Imagine collider is a head: your first if will be true. Then you go to the second if - the collider is neither body nor feet, and you go to the else, hence your code logs both HeadShot, and You've missed the target
To prevent that, you can use else if:
if (collision.collider == head)
{
Debug.Log("HeadShot");
}
else if (collision.collider == body || collision.collider == feet)
{
Debug.Log("Not a HeadShot");
}
else
{
Debug.Log("You've missed the target");
}
as it will prevent the code from choosing multiple options.
Related
This script was made to compare player tags and determine if they are active (clones) and select an active clone and rename Rplayer to random players name. But It seems to get stuck on the second random select if a player isn't active. I receive Debug.log (Rplayer 2) Debug.Log (Player tag 1) I have tried swapping it around so it's if (! = null) and rebuilding the code but still no luck same thing. Any Ideas? I feel like I'm just looking at this wrong.
if (player.CompareTag("Player1"))
{
Rplayer = Random.Range(1, 4);
if (Rplayer == 1)
{
rplayer1 = GameObject.FindWithTag("Player2");
Debug.Log("Rplayer 1");
}
else if (Rplayer == 2)
{
if (GameObject.FindGameObjectsWithTag("Player3") == null)
{
Rplayer = Random.Range(1, 3);
if (Rplayer == 1)
{
rplayer1 = GameObject.FindWithTag("Player2");
}
else if (Rplayer == 2)
{
if (GameObject.FindGameObjectsWithTag("Player4") == null)
{
rplayer1 = GameObject.FindWithTag("Player2");
}
else
{
rplayer1 = GameObject.FindWithTag("Player4");
}
}
}
else
{
rplayer1 = GameObject.FindWithTag("Player3");
}
Debug.Log("Rplayer 2");
}
else if (Rplayer == 3)
{
if (GameObject.FindGameObjectsWithTag("Player4") == null)
{
Rplayer = Random.Range(1, 3);
if (Rplayer == 1)
{
rplayer1 = GameObject.FindWithTag("Player2");
}
else if (Rplayer == 2)
{
if (GameObject.FindGameObjectsWithTag("Player3") == null)
{
rplayer1 = GameObject.FindWithTag("Player2");
}
else
{
rplayer1 = GameObject.FindWithTag("Player3");
}
}
}
else
{
rplayer1 = GameObject.FindWithTag("Player4");
}
Debug.Log("Rplayer 3");
}
Debug.Log("player tag 1");
}
Going off of this comment:
So I'll try and explain this sorry if it takes 2 comment boxes. You start the game there is an option for 4 players 2 are always active, player 1 player 2. Player 3 and 4 are options to turn on and off, What i'm doing is trying to display an alert when a player lands on a spot <-- Works. The displayed Alert Will get the players name that landed on the spot and enter it into the alert. it then needs to check if player 3 or 4 is active and randomly select 1 player that is not the player who landed on the spot. then activate the alert if (message == 1) { yield return MessageAlert.instance.DisplayAlert(player.name + "Trade Spaces with " + rplayer1.name, Color.blue);
Assuming each player in the game has a Player.cs script attached to it (or something similar), this should be fairly straightforward. Rather than managing players with tags and ids, we can manage the references directly.
First, let's create a method that selects another random player that is NOT the one that landed on the spot. This script can be made as a singleton, or even just attached to the spot.
public Player[] allActivePlayers;
void Start()
{
//Only returns active GameObjects with the Player.cs script attached
allActivePlayers = FindObjectsOfType<Player>();
}
public Player RandomOtherPlayer(Player excludedPlayer)
{
//Create a collection of all other active players that don't include the current player
IEnumerable<Player> activeOtherPlayers = allActivePlayers.Where(player => player != excludedPlayer);
//generate a random number to select from the new collection
int randNum = Random.Range(0, activeOtherPlayers.Count());
//Return the randomly select player
return activeOtherPlayers.ElementAt(randNum);
}
Now when playerA lands on the spot, you can call this to get a random other player.
Player playerB = RandomOtherPlayer(playerA);
--Disclaimer: If there are any syntax errors please let me know. I typed this in browser and have not yet tested via Unity.
I have an Enumerator for the effects played when you shoot a gun. It is:
private IEnumerator ShotEffect()
{
gunAudio.Play();
laserLine.enabled = true;
yield return shotDuration;
laserLine.enabled = false;
}
When I take the gunAudio.Play() out, the code works fine. However, when I add it in, the sound does not play and the line doesn't disable. I assume there is a problem with the shotDuration?
The variable gunAudio is given the audio component in start, and shotDuration is a wait for seconds.
EDIT:
Also, if I set it to play on awake, it plays. Therefore I think there is a problem with the code, not the component.
Here is where I call the Enumerator:
if (Input.GetKey(KeyCode.Mouse0) && Time.time > nextFire)
{
torsoDamage = (int)Random.Range(50f, 70f);
legDamage = (int)Random.Range(20f, 30f);
handDamage = (int)Random.Range(5f, 15f);
nextFire = Time.time + fireRate;
StartCoroutine (ShotEffect());
Vector3 rayOrigin = fpsCam.ViewportToWorldPoint (new Vector3(0.5f, 0.5f, 0.0f));
RaycastHit hit;
laserLine.SetPosition (0, gunEnd.position);
if (Physics.Raycast (rayOrigin, fpsCam.transform.forward, out hit, weaponRange))
{
laserLine.SetPosition (1, hit.point);
if (enemyAi.enemy_currentHealth != null)
{
if (hit.collider.gameObject.tag == "head")
{
enemyAi.Damage(100);
}
if (hit.collider.gameObject.tag == "torso")
{
enemyAi.Damage(torsoDamage);
}
if (hit.collider.gameObject.tag == "leg" || hit.collider.gameObject.tag == "arm")
{
enemyAi.Damage(legDamage);
}
if (hit.collider.gameObject.tag == "hand" || hit.collider.gameObject.tag == "foot")
{
enemyAi.Damage(handDamage);
}
}
if (hit.rigidbody != null)
{
hit.rigidbody.AddForce (-hit.normal * hitForce);
}
}
else
{
laserLine.SetPosition (1, gunEnd.position + (fpsCam.transform.forward * weaponRange));
}
}
I fixed it - there was some weird problem with another variable that was being called from another script.
The code works fine now.
I am making a simple drag and drop unity game. When I drag the object for the first time it does not give score but when I drag it once again it gives score even if I am dropping at the wrong place. I am using tag to match desired objects
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class sh_score : MonoBehaviour {
static int score = 0;
public Text scoreText;
public GameObject ans_circle;
public GameObject tag_circle;
public GameObject tag_rectangle;
public GameObject ans_rectangle;
public GameObject ans_triangle;
public GameObject tag_triangle;
public GameObject ans_square;
public GameObject tag_square;
public GameObject ans_star;
public GameObject tag_star;
void Start()
{
score = score;
if( (ans_circle == null || tag_circle == null) || (ans_rectangle == null || tag_rectangle == null)|| (ans_square == null || tag_square == null) || (ans_triangle == null || tag_triangle == null)|| (ans_star == null || tag_star == null))
{
ans_circle = GameObject.FindGameObjectWithTag("ans_circle");
if (ans_circle != null)
{ Debug.Log("ans Find"); }
tag_circle = GameObject.FindGameObjectWithTag("circle");
if (tag_circle != null)
{
Debug.Log("circle");
}
checkTagPlace();
ans_rectangle = GameObject.FindGameObjectWithTag("ans_rectangle");
if (ans_rectangle != null)
{ Debug.Log("ans Find"); }
tag_rectangle = GameObject.FindGameObjectWithTag("rectangle");
if (tag_circle != null)
{
Debug.Log("rectangle");
}
ans_triangle = GameObject.FindGameObjectWithTag("ans_triangle");
if (ans_triangle != null)
{ Debug.Log("ans Find"); }
tag_triangle = GameObject.FindGameObjectWithTag("triangle");
if (tag_triangle != null)
{
Debug.Log("triangle");
}
ans_star = GameObject.FindGameObjectWithTag("ans_star");
if (ans_star != null)
{ Debug.Log("ans Find"); }
tag_star = GameObject.FindGameObjectWithTag("star");
if (tag_star != null)
{
Debug.Log("star");
}
ans_square = GameObject.FindGameObjectWithTag("ans_square");
if (ans_square != null)
{ Debug.Log("ans Find"); }
tag_square = GameObject.FindGameObjectWithTag("square");
if (tag_square != null)
{
Debug.Log("square");
}
}
}
void update()
{
scoreText.text = score.ToString();
}
public void IncrementScore()
{
score = score + 9;
score++;
scoreText.text = "Score: " + score;
}
public void checkTagPlace()
{
Debug.Log("check function run");
float circle_postion = tag_circle.transform.position.x;
float circle_Tag_positon = ans_circle.transform.position.x;
float triangle_position = tag_triangle.transform.position.x;
float triangle_Tag_positon = ans_triangle.transform.position.x;
float square_postion = tag_square.transform.position.x;
float square_Tag_positon = ans_square.transform.position.x;
float star_postion = tag_star.transform.position.x;
float star_Tag_positon = ans_star.transform.position.x;
float rectangle_position = tag_rectangle.transform.position.x;
float rectangle_Tag_positon = ans_rectangle.transform.position.x;
if ((ans_circle.transform.position.x == tag_circle.transform.position.x))
{
Debug.Log("found position");
IncrementScore();
}
else if ((ans_rectangle.transform.position.x == tag_rectangle.transform.position.x))
{
IncrementScore();
}
else if ((ans_square.transform.position.x == tag_square.transform.position.x))
{
IncrementScore();
}
else if (ans_triangle.transform.position.x == tag_triangle.transform.position.x)
{
IncrementScore();
}
else if (ans_star.transform.position.x == tag_star.transform.position.x)
{
IncrementScore();
}
}
}
I cannot post comments yet but
You are calling checkTagPlace before having set all of your attributes it may be the cause of the bug.
Searching gameObjects with tags this way may be a problem in the future if you have several objects with the same tag
Usually to do what you want to do you want to use Colliders on your GameObject and the OnCollisionEnter/OnCollisionStay/OnTriggerEnter/OnTriggerStay functions (do not forget the upper case). Then you will be able to check if the "collisioned" GameObject have the correct tag.
I believe your problem might be here:
if(ans_rectangle.transform.position.x == tag_rectangle.transform.position.x)
When you check to see if these positions (and the other if statements like this one) are equal, you are checking if they're exactly equal. Unless you have some controller which is discretizing the movements of your shapes, thats almost never going to happen.
I believe what you want is really something like this:
float epsilon=.001;
if(Math.abs(ans_rectangle.transform.position.x - tag_rectangle.transform.position.x)<epsilon)
Alternatively, you can give colliders to all of your shapes and actually check for collisions between the two shape types, perhaps using layer masks to keep from comparing shapes of dissimilar types.
I understand that this doesn't explain all the behavior you're seeing, but it might explain why it doesn't increment your score the first time.
Since you don't include the code which is enabling the dragging, we can't know if that is the problem or not.
I'm trying to get an input from the "space" button, but it looks like it doesn't take the input when I click. Here's my code:
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "GreenKey") {
print ("Green Key taken");
Destroy (other.gameObject);
greenKey_canvas.enabled = true;
} else if (other.gameObject.tag == "RedKey") {
print ("Red Key taken");
Destroy (other.gameObject);
redKey_canvas.enabled = true;
} else if (other.gameObject.tag == "YellowKey") {
print ("Yellow Key taken");
Destroy (other.gameObject);
yellowKey_canvas.enabled = true;
} else if (other.gameObject.tag == "Gem") {
print ("Gem taken");
gems = gems + 5;
gemsText.text = gems.ToString ();
Destroy (other.gameObject);
} else if (other.gameObject.tag == "RedGem") {
print ("Gem taken");
gems++;
gemsText.text = gems.ToString ();
Destroy (other.gameObject);
} else if (other.gameObject.tag == "LiveTaker") {
lives--;
} else if (other.gameObject.tag == "RedDoor") {
if (redKey_canvas.enabled) {
if (Input.GetKeyDown(KeyCode.Space)) {
//OPEN DOOR
other.gameObject.GetComponent<SpriteRenderer>().sprite = enterDoor;
redKey_canvas.enabled = false;
}
}
} else if (other.gameObject.tag=="YellowDoor") {
if (yellowKey_canvas.enabled) {
//OPEN DOOR
}
} else if (other.gameObject.tag=="GreenDoor") {
if (greenKey_canvas.enabled) {
//OPEN DOOR
}
}
}
In the console, I get the "entered door with key" message, but when I press Space, nothing happens.
I've also tried to add an Axis to the Input Manager named "DoorEnter", but it doesn't work either...
The reason this dosent work, is that the OnCollisionEnter function only activates the frame that the collision first happens, and that the GetKeyDown only lauches the single frame the button gets pushed.
One quite ugly fix, would be to Replace GetKeyDown with GetKey, then already hold space when walking into the door.
A better solution would be to add a variable, for an if statement in the Update loop. Make it activate when the user enters, and deactivate when the user leaves collision area.
Then make an if statement like this:
if(inCollider && Input.GetKeyDown(KeyCode.Space)){
//Open door here
}
Also, can anyone format this correctly? (Am on phone)
EDIT: Collision means trigger! Sorry!
Okay, I am making a simple game mechanic where you are a ball rolling along a small panel. On the edge of the panel are 8 child objects. 4 of them are triggers on the edges of the panel, and 4 of them are empty game objects 1 unit away from each edge of the panel for the location of the next panel prefab to spawn at. The ball has a trigger on it that detects the location of the empty game objects to tell the panel prefab where to spawn. When the ball enters a specific trigger frm the panel the ball is suppose to instantiate a panel prefab on the location that I assign based on the trigger the ball enters. Here is my code:
public GameObject panelPrefab;
Transform frontSpawn;
Transform backSpawn;
Transform leftSpawn;
Transform rightSpawn;
private bool allowSpawn;
void Awake()
{
allowSpawn = true;
}
void OnTriggerStay(Collider spawn)
{
if (spawn.gameObject.tag == "FrontSpawn")
{
frontSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "BackSpawn")
{
backSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "LeftSpawn")
{
leftSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "RightSpawn")
{
rightSpawn = spawn.transform;
}
}
void OnTriggerEnter (Collider other)
{
if (other.gameObject.tag == "Front" && allowSpawn == true)
{
Instantiate (panelPrefab, frontSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Back" && allowSpawn == true)
{
Instantiate (panelPrefab, backSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Left" && allowSpawn == true)
{
Instantiate (panelPrefab, leftSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Right" && allowSpawn == true)
{
Instantiate (panelPrefab, rightSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
}
void OnTriggerExit (Collider other)
{
allowSpawn = true;
}
My issue is on each of the Instantiate calls, I am getting a NullReferenceException. I have the panelPrefab assigned in the unity editor, and I don't know what could be causing this! If anyone can help me here it would be GREATLY appreciated... So thank you in advance!
OnTriggerEnter is called before OnTriggerStay. The error is not due to the panelPrefab object. It might happen that your rightSpawn, leftSpawn etc. objects are null and hence cannot access the transform property of a null object.
Before instantiating verify if rightSpawn etc. is null or not and then access it's position.