I am trying to make an object that teleports the player to a different scene when clicked.
I tried following this tutorial: https://youtu.be/PpLJq6AR2J0
This is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Table : MonoBehaviour
{
[SerializeField] private GameObject UiElement;
private void OnTriggerStay2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
UiElement.SetActive(true);
if (Input.GetKeyDown(KeyCode.E))
{
SceneManager.LoadScene("Table1");
}
}
}
void Update()
{
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
UiElement.SetActive(false);
}
}
}
But when I tried it executes everything except
if (Input.GetKeyDown(KeyCode.E))
{
SceneManager.LoadScene("Table1");
}
The code is correct and it executes when it's inside the update function. Is there a fix to this?
The physics framerate update doesn't have to match the game framerate. The Input.GetKeyDown will be true only for one frame so it won't be called. You should put input checks like Input.GetKeyDown inside the update function.
This is not the best way to do it but only to show a way to do it:
private void OnTriggerStay2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
UiElement.SetActive(true);
colliderHit = true;
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
if(colliderHit)
SceneManager.LoadScene("Table1");
}
}
Thanks, here is the solution:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Table : MonoBehaviour
{
private bool collided = false;
[SerializeField] private GameObject UiElement;
private void OnTriggerStay2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
collided = true;
}
}
void Update()
{
if (collided == true)
{
UiElement.SetActive(true);
if (Input.GetKeyDown(KeyCode.E) && UiElement == true)
{
SceneManager.LoadScene("Table1");
}
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
collided = false;
UiElement.SetActive(false);
}
}
}
I just used a boolean called collided. That way u can check inside the Update() function.
Related
So I am currently Trying to create a zombies game, where I have a script written that would enable a hitting animation if it was "close" to the player.
The code for this script is below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ZombieNavMesh : MonoBehaviour
{
private Transform movePositionTransform;
private NavMeshAgent navMeshAgent;
private Animator animator;
static bool close;
private void Start()
{
movePositionTransform = GameObject.Find("Player").transform;
animator = GetComponent<Animator>();
}
private void Awake()
{
navMeshAgent = GetComponent<NavMeshAgent>();
}
private void Update()
{
if (!close)
{
navMeshAgent.destination = movePositionTransform.position;
animator.SetBool("Close", false);
}
if (close)
{
animator.SetBool("Close", true);
}
}
public void OnTriggerEnter(Collider other)
{
if(other.tag == "Player")
{
Debug.Log("Should hit");
close = true;
}
}
public void OnTriggerExit(Collider other)
{
if(other.tag == "Player")
{
Debug.Log("Should not hit");
close = false;
}
}
}
The problem in here is that, if one zombie Enters Trigger, and another zombie Exit Trigger, the bool value close would be set to false, so both would perform walking animation; it should be the "close" zombie hitting animation, and the far zombie walking animation.
Remove the word static from static bool close;
static means there is only one of that thing shared by all versions and instances of the class.
Assets\GameControl2D.cs(25,10): error CS0106: The modifier 'public' is not valid for this item
This error is happening why? Please anyone let me help it to figure out.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameControl2D : MonoBehaviour
{
public static GameControl2D instance;
public GameObject gameOverText;
public bool gameOver = false;
void Awake ()
{
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Destroy (gameObject);
}
}
void Update ()
{
public void BirdDied()
{
GameOverText.SetActive (true);
gameOver = true;
}
}
}
You have a nested/local method BirdDied, that can't have access modifiers. It's accessible only from the method body of Update anyway. So this compiles:
void Update ()
{
void BirdDied()
{
GameOverText.SetActive (true);
gameOver = true;
}
}
But since you don't use it in your code, i doubt that it's what you want.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bird2D : MonoBehaviour
{
public float upForce = 200f;
private bool isDead = false;
private Rigidbody2D rb2d;
private Animator anim;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (isDead == false)
{
if (Input.GetMouseButtonDown(0))
{
rb2d.velocity = Vector2.zero;
rb2d.AddForce(new Vector2(0, upForce));
anim.SetTrigger("Flap");
}
}
}
void OnCollisionEnter2D()
{
isDead = true;
anim.SetTrigger("Die");
GameControl2D.Instance.BirdDied();
}
}
This is the Bird2D.cs file i already remove public from birdDied method but the error is same
This code is attached to my player by a script named PlayerCollision:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
void Start()
{
}
void Update()
{
}
void OnCollisionEnter (Collision collision)
{
if (collision.collider.tag == "Finish")
{
Debug.Log("Level Finished");
}
}
}
Can Someone tell me why this code is not displaying Level Finished in the Console
If it's a 2D game, I think you want to use OnCollisionEnter2D: https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnCollisionEnter2D.html
void OnCollisionEnter2D (Collision2D collision)
{
if (collision.collider.tag == "Finish")
{
Debug.Log("Level Finished");
}
}
So i want to check if a spawned Block (prefab) collides with my trigger collider but what i wrote doesn't seem to work. Anyone knows how to correctly check if the colliding GameObject is a Block?
Thanks in Advance. :)
Check:
using System;
using GameOver;
using UnityEngine;
public class gameOver : MonoBehaviour
{
[SerializeField] public DeathScreen deathScreen;
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.gameObject.GetType() == typeof(Block))
{
deathScreen.Setup();
}
}
}
Block:
using System;
using TMPro;
using UnityEngine;
public class Block : MonoBehaviour
{
private int _hitsRemaining = 5;
private SpriteRenderer _spriteRenderer;
private TextMeshPro text;
private void Awake()
{
_spriteRenderer = GetComponent<SpriteRenderer>();
text = GetComponentInChildren<TextMeshPro>();
UpdateVisualState();
}
private void UpdateVisualState()
{
text.SetText(_hitsRemaining.ToString());
_spriteRenderer.color = Color.Lerp(new Color(0.35f, 1f, 0.67f), new Color(0.04f, 1f, 0.96f), _hitsRemaining / 10f);
}
private void OnCollisionEnter2D(Collision2D collision)
{
_hitsRemaining--;
if (_hitsRemaining > 0)
UpdateVisualState();
else
Destroy(gameObject);
}
internal void SetHits(int hits)
{
_hitsRemaining = hits;
UpdateVisualState();
}
}
Block Prefab:
Collider:
To check if the collided object is an instantiated Block (or any Block really), you check for the existence of the Block component:
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.GetComponent<Block>() != null)
{
deathScreen.Setup();
}
}
Additionally, with one of your collides being a trigger, OnCollisionEnter2D will not be called. Either switch both to non-triggers if you can, or use OnTriggerEnter2D - but then one of your objects has to have a Rigidbody2D as well (source), so it is really up to what you are designing.
I'm developing a TopDown 2D game in Unity.
The idea is, when the player steps on a certain tile, a UI with text pops up (already working) and the player stops moving until the player clicks a button (already programmed and working) and the UI disappears.
I was advised to turn the RigidBody2D to kinematic however it doesn't work and it just does what it used to do.
Am I doing something wrong?
Here is the code for the trigger script on the tiles:
public class TriggerScript : MonoBehaviour
{
public string popUp;
public void Start()
{
}
private void OnTriggerEnter2D(Collider2D collision)
{
Rigidbody2D Player = GameObject.Find("Player").GetComponent<Rigidbody2D>();
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
if (collision.gameObject.tag == "Player")
{
pop.PopUp(popUp);
Player.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Kinematic;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
Rigidbody2D Player = GameObject.Find("Player").GetComponent<Rigidbody2D>();
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
pop.closeBox();
Player.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
}
}
PopUpSystem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PopUpSystem : MonoBehaviour
{
public GameObject popUpBox;
public Animator popupanimation;
public TMP_Text popUpText;
public PLayerController mb;
public void PopUp(string text)
{
popUpBox.SetActive(true);
popUpText.text = text;
popupanimation.SetTrigger("pop");
}
public void closeBox()
{
popupanimation.SetTrigger("close");
mb.camMove = true;
}
}
PLayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PLayerController : MonoBehaviour
{
private Rigidbody2D MyRB;
private Animator myAnim;
[SerializeField]
private float speed;
public bool camMove = true;
// Start is called before the first frame update
void Start()
{
MyRB = GetComponent<Rigidbody2D>();
myAnim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (camMove)
{
MyRB.velocity = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed * Time.deltaTime;
myAnim.SetFloat("moveX", MyRB.velocity.x);
myAnim.SetFloat("moveY", MyRB.velocity.y);
if ((Input.GetAxisRaw("Horizontal") == 1) || (Input.GetAxisRaw("Horizontal") == -1) || (Input.GetAxisRaw("Vertical") == 1) || (Input.GetAxisRaw("Vertical") == -1))
{
myAnim.SetFloat("LastMoveX", Input.GetAxisRaw("Horizontal"));
myAnim.SetFloat("LastMoveY", Input.GetAxisRaw("Vertical"));
}
}
if (!camMove)
{
MyRB.velocity = new Vector2(0, 0);
}
}
}
TriggerScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerScript : MonoBehaviour
{
public string popUp;
Animator popAnim;
public PLayerController mb;
private void Start()
{
popAnim = GameObject.FindGameObjectWithTag("PopUpBox").GetComponent<Animator>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
var myp = GameObject.FindGameObjectWithTag("Player").GetComponent<PLayerController>();
if (collision.gameObject.tag == "Player")
{
pop.PopUp(popUp);
mb.camMove = false;
}
if (popAnim.GetCurrentAnimatorStateInfo(1).IsName("close"))
{
mb.camMove = true;
Debug.Log("close");
}
}
private void OnTriggerExit2D(Collider2D collision)
{
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
pop.closeBox();
}
}
Things to keep in mind:
1- Make a new tag and call it PopUpBox. then assign this tag to the Trigger GameObject.
2- To the button of the PopUpBox GameObject (the one which is disabled) assign GameManager GameObject and in its function select PopUpSystem.closeBox
3- In both Trigger GameObject and GameManager assign Player in Mb field.
Hope this help you. You can play with that more to get better results.