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_;
Related
I'm trying to make a script that has an enemy chase the player only if the enemy is viewable by the player camera and the player hits the space key. I've been trying to use render.isVisible but run in to two MAJOR problems:
isVisible is enabled even if the enemy is visible in the scene view, making testing impossible.
isVisible works through walls, so if the player is looking at a wall and the enemy is behind it, it still registers as isVisible.
Please help I'm losing my mind. Thank you!
public NavMeshAgent enemy;
public Transform player;
Renderer m_Renderer;
private void Start()
{
m_Renderer = GetComponent<Renderer>();
}
private void OnBecomeInvisible()
{
enabled = false;
}
void OnBecameVisible()
{
enabled = true;
if (Input.GetKey(KeyCode.Space) && m_Renderer.isVisible)
{
Debug.Log("is visible");
enemy.SetDestination(player.position);
}
}
private void Update()
{
OnBecameVisible();
}
I'm honestly not sure what to try, thank you so much for any help!
IsVisible is really not designed for that usage. It just means object is being rendered by any camera. See the documentation here: https://docs.unity3d.com/ScriptReference/Renderer-isVisible.html
To determine whether something is actually visible from one entity by another, you typically have to do a frustum check followed by one or more raycasts to determine whether the target is blocked.
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 am trying to create a script for my enemy turret, but it is not going well. I have a couple animations of the turret being activated and deactivated. What I need is that based on the distance from the player, it plays either animation. So once it moves inside the detection radius it plays the activation animation and once it is outside it plays the deactivation animation. Most of the other ways I try require me to create an Animation Controller, which I have little experience in using. I want a simple way to play one animation once it is inside and play a different one when it is outside. I think there was a way to store the animation clip in the script, and then play it. I have attached my current script, so you know what I mean.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyTurret : MonoBehaviour
{
public GameObject Player;
public float DistanceToPlayer;
public float DetectionRadius = 75;
// Start is called before the first frame update
void Start()
{
Player = GameObject.FindGameObjectWithTag("PlayerTank");
}
// Update is called once per frame
void Update()
{
DistanceToPlayer = Vector3.Distance(transform.position, Player.transform.position);
if (DistanceToPlayer<=DetectionRadius)
{
Debug.Log("Within Radius");
}
if (DistanceToPlayer >= DetectionRadius)
{
Debug.Log("Outside Radius");
}
}
}
Calculating and checking the distance of the player for every update() is not ideal. It will work, but it will do more work than it needs to when the player isn't even near it. Its not efficient.
What you may want to do if your player is a Rigidbody, is add a SphereCollider to the turret, set isTrigger=true, set the radius to be your detection radius, and handle the OnTriggerEnter() and OnTriggerExit() events to play or stop animations.
You can also add two public Animiation objects to the script, drag and drop your animations in the editor, then you can use animation.Play() and .Stop() etc. to control the animations.
Something similar to this. Not tested fully, but you can get the idea.
public float detectionRadius = 75;
public Animation activateAnimation;
public Animation deactivateAnimation;
void Start()
{
SphereCollider detectionSphere = gameObject.AddComponent<SphereCollider>();
detectionSphere.isTrigger = true;
detectionSphere.radius = detectionRadius;
detectionSphere.center = Vector3.zero;
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "PlayerTank")
{
activateAnimation.Play();
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "PlayerTank")
{
deactivateAnimation.Play();
}
}
Your animations must not loop otherwise you will have to add more logic to check if animation.isPlaying and do your own animation.Stop() etc.
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;
}
}
I'm trying to build a pool game where the pot has a collider. Now on collision with a ball, I expect that particular ball that collided to disable.
The code below is what I've tried but it only allows me to set the ball manually. How do I automat and detect the right ball directly?
using UnityEngine;
using System.Collections;
public class pot: MonoBehaviour
{ //allows me to set collider
public SphereCollider ball;
void OnTriggerEnter(Collider other) {
Debug.Log("Ball potted");
ball = GetComponent<SphereCollider>();
ball.enabled = !ball.enabled;
}
}
Is
other.enabled = false;
what you are looking for?
It looks like your code is getting the sphere collider of the pot itself. Isn't "other" the ball in this case?
You can disable the "other" object (assuming it is the ball) with "other.gameObject.SetActive(false)" -- that's if you want the whole ball to disappear. If you just want it's collider to stop working then use "other.enabled = false".
public SphereCollider sphereCollider;
void Update()
{
if (Input.GetKeyDown(KeyCode.Q)) //or however you want to call it.
{
sphereCollider = gameObject.GetComponent<SphereCollider>();
sphereCollider.enabled = false;
}
}