hide and show button in unity 3d - c#

Hello I am making a tile related game in unity 3d where player jumps on the right tile and I am also making hint button so that player uses those hints but the issue is I want to hide and show button when player jumps on the first tile and when my player moves onto the next tile it will disable my button and show another button.
I have tried canvas group and sorting layer but nothing happens.

Off the top of my head, it looks like you would need to put an new game object on top of the tiles to act as a collider.
You can then call button game object enable/disable within the native trigger enter/stay/leave functions (Add these functions within a script attached to your created collider) e.g.:
// change these functions to 3D equivalent if project is 3D
void OnTriggerEnter2D(Collider2D col)
{
if (col.tag == "myplayertag")
{
myButton.gameObject.SetActive(true);
}
}
void OnTriggerStay2D(Collider2D col)
{
if (col.tag == "myplayertag")
{
myButton.gameObject.SetActive(true);
}
}
public void OnTriggerExit2D(Collider2D col)
{
if (col.tag == "myplayertag")
{
myButton.gameObject.SetActive(false);
}
}
Make sure to mark said collider object as trigger like so:

Related

HitTest is obsolete, what is the new format to get my buttons working again with UI image(once GUITexture)?

I'm having issues trying to resolve this issue I have from migrating my old Unity5 game to Unity 2020. I've got everything running again, except for this issue with my buttons not working because of an update to "HitTest" being obsolete. What can I do to make this work without completely starting from scratch?
foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Stationary && hitButton.HitTest(touch.position))
{
GetComponent<Rigidbody2D>().MoveRotation(80);
}
I would make a Canvas as a child of the gameobject with the rigidbody2d/collider2d components, then put the button on that canvas, and then in your code above, keep a reference to the canvas and the button that lives there.
Then, you can use GraphicRaycaster.Raycast. Modified version of the source code in the Unity Docs:
// Attach this script to your Canvas GameObject.
// Also attach a GraphicsRaycaster component to your canvas by clicking the
// Add Component button in the Inspector window.
// Also make sure you have an EventSystem in your scene
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
public class RaycasterTester : MonoBehaviour
{
GraphicRaycaster m_Raycaster;
void Start()
{
//Fetch the Raycaster from the GameObject (the Canvas)
m_Raycaster = GetComponent<GraphicRaycaster>();
}
public bool TestTouch(Touch touch, GameObject target)
{
//Set up the new Pointer Event
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
//Set the Pointer Event Position to that of the touch position
pointerEventData.position = touch.position;
//Create a list of Raycast Results
List<RaycastResult> results = new List<RaycastResult>();
//Raycast using the Graphics Raycaster and touch position
m_Raycaster.Raycast(pointerEventData, results);
foreach (RaycastResult result in results)
{
if (result.gameObject == target) return true;
}
return false;
}
}
So basically the hierarchy looks something like this at runtime:
Flipper object [ Rigidbody2D, Collider2D, questionScript (references RaycasterTester and Button) ]
L Canvas object [ Canvas (world space), GraphicRaycaster, RaycasterTester ]
L Button object [ Button, Image, hitButtonScript (?) ]
(somewhere in scene) [ EventSystem ]
Then, in the Question Script, get a reference to the instance of the above script then call the TestTouch method:
foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Stationary
&& raycasterTester.TestTouch(touch, hitButton.gameObject))
{
GetComponent<Rigidbody2D>().MoveRotation(80);
// break to avoid being turned by multiple touches?
// break;
}
}
By the way, if the question code is happening in Update, it might be best to call GetComponent<Rigidbody2D> in Start (or, if the Rigidbody2D is ever removed and/or replaced, at those times as well) and cache the results, since it can be an expensive operation.
Actually better than checking this manually would indeed be a UI.Button + additionally implementing a custom extension using the IPointerDownHandler and IPointerUpHandler etc interfaces (note: the linked API is 2018, but this applies to 2020 as well, they just moved the API to a package and there it is not so well explained) like
public class HoldButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler
{
// Called once when the button goes down (comparable to GetKeyDown)
public UnityEvent OnButtonDown;
// Called every frame while the button is pressed (comparable to GetKey)
public UnityEvent WhilePressed;
// Called once when the button goes up (comparable to GetKeyUp)
public UnityEvent OnButtonUp;
// Called if you hover with the mouse or drag an existing touch into the button
public void OnPointerEnter(PointerEventData pointerEventData)
{
// Not sure if needed for OnPointerExit to work, doing nothing else
}
// Called when mouse or touch leaves the button
public void OnPointerExit(PointerEventData pointerEventData)
{
OnButtonUp.Invoke();
StopAllCoroutines();
}
// Called if you press the mouse or begin a touch over this button
public void OnPointerDown(PointerEventData pointerEventData)
{
OnButtonDown.Invoke();
StartCoroutine (WhilePressedRoutine());
}
// Called if you release mouse or touch over this button
public void OnPointerUp(PointerEventData pointerEventData)
{
OnButtonUp.Invoke();
StopAllCoroutines();
}
private IEnumerator WhilePressedRoutine()
{
while(true)
{
WhilePressed.Invoke();
yield return null;
}
}
}
In these UnityEvents you can reference your handler methods just like in the UI.Button.onClick via the Inspector or on runtime via script.
So you can either attach this on a UI element (like a Button) and let the EventSystem of the scene call the pointer handlers.
Or you can even attach this to normal 3D objects! In such case this requires additionally
A collider on your 3D object
A PhysicsRaycaster component on your Camera
Or for a 2D object accordingly
A Collider2D on your object
A Physics2DRaycaster on your Camera
These interfaces work for both, mouse and touch input (except for the pointer enter probably because a touch can't just hover - at least not on all phones ;) )

Unity player/sprite becomes invisible after transform.position change. How do I prevent the disappearance of the player?

I'm trying to make a game with "Death Blocks" that move the player to the respawn point after triggering the OnTrigger method. Here is the code:
public class DeathBlock : MonoBehaviour
{
public GameObject respawnPoint;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.name == "Player")
{
collision.gameObject.transform.position = respawnPoint.transform.position;
}
}
}
Edit: I found out the problem. The camera was moving on the Z axis as well so clamp the cameras Z axis position to whatever you had it to on scene startup (-10 for me), and the character remains on screen.
Do either the respawn or the player have a parent game object? When you change the transform.position you change the local transform, if there is a parent object it will multiply the rotation/scale of the parent. You can also while the game is running click on 'scene' in the editor, then click on the player in the inspect, hit 'f' and find out where it is or what it doing, and whether its set active.

