I'm working on a 2D game in Unity 3D, v4.5. I have added some sprites to the Hierarchy. How do I add a button to the hierarchy? I already have a designated button.png that should display as the button. Should I turn a sprite into a button?
What I tried so far:
Someone noted GUI.Button, but
1: It has to be done in code - I assume we can add buttons to the game UI inside Unity GUI (??)
2: Even using GUI.Button from script, that class adds a border around the specified texture. I also haven't figured out how to use the existing image and size (width/height) of the sprite as the texture that is sent to GUI.Button.
you can useOnGUI for button and to disappear the rectangle you have to make a new GUIStyle
private GUIStyle testStyle = new GUIStyle();
public Texture2D Texture1;
void OnGUI(){
if( GUI.Button( new Rect (0, 0, 100, 100) , texture1 ,testStyle) )
{
//doSomething if clicked on
}
}
if you dont want that you can do a raycasting your selfand give your buttons tags like below
void Update () {
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) {
if(hit.collider.tag=="play")
//DoSomething
}
}
}
in unity 4.6 UI you can add listeners to buttons in script like below
private Button MyButton = null; // assign in the editor
void Start()
{
MyButton.onClick.AddListener(() => { somefunction(); });
}
Related
I am fairly new to Unity and am currently working on a small project.
My problem is this.
I want to display text when I click on the cube.
I have a total of four different cubes, all of which should display different text when clicked.
The solution I have so far works, but of course now when I click on the cubes the same text comes up and if I assign each cube its own text they all appear at once.
The cubes should also rotate and when clicked on just stop and display the text.
I tried it with the Event Trigger System and assign different texts, but without success.
Any suggestion for a solution?
I tried it with the Event Trigger System and assign different texts, but without success.
Any suggestion for a solution?
enter image description here
You are using input.GetMouseButtonDown, when you click anywhere all
the boxes run the same code, you don't specify which box is clicked
you only looking for a click, I suggest you use raycast to send a
ray to detect which box you are clicking and run ,
Add this script to the camera or player and give all the boxes gameobject a "Box" Tag :
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Transform objectHit = hit.transform;
if (objectHit.CompareTag("Box"))
{
objectHit.GetComponent<Rotator>().RotateObject();
}
}
}
}
add this function to the Rotator Script and remove the code from update :
public void RotateObject()
{
if (rotateObject)
{
rotateObject = false;
Text.SetActive(true);
}
else
{
rotateObject = true;
Text.SetActive(false);
}
}
}
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
I have 3 Game Objects. These 3 Game Objects are my right , up and left buttons.
But I have no idea to control and check which of them clicked to action on player !
Note : I can do this by creating special C# for each of game objects
by using OnMouseDown Method but I want do this in one Script file
attached to player .
and this is one of my Game Objects for Control Player
Note : I can do this by creating special C# for each of game objects
by using OnmouseDown Method but i want do this in one Script file
attached to player .
This shouldn't be a problem at-all. You can have two scripts communicate with each other.
Method 1:
Notify the PlayerController script when there is a click action from other script.
Attach to each GameObject to detect click on. It sends the GameObject that was clicked to your PlayerController script.
public class ClickDetector: MonoBehaviour
{
PlayerController playerController;
void Start()
{
playerController = GameObject.Find("GameObjectPlayerControlIsAttachedTo").GetComponent<PlayerController>();
}
void OnMouseDown()
{
//Notify our PlayerController script that there was a click
playerController.OnGameObjectClicked(this.gameObject);
}
}
Add this to your PlayerController script. It receives the GameObject that was clicked. You can compare with the GameObject name or tag. I suggest you go with a tag.
public class PlayerController: MonoBehaviour
{
public void OnGameObjectClicked(GameObject objClicked)
{
Debug.Log("There was a click from: "+objClicked.name);
if (objClicked.CompareTag("right"))
{
//Your code
}
else if (objClicked.CompareTag("left"))
{
//Your code
}
else if (objClicked.CompareTag("up"))
{
//Your code
}
}
}
Method 2:
Do everything in one script (PlayerController).
You can use a raycast. I suggest you use tag to compare which gameobject is clicked. Create 3 tags(right,left and up) from the Editor and put each GameObject to the right tag. If you don't want to use tag, you can replace the if (rayCastHit.collider.CompareTag("up")) with if (rayCastHit.collider.name=="up").
void Update()
{
//Check if Mouse Button is pressed
if (Input.GetMouseButtonDown(0))
{
//Raycast from mouse cursor pos
RaycastHit rayCastHit;
Ray rayCast = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(rayCast, out rayCastHit))
{
if (rayCastHit.collider.CompareTag("right"))
{
//Your code
}
else if (rayCastHit.collider.CompareTag("left"))
{
//Your code
}
else if (rayCastHit.collider.CompareTag("up"))
{
//Your code
}
}
}
}
EDIT:
After updating your question, you need to attach a collider to your GameObjects for raycast to work. Attach Box Collider 2D to each of the 3 GameObjects.
Also, since this is a 2D sprite, The code for Method 2 changes a little bit:
if (Input.GetMouseButtonDown(0))
{
Vector2 ray = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D rayHit = Physics2D.Raycast(ray, Vector2.zero);
if (rayHit)
{
if (rayHit.collider.CompareTag("up"))
{
}
}
}
Finally, from what you are doing, it looks like you need a Virtual JoyStick and you are current doing it wrong. The current solution should work for you but the right way to do this is with the UI system (Image component).
I've got a draggable class that works great for dragging entire sprites and I'm trying to modify it to register dragging only within the defined 2D polygon collider component of the sprite object. I'm having a really hard time getting the drag to only register when I click within the boundaries of the polygon collider. Right now it's still dragging wherever I click-drag on the sprite including outside the boundaries of my polygon collider. I could really use some guidance on this. I've also attached an image to illustrate what I'm trying to achieve. Thanks!
PolygonCollider2D collider;
void Start ()
{
collider = transform.GetComponent<PolygonCollider2D>();
}
public void OnDrag (PointerEventData eventData)
{
Vector3 mousePosition = new Vector3(eventData.position.x, eventData.position.y, 0);
collider.transform.position = mousePosition;
if(transform.parent.gameObject == partsPanel)
transform.SetParent(dragLayer.transform);
if(transform.parent.gameObject == buildBoard)
transform.SetParent(dragLayer.transform);
}
AFAIK, The polygon collider we added to the sprite is editable. Goto inspector, collider component and there is a button which allow editing collider area. Adjust the points of this collider to cover just the desired area. This way only the desired area will receive touch events.
Ok, I know this is very old thread, but I had similar problem and I found a solution so I will post it here :)
Just create a class with this code and put it on your object
using UnityEngine;
[RequireComponent(typeof(RectTransform), typeof(Collider2D))]
public class Collider2DRaycastFilter : MonoBehaviour, ICanvasRaycastFilter
{
Collider2D myCollider;
RectTransform rectTransform;
void Awake()
{
myCollider = GetComponent<Collider2D>();
rectTransform = GetComponent<RectTransform>();
}
public bool IsRaycastLocationValid(Vector2 screenPos, Camera eventCamera)
{
var worldPoint = Vector3.zero;
var isInside = RectTransformUtility.ScreenPointToWorldPointInRectangle(
rectTransform,
screenPos,
eventCamera,
out worldPoint
);
if (isInside)
isInside = myCollider.OverlapPoint(worldPoint);
return isInside;
}
}
Please keep in mind that I'm new to unity. I created an 2D android game app.
I created a start button( from an image) and attacted a Box colider, and a C# script to it.
When I click the "button" I want the program to move to the next "Level", that Works except that I want it to only Work if i click the object and not everywhere on the game.
This is the C#:
using UnityEngine;
using System.Collections;
public class StartGame : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0)) {
Application.LoadLevel("Game");
}
}
}
I searched alot about this and maybe people say that to solve this you have to use, Ray and RaycastHit But I cant get that to Work either.
Here is what I tried to with Ray & RaycastHit
// Update is called once per frame
void Update () {
if ((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) || (Input.GetMouseButtonDown(0)))
{
RaycastHit hit;
Ray ray;
#if UNITY_EDITOR
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
#elif (UNITY_ANDROID || UNITY_IPHONE || UNITY_WP8)
ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
#endif
if(Physics.Raycast(ray, out hit))
{
Application.LoadLevel("Game");
}
}
}
Any help would be so appriciated.
Probably the easiest way is to add box collider and script component including function below to the gameobject.
void OnMouseOver()
{
if (Input.GetMouseButtonDown(0))
{
Application.LoadLevel("Game");
}
}
Edit:
I'm guessing that the original code is not working on your scene, because you are using box collider 2d. Physics.Raycast is testing against 3D colliders. When I run it with the 3D version box collider it works fine.