this is a pretty long code for a simple function but i can't seem to know how i can shorten it. any advice?
this is a simple script that i created for a beginner project and i placed the script inside the player object with both rigidbody2d and boxcollider2d and yeah it works and all, it toggles both the button gameobjects which is what i was going for in a sense but i wanted it to use only one button. if you can help with this as well i would appreciate it.
//different button objects
public GameObject smithbutton;
public GameObject innbutton;
private void OnTriggerEnter2D(Collider2D col)
{
//debugs which collider player is in
if (col.gameObject.name == "Blacksmith")
{
Debug.Log("This is the Blacksmith");
}
if (col.gameObject.name == "Inn")
{
Debug.Log("This is the Inn");
}
}
private void OnTriggerStay2D(Collider2D col)
{
//once playerobject stays, button will toggle till player leaves
if (col.gameObject.name == "Blacksmith")
{
Debug.Log("still on the Blacksmith's door");
smithbutton.SetActive(true);
}
if (col.gameObject.name == "Inn")
{
Debug.Log("still on the Inn's door");
innbutton.SetActive(true);
}
}
private void OnTriggerExit2D(Collider2D col)
{
//once playerobject exits, button will toggle and disappear
if (col.gameObject.name == "Blacksmith")
{
smithbutton.SetActive(false);
}
if (col.gameObject.name == "Inn")
{
innbutton.SetActive(false);
}
}
There is no much you could do, as the function is quite simple. You could make it better, and still reduce some of the lines. Using tag instead of name will be future proof if you create more Inns or more blacksmiths. Using the collider call a method will let you extend the functionality with ease. I will usually add each of this checks to the Inn and Blacksmiths myself, and they will be looking for the player.
//different button objects
[SerializeField] private GameObject smithbutton;
[SerializeField] private GameObject innbutton;
private void OnTriggerEnter2D(Collider2D col)
{
//debugs which collider player is in
if (col.gameObject.tag == "Blacksmith")
{
ButtonActivationToggle(smithbutton, col);
}
if (col.gameObject.tag == "Inn")
{
ButtonActivationToggle(innbutton, col);
}
}
private void OnTriggerExit2D(Collider2D col)
{
//once playerobject exits, button will toggle and disappear
if (col.gameObject.tag == "Blacksmith")
{
ButtonActivationToggle(smithbutton, col);
}
if (col.gameObject.tag == "Inn")
{
ButtonActivationToggle(innbutton, col);
}
}
public void ButtonActivationToggle(GameObject button, Collider2D collider)
{
bool tmp = false;
tmp = button.activeInHierarchy ? false : true;
button.SetActive(tmp);
if (button.activeInHierarchy)
{
Debug.Log("This is the " + gameObject.collider.tag)
}
}
you dont need the OnTriggerStay, you can do that in OnTriggerEnter and get rid of the Stay function.
public Button mybtn;
bool isBlacksmith; // keep track of where you are (you can later make it an enum if there are more than 2 places and check that)
void Start()
{
//when the button is clicked buttonFunction will be called
mybtn.onClick.AddListener(buttonFunction);
}
private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.name == "Blacksmith")
{
Debug.Log("Entered Blacksmith's door");
mybtn.gameObject.SetActive(true);
isBlacksmith = true;
}
if (col.gameObject.name == "Inn")
{
Debug.Log("Entered Inn's door");
mybtn.gameObject.SetActive(true);
isBlacksmith = false;
}
}
private void OnTriggerExit2D(Collider2D col)
{
//once playerobject exits, button will toggle and disappear
if (col.gameObject.name == "Blacksmith" || col.gameObject.name == "Inn")
{
smithbutton.SetActive(false);
}
}
public void buttonFunction()
{
if (isBlacksmith)
Debug.Log("In Blacksmith");
else
Debug.Log("In Inn");
}
Related
is actually a rythm game and when a circle enter into a trigger we can make disapear the circle.
public class CursorPress : MonoBehaviour {
public bool canBePressed;
public KeyCode keyToPress;
void Update()
{
if (Input.GetKeyDown(keyToPress))
{
GameObject target = GameObject.Find("hitcircle_r");
if(target.tag == "Target")
{
if (canBePressed)
{
target.GetComponent<Animation> ().play("hitcircle_fading");
target.SetActive(false);
}
}
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.tag == "Target")
{
canBePressed = true;
}
}
void OnTriggerExit2D(Collider2D col)
{
if (col.gameObject.tag == "Target")
{
canBePressed = false;
}
}
}
I want that when the player press a key (keyToPress), a custom gameObject (hitcircle_r) gets a fade animation before disapearing, but idk how to do it, i tried a lot of code i found on the web, can someone helps me please ?
There are many ways to achieve what you want.
One would be to call a coroutine that fades deactivates your target after time.
If you are only doing fading style animations you should look into DOTween.
using System.Collections;
using UnityEngine;
public class CursorPress : MonoBehaviour
{
public bool canBePressed;
public KeyCode keyToPress;
void Update()
{
if (Input.GetKeyDown(keyToPress))
{
GameObject target = GameObject.Find("hitcircle_r");
if (target.tag == "Target")
{
if (canBePressed)
{
target.GetComponent<Animation>().Play("hitcircle_fading");
float hideTime = 0.5f; // the length of your animation
StartCoroutine(DeactivateTarget(target, hideTime));
}
}
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.tag == "Target")
{
canBePressed = true;
}
}
void OnTriggerExit2D(Collider2D col)
{
if (col.gameObject.tag == "Target")
{
canBePressed = false;
}
}
// coroutine to deactivate GameObject
private IEnumerator DeactivateTarget(GameObject targetGo, float hideDelay)
{
yield return new WaitForSeconds(hideDelay);
targetGo.SetActive(false);
}
}
I'm currently working on some type of LOD system where I have some ferns that have to be enabled and disabled. I'm using a cube for this process, so when when my character touches the cube the ferns meshrenderers will be disabled and when not touching it, it'll enable them. Now the part where I struggle, is when I have to enable/disable the meshrenderes of these gameobjects tagged with fern.
Here is my code so far:
public GameObject[] FernPlants;
public MeshRenderer MR;
// Start is called before the first frame update
void Start()
{
FernPlants = GameObject.FindGameObjectsWithTag("Fern");
}
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Player")
{
//Disable meshrenderers on FernPlants
}
}
private void OnTriggerExit(Collider other)
{
//Enable meshrenderers on FernPlants
}
Try with something like:
public GameObject[] FernPlants;
public MeshRenderer MR;
// Start is called before the first frame update
void Start()
{
FernPlants = GameObject.FindGameObjectsWithTag("Fern");
}
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Player")
{
//Disable meshrenderers on FernPlants
foreach(GameObject go in FernPlants)
{
go.GetComponent<MeshRenderer>().enabled = false;
}
}
}
private void OnTriggerExit(Collider other)
{
//Enable meshrenderers on FernPlants
foreach(GameObject go in FernPlants)
{
go.GetComponent<MeshRenderer>().enabled = true;
}
}
I have wrote a code that semi-works for me. Everything works aside from working animation.
What I'm trying to do is that when Player enters trigger, and if he/she presses E it will perform an animation. (Animation is working fine btw, so it's just code error?).
Here's what I got so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class barTrigger : MonoBehaviour {
// press shit to drink text
public GameObject drinkText;
// bottle
public GameObject alcBottle;
// drink animator
public GameObject animatorOjbect;
Animator drinkAmin;
public bool triggerIsOn;
// Use this for initialization
void Start () {
drinkAmin = animatorOjbect.GetComponent<Animator> ();
drinkText.SetActive(false);
alcBottle.SetActive(false);
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider other){
triggerIsOn = true;
if (other.gameObject.name == "vThirdPersonController") {
drinkText.SetActive (true);
}
if (triggerIsOn && Input.GetKeyDown (KeyCode.E)) {
drinkAmin.Play ("Dab");
alcBottle.SetActive (true);
}
}
void OnTriggerExit(Collider other){
if (other.gameObject.name == "vThirdPersonController") {
drinkText.SetActive (false);
alcBottle.SetActive (false);
}
}
}
OnTriggerEnter is called once and it will be hard to get press the E button and get Input.GetKeyDown(KeyCode.E) to detect that at the-same time. Checking the E input in the OnTriggerStay function is more appropriate for this but OnTriggerStay does not work sometimes so count it out. Although it's worth knowing that it exist.
Move Input.GetKeyDown(KeyCode.E) to the Update function which is called every frame then set it to true in the OnTriggerEnter function and false in the OnTriggerExit function. Below are the code that should be changed.
void Update()
{
if (triggerIsOn && Input.GetKeyDown(KeyCode.E))
{
Debug.Log("E button pressed");
drinkAmin.Play("Dab");
alcBottle.SetActive(true);
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "vThirdPersonController")
{
Debug.Log("Detected vThirdPersonController");
triggerIsOn = true;
drinkText.SetActive(true);
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.name == "vThirdPersonController")
{
Debug.Log("Lost vThirdPersonController");
triggerIsOn = false;
drinkText.SetActive(false);
alcBottle.SetActive(false);
}
}
Once you get that working, starting using the CompareTag function instead of gameObject.name as that is more proficient.
I'm making a classic trap where two walls come together to smash the player. To do this, I've created two separate tags, "Crush" and "Crush1", and assigned one tag to each wall. This is my code on my player class:
void OnCollisionEnter(Collision other)
{
if (other.transform.tag == "Crush" && other.transform.tag == "Crush1")
{
Die ();
}
}
I only want the player to be destroyed if both walls are touching the player at the same time. When I remove one of the tags in the parameter, the method works fine (only not how I want it). I'm sure there's a simple workaround here, I'm just not seeing it. Thanks for the help!
#Christiopher G is correct in saying you need to store flags as they hit you(and stop hitting you).
I think his is a little bloated though as a new class is not required, your current code is easily expanded to do what you want.
Note: Unity not available to be at the moment so untested.
bool wall1 = false;
bool wall2 = false;
void Update()
{
if( wall1 && wall2 )
{
Die();
}
}
void OnCollisionEnter(Collision other)
{
if (other.transform.tag == "Crush")
{
wall1 = true;
}
else if(other.transform.tag == "Crush1")
{
wall2 = true;
}
}
void OnCollisionExit(Collision other)
{
if (other.transform.tag == "Crush")
{
wall1 = false;
}
else if(other.transform.tag == "Crush1")
{
wall2 = false;
}
}
What you could do is create a single script with the following code and attach it to both your Wall objects:
public class WallScript : MonoBehaviour
{
[HideInInspector] //Optional Attribute
public bool collidedWithPlayer;
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.name == "Player")
{
collidedWithPlayer = true;
}
}
private void OnCollisionExit(Collision collision)
{
if(collision.gameObject.name == "Player")
{
collidedWithPlayer = false;
}
}
//We don't want "collidedwithPlayer" to remain true if either of the walls touches the player before both do so we call "OnCollisionExit" to set it to false.
}
Then do the following inside your player script:
private WallScript wall1Script;
private WallScript wall2Script;
private void Awake()
{
wall1Script = GameObject.Find("Wall1").GetComponent<WallScript>();
wall2Script = GameObject.Find("Wall2").GetComponent<WallScript>();
}
OR
private WallScript wall1Script;
private WallScript wall2Script
public GameObject wall1;
public GameObject wall2; //Assign GameObjects in Inspector
private void Awake()
{
wall1Script = wall1.GetComponent<WallScript>();
wall2Script = wall2.GetComponent<WallScript>();
}
Then inside the same script:
private void Update()
{
if(wall1Script.collidedWithPlayer && wall2Script.collidedWithPlayer)
{
//Do Something here
}
}
You know, when the player touch two walls.
function OnCollisionEnter will be execute twice.
the first time, other.transform.tag == "Crush" is true.
the second time, other.transform.tag == "Crush1" is true.
in OnCollisionEnter, other have only one tag.
It will never be true that tag == tag1 && tag == tag2 if tag1 != tag2
I'm facing the problem that i wish to destroy a parent object but i couldn't do so.
i wish to destroy User01 while bullet hit any of these child.
My code was as below.
JS:
function OnControllerColliderHit(col:ControllerColliderHit){
if(col.gameObject.tag == "Bullet"){
Destroy(col.transform.parent.gameObject);
}
}
C#:
public class PlayerDoe : MonoBehaviour {
private GameObject par;
// Use this for initialization
void Start () {
par = transform.parent.gameObject;
}
// Update is called once per frame
void Update () {
}
void OnCollisionHit(Collision col){
if (col.gameObject.tag == "Bullet") {
Destroy(par);
}
}
}
I believe you need to use OnCollisionEnter, instead of OnCollisionHit.
There is no OnCollisionHit(). You want to use OnCollisionEnter
void OnCollisionEnter(Collision collision)
{
if(col.gameObject.tag == "Bullet")
Destroy(transform.parent.gameObject);
}