Check which collider trigger in Unity3D

Context
I'm developing an AbstractAliveEntity, which have basically three functions:
Sight: Detect interactable objects. (Collider + Raycast)
Detection: Detect anothers AbstractAliveEntities (Collider + Raycast)
Hearing: Hear noises (Collider)
Currently i'm creating via script empty gameObjects with these colliders.
What i want
I want to know which collider was trigger in OnTriggerEnter and OnTriggerExit
Code
Creating the Sphere collider
private void Start() {
// Creating empty gameObject
sightGameObject = new GameObject("Sight");
sightGameObject.transform.parent = transform;
sightGameObject.transform.localPosition = new Vector3(0, 0, 0);
// Add Component Sphere
_sightInteractable = sightGameObject.AddComponent<SphereCollider>();
// _sightInteractable = gameObject.AddComponent<SphereCollider>();
_sightInteractable.radius = radiusInteractableDetection;
_sightInteractable.isTrigger = true;
}
Detecting
private void OnTriggerEnter(Collider other) {
// How can i detect which collider was?? this.gameObject = "Player" (i want "Sight")
}
Since Unity is originally designed around a component based approach my approach would be to split up the three separate "detection" systems into separate GameObjects with their own collider and script.
AliveEntity
SightController
ColliderA
DetectionController
ColliderB
HearingController
ColliderC
Then you can use the OnTrigger in each separate script to fire a notification to the main AbstractAliveEntity which then handles them on a case by case basis.
Main Script
OnSight(Collider other) {
// Do sight related actions here
}
OnDetection(Collider other) {
// Do detetction related actions here
}
OnHearing(Collider other) {
// Do hearing related actions here
}
Then for each respetive detector:
// reference to master script
public AbstractAliveEntity aae;
OnTriggerEnter(Collider other) {
// replace function with whatever you want to use
aae.OnSight(other)
}
The Added advantage here is that you are now also free to design 'blind' or 'deaf' Entities without all too much hassle. (You simply do not add the respective components)
other.gameObject to get the gameObject the other collider is attached to.
Check unity documentation about collider here for more info.

unity2d prevent ui button from being clicked when raycast2d hit

I have a gameobject with collider2d which was designed to be clickable, and I also Have an UI button which will follow the camera while player moving, the thing is they may overlap sometimes, and when they overlap, when user click the overlap area, I am sure that user want to click the object (which was do by raycast2d hit) so I should prevent the button to be clicked.
The script for the raycast implantation of clickable gameobject is as following:
private void checkTouch()
{
if (Input.touchCount > 0 || Input.GetMouseButtonDown(0))
{
Vector2 rayPos = new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
RaycastHit2D hit = Physics2D.Raycast(rayPos, Vector2.zero, 0f);
if (hit)
{
Debug.Log(hit.collider.gameObject + "is hit");
IInputBehavior inputBehavior = hit.collider.gameObject.GetComponent<IInputBehavior>();
//IInputVehavior was a self-desgined C# interface which has a `OnClick()` method.
if (inputBehavior != null)
{
//here we should prevent the UIButton to be clicked, but how?
inputBehavior.OnClick();
}
}
}
}
Okay so I'm at work so I can't give you the exact code but I can point you in the right direction. When you made the canvas originally it should have generated an event system ( as a game object in the scene somewhere ), you need to reference this in your game object that you want to not click when the ui is over it.
In your game object it's something like this:
if(GetComponent<EventSystem>().IsPointerOverGameObject) {
// The mouse is obscured by a UI element
} else {
// The mouse is not over a UI element
}
https://docs.unity3d.com/ScriptReference/EventSystems.EventSystem.IsPointerOverGameObject.html

C# OnTriggerEnter, Pick up an object. OnTriggerExit, drop the object

I'm trying to get my sprite to pick up a cube when it encounters one, if it isn't already carrying one. If it is, drop the cube it is carrying.
This is what I have right now.
void OnTriggerEnter(Collider other)
{
if (other.Tag == "cube")
{
other.Transform.position = this.Transform.position;
}
}
I tried telling the cube to become a child of the sprite. Wasn't working. All this does is put the cube to the sprites position when the trigger is entered, but the cube stays in that position while the sprite wonders off.
With this code,you can change the cubes position to the players position just one time.If you want cube to move with your character than you should make child of your character.
Try using this code;
void OnTriggerEnter(Collider other)
{
if (other.tag == "cube")
{
other.transform.parent = gameObject.transform;
}
}
PS:I don't have access to Unity now.Some coding mistakes can occur.

Categories

Resources