I want to move an image UI when Canvas is set on Screen Space - Camera
However, nothing seems to work. I've tried the following things:
public void OnDrag(PointerEventData eventData)
{
Vector3 screenPoint = Input.mousePosition;
screenPoint.z = 0.13f; //distance of the plane from the camera
icon.transform.position = Camera.main.ScreenToWorldPoint(screenPoint);
}
Makes the image move out of the screen instantly.
public GameObject Target;
private EventTrigger _eventTrigger;
void Start ()
{
_eventTrigger = GetComponent<EventTrigger>();
_eventTrigger.AddEventTrigger(OnDrag, EventTriggerType.Drag);
}
void OnDrag(BaseEventData data)
{
PointerEventData ped = (PointerEventData) data;
Target.transform.Translate(ped.delta);
}
same story, image dissapires and moves out of the screen.
public void OnDrag(PointerEventData eventData)
{
Vector3 clickedPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
InventoryParent.transform.position = clickedPosition;
}
as the above.
Anyone has idea on how can I do accurate mouse dragging UI with Screen-Space Camera? Doing it with overlay works fine.
Change your UI element RectTransform anchors to:
and add this script to your UI element object:
RectTransform rectT;
void Start()
{
EventTrigger trigger = GetComponent<EventTrigger>();
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = EventTriggerType.Drag;
entry.callback.AddListener((data) => { OnDragDelegate((PointerEventData)data); });
trigger.triggers.Add(entry);
rectT = GetComponent<RectTransform>();
}
public void OnDragDelegate(PointerEventData data)
{
rectT.anchoredPosition = data.position;
}
You also need the EventTrigger component on your UI element object.
Related
So I was working on a Unity 2D game project, where you are supposed to throw stuff around using mouse and then collecting keys and unlocking doors. I got some help to be able to get the dragging, but basically whenever you rise your left click, the object would just fall to the ground. I'd like it to be affected by G-forces, that way that when you spin your mouse the object would spin around the cursor and when you make mouse movement and release left click the object would fly depending on the mouse movements.
I found one similar to this, but the code wasn't anything I could understand and all the custom stuff I have made to be able to unlock the door didn't seem to fit well with that.
{
public static GameObject HeldItem;
private bool isBeingHeld = false;
void Update()
{
if(isBeingHeld == true)
{
Vector3 mousePos;
mousePos = Input.mousePosition;
mousePos = Camera.main.ScreenToWorldPoint(mousePos);
this.gameObject.transform.localPosition = new Vector3(mousePos.x, mousePos.y, 0);
}
}
private void OnMouseDown()
{
if(Input.GetMouseButtonDown(0))
{
HeldItem = this.gameObject;
Vector3 mousePos;
mousePos = Input.mousePosition;
mousePos = Camera.main.ScreenToWorldPoint(mousePos);
isBeingHeld = true;
}
}
private void OnMouseUp()
{
isBeingHeld = false;
}
}```
Also sorry if this ain't the greatest explaining, but I have never seen my self as any how good at it.
The code you have shared here makes an object follow your mouse directly, but would not keep any of the velocity of that movement because you're directly controlling the transform's position.
For drag and drop, the most common way to make this work is what you have here.
For drag and throw, you'll need to implement this with physics in mind. There are many ways you could do this, but this sounds like the behavior you want:
Have the object "chase" your mouse around the screen in real-time using forces:
This would involve using OnMouseDrag
[RequireComponent(typeof(Collider2D))]
public class DragAndThrow : MonoBehaviour
{
Rigidbody2D rb2d;
Vector3 mousePos;
float dragIntensity = 1.0f;
bool dragging = false;
void Start()
{
rb2d = gameObject.GetComponent<Rigidbody2D>();
}
void OnMouseDrag()
{
dragging = true;
mousePos = Input.mousePosition;
mousePos.z = 0;
mousePos = Camera.main.ScreenToWorldPoint(mousePos);
}
void OnMouseUp()
{
dragging = false;
}
FixedUpdate()
{
if(!dragging)
return;
Vector3 dragVector = (mousePos - rb2d.position);
dragVector.z = 0f;
rb2d.AddForce(dragVector * dragIntensity);
//The further your mouse is from the objet, the greater the force applied
}
}
This code was written freehand, so please let me know if there are any syntax errors.
Ok, so I have a standard joystick downloaded from Unity asset store, script here (isn't that long):
// Implement IPointerDownHandler, IPointerUpHandler, IDragHandler to subscribe to pointer events
public class Joystick : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler {
public delegate void JoystickAction(Vector2 joystickAxes);
public static event JoystickAction JoystickMoved;
public Vector2 joystickAxes;
public bool usingJoystick;
private Image bgImg;
private Image stickImg;
private RectTransform bgTransform;
private RectTransform stickTransform;
// The first tap is treated similar to any following detection of a drag
public virtual void OnPointerDown(PointerEventData ped) {
usingJoystick = true;
OnDrag (ped);
}
public virtual void OnPointerUp(PointerEventData ped) {
usingJoystick = false;
joystickAxes = stickImg.GetComponent<RectTransform> ().anchoredPosition = Vector2.zero;
//joystickAxes = new Vector2(Screen.height / 2, Screen.width/2);
if (JoystickMoved != null) JoystickMoved (Vector2.zero);
}
public virtual void OnDrag(PointerEventData ped) {
Vector2 rectPos;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
bgImg.rectTransform,
ped.position,
ped.enterEventCamera,
out rectPos)) { // Check if the pointer is positioned on the joystick
// Clamp the position to be inside the image bounds, prevents dragging beyond the image to get higher values.
Vector2 clampedPos = GetClampedPosition (rectPos);
// Normalize the joystick axes to be between -1 and 1.
joystickAxes = new Vector2 (
clampedPos.x / (bgTransform.rect.width / 2f),
clampedPos.y / (bgTransform.rect.height / 2f));
// Set the position of the inner joystick.
if (joystickAxes.magnitude > 1f) { // Normalizing the clampedPos constrains the joystick positions to a circle
stickImg.GetComponent<RectTransform> ().anchoredPosition = clampedPos.normalized * stickTransform.rect.width;
} else {
stickImg.GetComponent<RectTransform> ().anchoredPosition = clampedPos;
}
}
}
private Vector2 GetClampedPosition(Vector2 pos) {
Vector2 bgMin = bgTransform.rect.min;
Vector2 bgMax = bgTransform.rect.max;
return new Vector2 (
Mathf.Clamp (pos.x, bgMin.x, bgMax.x),
Mathf.Clamp (pos.y, bgMin.y, bgMax.y));
}
// Use this for initialization
void Start () {
joystickAxes = new Vector2 ();
bgImg = GetComponent<Image> ();
stickImg = transform.GetChild (0).GetComponent<Image> ();
bgTransform = gameObject.GetComponent<RectTransform> ();
stickTransform = transform.GetChild (0).GetComponent<RectTransform> ();
}
void Update() {
if (usingJoystick && JoystickMoved != null) {
JoystickMoved (joystickAxes);
}
}
}
This relies on an image object on a canvas and another image for the knob. as pictured:
This all works well, however I want the joystick to BE the screen, meaning the outside bounds for the knob aren't the background image but the screen bounds itself.
Ive tried scaling the background image to the screen using rh canvas, etc but this makes the inputAxes values way off. How can I do this?
I want to keep this script, just tweak it so the background "image"/bounds are the screen, whatever size that is.
I can't get my Gear VR touchpad to work - I'm just trying to move the camera position on touch. I've tried both pieces of code below:
public Camera cam;
void Update()
{
if (Input.GetMouseButton (0))
{
cam.transform.position = new Vector3(-100f, -100f, -100f);
}
}
and
void Start ()
{
OVRTouchpad.Create();
OVRTouchpad.TouchHandler += HandleTouchHandler;
}
void HandleTouchHandler (object sender, System.EventArgs e)
{
OVRTouchpad.TouchArgs touchArgs = (OVRTouchpad.TouchArgs)e;
if(touchArgs.TouchType == OVRTouchpad.TouchEvent.SingleTap)
{
cam.transform.position = new Vector3(-100f, -100f, -100f);
}
}
My script is attached to the OVRPlayerController
You can't move the VR Camera, it's the SDK that determine the Camera position.
In order to move your camera you can just make a new GameObject as a parent of your Cam then move the parent GameObject (here ParentCamera):
public GameObject ParentCamera;
void Update()
{
if (Input.GetMouseButton (0))
{
cam.transform.position = new Vector3(-100f, -100f, -100f);
}
}
I am making a 2D platformer in Unity for iOS, and I need to make buttons so the user can move, but for some reason, the script I made is not working. Also, the script I am putting in is just for the Left button, but the Right and Jump scripts work the same way.
Code:
using UnityEngine;
using System.Collections;
public class Left : MonoBehaviour {
public GameObject player;
public GameObject button;
void Start () {
}
void Update () {
if (Input.GetKey (KeyCode.A)) {
player.GetComponent<PlayerAnimator>().animationState = MovementState.moveLeft;
player.transform.position+=Vector3.left / 30;
}
if (Input.touchCount > 0){
foreach(Touch touch in Input.touches){
Collider2D col = button.GetComponent<Collider2D>();
Vector3 tpos = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 0));
if(col.bounds.Contains(tpos)){
Debug.Log ("left");
player.GetComponent<PlayerAnimator>().animationState = MovementState.moveLeft;
player.transform.position+=Vector3.left / 30;
}
}
}
}
void OnMouseOver(){
Debug.Log ("left");
player.GetComponent<PlayerAnimator>().animationState = MovementState.moveLeft;
player.transform.position+=Vector3.left / 30;
}
void OnMouseUp(){
player.GetComponent<PlayerAnimator> ().animationState = MovementState.idleLeft;
}
}
Don't use OnMouseOver for android application. It isn't usable on touch devices. But instead of it, OnMouseDrag function will work.
void OnMouseDrag(){
Debug.Log ("left");
player.GetComponent<PlayerAnimator>().animationState = MovementState.moveLeft;
player.transform.position+=Vector3.left / 30;
}
Edit: Because OnMouseOver is called when position of mouse is over object but not clicked. Otherwise OnMouseDrag is called when position of mouse is over object and clicked. In mobile devices OnMouseOver situation isn't possible.
Hoping someone has a quick answer for this one as I haven't been able to figure this out. Rather than have the image jumping to center itself on the mouse cursor, I'd like to be able to drag the image from any place on the image without the jump. I know it has something to do with referencing the mouse position against the image or reseting the origin point of the image to the mouse location, but I don't know how to code it. Has anyone done this already? Using C#.
Vector3 partsPanelScale;
public Vector3 buildPanelScale;
public Transform placeholderParent = null;
public Transform parentToReturnTo = null;
GameObject placeholder = null;
public GameObject animalPart;
public GameObject trashCan;
public GameObject partsPanel;
public GameObject partsWindow;
GameObject buildBoard;
GameObject dragLayer;
private float _mX; // holds current eventData.position.x
private float _mY; // holds current eventData.position.y
private float _pmX;// holds previous eventData.position.x
private float _pmY;// holds previous eventData.position.y
void Start ()
{
dragLayer = GameObject.FindGameObjectWithTag("DragLayer");
buildBoard = GameObject.FindGameObjectWithTag("Board");
partsPanel = GameObject.FindGameObjectWithTag("Parts");
partsWindow = GameObject.FindGameObjectWithTag("PartsWindow");
trashCan = GameObject.FindGameObjectWithTag("Trash");
}
#region IPointerClickHandler implementation
public void OnPointerClick (PointerEventData eventData)
{
if(transform.parent.gameObject == buildBoard)
{
transform.SetAsLastSibling();
}
}
#endregion
#region IBeginDragHandler implementation
public void OnBeginDrag (PointerEventData eventData)
{
// each frame updates the current position of the mouse.
_mX = eventData.position.x;
_mY = eventData.position.y;
// create placeholder gap and hold correct position in layout
placeholder = new GameObject();
placeholder.transform.SetParent(transform.parent);
placeholder.transform.SetSiblingIndex(transform.GetSiblingIndex());
if(transform.parent.gameObject == partsPanel)
{
partsPanelScale = transform.localScale;
}
parentToReturnTo = transform.parent; // store current parent location
placeholderParent = parentToReturnTo; // set placeholder gameobject transform
GetComponent<CanvasGroup>().blocksRaycasts = false; // turn off image raycasting when dragging image in order to see what's behind the image
}
#endregion
#region IDragHandler implementation
float distance = 0;
public void OnDrag (PointerEventData eventData)
{
// Divided the difference by 6 to reduce the speed of dragging.
transform.position = new Vector3
(
(_pmX - _mX)/6 + transform.position.x,
(_pmY - _mY)/6 + transform.position.y,
distance
);
// Vector3 mousePosition = new Vector3(eventData.position.x, eventData.position.y, distance);
// Vector3 objPosition = Camera.main.ViewportToScreenPoint(mousePosition);
// transform.position = mousePosition; // set object coordinates to mouse coordinates
if(transform.parent.gameObject == partsPanel)
{
transform.SetParent(dragLayer.transform); // pop object to draglayer to move object out of partsPnael
}
if(transform.parent.gameObject == buildBoard)
{
// Constrain drag to boundaries of buildBoard Code
}
}
#endregion
#region IEndDragHandler implementation
public void OnEndDrag (PointerEventData eventData)
{
// end of the drag. set the previous position.
_pmX = _mX;
_pmY = _mY;
transform.SetParent(parentToReturnTo); // Snaps object back to orginal parent if dropped outside of a dropzone
transform.SetSiblingIndex(placeholder.transform.GetSiblingIndex()); // Returns card back to placeholder location
GetComponent<CanvasGroup>().blocksRaycasts = true; // turn Raycast back on
Destroy(placeholder); // kill the placeholder if object hits a drop zone or returns to parts panel
if(transform.parent.gameObject == buildBoard)
{
// Debug.Log ("Your sprite is now on the " + transform.parent.name);
transform.localScale = buildPanelScale;
transform.SetAsLastSibling(); // always place last piece on top
}
if(transform.parent.gameObject == partsPanel)
{
transform.localScale = partsPanelScale;
}
}
#endregion
To drag correctly you need both Previous and Current position of the mouse.
Because each time you move mouse the Image should Move a bit (at x and y coordinate) from its previous position.
If you just use the current position and directly set it to image the resault will be jump over the screen.
You have to Transform the transformation of image by getting differences of previous and current position (x2 - x1 , y2 - y1).Then set the Final transformation to the Image transform.
You also need MouseOver event to update the positions. (orMouseMove)
private double _mX; // holds current eventData.position.x
private double _mY; // holds current eventData.position.y
private double _pmX;// holds previous eventData.position.x
private double _pmY;// holds previous eventData.position.y
// each frame updates the current position of the mouse.
private void MouseOver(PointerEventData eventData)
{
_mX = eventData.position.x;
_mY = eventData.position.y;
}
public void OnDrag (PointerEventData eventData)
{
transform.position = new Vector3D((_pmX - _mX)/6 + transform.position.x,
(_pmY - _mY)/6 + transform.position.y, distance);
// Divided the difference by 6 to reduce the speed of dragging.
//...
// end of the drag. set the previous position.
_pmX = _mX;
_pmY = _mY;
}
Note that class names and events i have used may differ from unity3d.
If you drag from right to left but image goes from left to right replace _pmX - mX with _mX - _pmX.
If you drag from up to down but image goes from down to up replace _pmY - mY with _mY - _pmY.