I have 4 objects (A, B, C, D). All are onTriggerStay along with tags of their names as well. A question would pop up and they have to answer it by colliding with their answer(A, B, C, D), but if statements are not working correctly for some reason I tried OnTriggerStay and OnTriggerEnter but none of them. I tried changing if statements to else if but no luck. These scripts are attached to 4 gameobjects(A, B, C, D) I have attached a small clip to demonstrate the problem and my script.
Video Clip
Thank you
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class Question1 : MonoBehaviour
{
public GameObject A;
public GameObject B;
public GameObject C;
public GameObject D;
public GameObject fluSyringe;
public GameObject virusA;
public GameObject virusD;
public GameObject virusC;
private void OnTriggerStay(Collider other)
{
if (CompareTag("A") == other.CompareTag("Player"))
{
Debug.Log("A");
virusA.SetActive(true);
}
if (CompareTag("B") == other.CompareTag("Player"))
{
Debug.Log("B");
fluSyringe.SetActive(true);
}
if (CompareTag("C") == other.CompareTag("Player"))
{
Debug.Log("C");
virusC.SetActive(true);
}
if (CompareTag("D") == other.CompareTag("Player"))
{
Debug.Log("D");
virusD.SetActive(true);
}
else
{
Debug.Log("ABCD");
}
}
}
Your if-statements have side effects. This statement (like the others)
if (CompareTag("A") == other.CompareTag("Player"))
will also evaluate to true if CompareTag("A") and other.compareTag("Player") will both evaluate to false. How can this happen? Watching your video one can see that when you trigger the letter A, the other viruses at C and D will fall down the moment the virus at A touches the letter A. Thus i assume your virus object has a collider on it which leads to other.CompareTag("Player") being false. The script placed at A will now trigger all if-statements with CompareTag(X) where X is not "A". The syringe is a smaller object and i assume its collider is not touching letter B when falling down, hence in the video it looks like that it works for letter B. But that is just lucky not triggering the side effects in this case.
Assuming you want to keep the whole logic in this one script (i am not sure if this is feasible), you need to split the if-conditions:
// exemplary shown for A
if (CompareTag("A") {
if (other.CompareTag("Player")) {
Debug.Log("A");
virusA.SetActive(true);
}
}
Related
I am in the middle of creating a simple 3d platformer in unity and i'm trying to make it so if you are in a certain radius and you hit the "f" key the enemy will disappear. the way i'm checking to make sure the enemy is close enough to be attacked is to have trigger sphere and when its triggered and you press "f" the enemy will be removed. i'm currently trying to see what collided with the trigger but i cant figure it out. here is my current code
using UnityEngine;
public class PlayerCombat : MonoBehaviour
{
public GameObject Enemy1;
public GameObject Enemy2;
public GameObject Enemy3;
public GameObject Enemy4;
// Update is called once per frame
void OnTriggerEnter (Trigger triggerInfo)
{
if (triggerInfo.collider.tag == "Enemy" & Input.GetKey("f"))
{
if (triggerInfo.collider.name == Enemy)
{
Enemy1.SetActive(false);
}
}
}
}
The signature is and has always been OnTriggerEnter(Collider) otherwise that message method will not be recognized by Unity and not get called at all!
And then you already have the according Collider ... what else do you need?
public class PlayerCombat : MonoBehaviour
{
// There is no need to know the enemy references beforehand at all
// you will get all required references from the Collider parameter of OnTriggerEnter itself
// I personally would however expose these two settings to the Inspector to be more flexible
// this way you can adjust these two settings within Unity without having to touch your code
public string listenToTag = "Enemy";
public KeyCode listenToKey = KeyCode.F;
// The signature has to be this otherwise the message method is never invoked at all
private void OnTriggerEnter (Collider other)
{
// Rather use "CompareTag" instead of `==` since the latter will silently fail
// for typos and nonexistent tags while "CompareTag" shows an error which is good for your debugging
// And in general you want to use the logical "&&" instead of the bitwise operator "&" for bools
if (other.CompareTag(listenToTag) && Input.GetKey(listenToKey))
{
// simply set the object you collide with inactive
other.gameObject.SetActive(false);
}
}
}
Finally just make sure that all your enemy instances actually have the tag Enemy
First, I'm pretty sure OnTriggerEnter takes a Collider as its parameter, no? https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html
You can get the name of the collided object like so
//Upon collision with another GameObject,
private void OnTriggerEnter(Collider other)
{
Debug.Log($"collided with {other.gameObject.name}");
//you can check for specific components too
MyComponent myComponent = other.GetComponent<MyComponent>();
if (myComponent != null) {
// do something if it has that component on it!
}
}
I'm beginner in Unity. I'm making a game in Unity 2D. In this game I have a player, platforms and a die_zone, but when my player die his sprite becomes invisible. How can I change my script to make the sprite visible?
Here is the script:
using UnityEngine;
public class Death : MonoBehaviour
{
public GameObject Respawn;
public Sprite Player_;
public GameObject Player;
public GameObject die_zone1;
public GameObject die_zone2;
public GameObject die_zone3;
public GameObject die_zone4;
public void die()
{
Player.transform.position = Respawn.transform.position;
Player.GetComponent<SpriteRenderer>().sprite = Player_;
}
void OnTriggerEnter2D(Collider2D deth)
{
if (die_zone1.tag == "Death" || die_zone2.tag == "Death" || die_zone3.tag == "Death" || die_zone4.tag == "Death")
{
die();
}
}
}
I will glad to any suggestion.
Thanks!
Let's break your code down to walk through its points of failure.
using UnityEngine;
public class Death : MonoBehaviour
{
public GameObject Respawn;
public Sprite Player_;
public GameObject Player;
public GameObject die_zone1;
public GameObject die_zone2;
public GameObject die_zone3;
public GameObject die_zone4;
Type/field declarations, probably not your problem
public void die()
{
Player.transform.position = Respawn.transform.position;
Player.GetComponent<SpriteRenderer>().sprite = Player_;
}
Suspect, as your bug happens when you die. But maybe there's other code executing?
void OnTriggerEnter2D(Collider2D deth)
{
if (die_zone1.tag == "Death" || die_zone2.tag == "Death" || die_zone3.tag == "Death" || die_zone4.tag == "Death")
{
die();
}
}
}
Ah, looks safe enough. There's a conditional invocation to die(). Presumably your code could crash in the conditional (diezonetag == ...), but that would abort further execution without having edited the Player object. So probably okay.
Alright, so that leaves us with die(). There are two lines, each is a point of failure. They seem to be independent changes of each other (move the player, change their sprite) so perhaps you can test each of them in isolation to determine your culprit. You could do this by commenting out one, running, and seeing if your game still breaks. If that works, then comment out the other (and uncomment the first), run, and hopefully your game breaks.
Player.transform.position = Respawn.transform.position;
Hm, so what is the value of Respawn.transform.position? If that's off-screen or invalid, one would suspect that'd make your player position offscreen or invalid.
You can debug this one by looking at your scene view before/after your Player has died. What's their position before / after?
Player.GetComponent<SpriteRenderer>().sprite = Player_;
What's Player_ set to? Is it, perhaps, null? Alternatively, if you changed your player's sprite to be its death-state sprite in-editor, do you see anything? Maybe your death sprite is fully transparent, or the combination of your death sprite and your spriterenderer's settings makes it not appear on your screen?
When you click on your player object, does the sprite field appear in the inspector, and is it set to something sane?
Actually, you're setting Sprite to a GameObject. How's that supposed to work? Are you setting Sprite to a GameObject containing your sprite, instead of a Sprite itself? This doesn't seem like it should compile. According to Unity's documentation (which I got to by googling unity spriterenderer sprite) here https://docs.unity3d.com/ScriptReference/SpriteRenderer.html the type of SpriteRenderer.sprite is a Sprite, whereas you have a GameObject. Something seems wrong.
Remove this line, or check the sprite of Player_. Also double check if he is invisible or just moved back to the spawn point.
Player.GetComponent<SpriteRenderer>().sprite = Player_;
I am making a shooting game using Raycasts in Unity. I have a gameObject which is a cube (The ground for my game). That cube can be destroyed by using Destroy() method. How do I make it indestructible so that it doesn't get destroyed even after using the Destroy() method?
This my FPS gun script so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gun : MonoBehaviour
{
public float damage = 20f;
public float range = 150f;
//public GameObject ground;
public Camera fpsCamera;
void Start()
{
//DontDestroyOnLoad(ground);
}
void Update()
{
if (Input.GetButtonDown("Fire1")) {
Shoot();
}
}
void Shoot()
{
RaycastHit hitObject;
if (Physics.Raycast(fpsCamera.transform.position, fpsCamera.transform.forward, out hitObject, range) && hitObject.transform.name != "Ground") {
Destroy(hitObject.transform.gameObject);
}
}
It sounds like you want to sort which objects are destroyed somehow. The most simple way is of course to not call the Destroy method on that object in the first place.
However since you explain in the comments you wish to shoot and destroy some objects but not all. I would in your case make a script which either checks the tag, layer or calls a method in a script on each object.
For example, you try something similar to this:
ObjectProperties : MonoBehaviour{
public boolean CanBeDestroyed = true;
}
Add that script to the objects you shoot at.
And then when your raycast hits an object, use GetComponent on the object shot to try get ObjectProperties from that object. If the object hit has a ObjectProperties that isn't null, and that ObjectProperties has CanBeDestroyed set to be true. Then you may destroy the object.
The most simple way of achieving this, is using tags. Create a tag by highlighting the object. In the Inspector open the tags tab. Then create a tag and assign it to your object. The last thing you need to do is to check in code which tag the object you hit has.
if (Physics.Raycast(fpsCamera.transform.position, fpsCamera.transform.forward, out hitObject, range) && hitObject.transform.name != "Ground") {
switch (hitObject.tag)
{
case "immortal": //Nothing happens
break;
case "veryweak": //Objects with this tag get destroyed
Destroy(hitObject.transform.gameObject);
break;
default: //Objects that do not have a tag and do not match any of the above get destroyed
Destroy(hitObject.transform.gameObject);
break;
}
}
Hope that helps.
so i have an old code for a "Connect4" game it was written years ago, now i am having a big problem getting it results and rebuild them for a unity3D project.
the problem is that every gameObject (i've managed to instanciate in the scene) is, meant to be destroyed and reinstantiated every frame (and i have the feeling that is really more that a frame time); wanting to get the color of each gameobject in time seem to be really challenging, i am supposed now to not enter the code created i am only supposed to get the information from what i get as graphical results.
so now i have a board of boxes having a grid disposition that changes colors according to the player turns (red for the cp and yellow for the plyer).
i created a fixed boxes having colliders and wanted to get the game objects colliding with it everyframe but i failed .
PS: i tested this code and every solution i found in this community hope to find somehelp, thank you.
using UnityEngine;
using System.Collections;
public class SelectorCode : MonoBehaviour
{
public Collision other;
public GameObject GO;
void OnTriggerEnter(Collider other)
{
GO = other.gameObject;
}
void OnTriggerStay(Collider other)
{
GO = other.gameObject;
}
void OnTriggerExit(Collider other)
{
GO = other.gameObject;
}
void Update()
{
GO = this.other.gameObject;
}
}
First make sure the object to which the SelectorCode component is attached has a trigger collider (property "Is Trigger" is checked).
Next you'll get an error in the Updatemethod with GO = this.other.gameObject; since other is never assigned. I think you should remove that line.
Finally, in OnTriggerExit you put in GO the object that is leaving your collider, that doesn't make sense, you should probably assign GO to null at this point :
void OnTriggerExit(Collider other)
{
if (other.gameObject == GO)
{
GO = null;
}
}
In Unity, how can my code detect when a trigger occurs with a specific distinct object?
I already tried several things, such as:
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public GameObject DualCannon_PU;
void OnTriggerEnter2D (Collider2D coll) {
if (coll.name == "DualCannon_PU") {
Debug.Log ("DualCannon PowerUp");
}
}
}
But it doesn't work: it doesn't trigger anything and "DualCannon PowerUp" does not appear in console.
In player gameObject "is trigger" is checked and my powerUp (DualCannon_PU) "is trigger" is not checked.
I noticed that I had 2 "Player Controller (Scripts)", I deleted the first one but the problem still persists...
an example of what I want:
I have 4 gameObjects and both have 2D Colliders
A. Player ship ("is trigger" is on)
B. Enemy projectiles
C. Health PowerUp
D. Dual Cannon PowerUp
Condition I want:
A is triggered by B, C, and D
When B triggers with A in A script (Player.cs) executes: health -= laser.GetDamage();
When C triggers with A in A script (Player.cs) executes: health = health + 10;
When D triggers with A in A script (Player.cs) executes isDualCannon = true
first you need to:
Put the "Is trigger" On
Make sure you're colliders are in the border of the gameObject(edit Colliders and drag until the green lines are in the corners)
If the error still consist comment on the answer and I will see what I can do
It works fine with mine:
This guy will hit
this guy
using this code:
void OnTriggerEnter2D(Collider2D col){
Debug.Log ("notset = " + col.name);
}