Reputation: 47
I am making a simple puzzle game in Unity. I have two objects and two targets.- I wrote script to drag my objects to their target location. I want my objects to snap at a different locations. My code is not letting me drag the game object as I wanted. I can only move one of the objects even if I move it. I can't drag it. It just appears at target position after a second it jumps to other object's target location.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class moveObject : MonoBehaviour
{
[SerializeField] private Transform objectPosition;/// target position
private Vector3 initialPosition; ///objects return position if placed wrong
private float deltaX, deltaY;
public static bool correctPosition; /// lock item if it is snapped to true location
public float snapdifficulty; /// snapping range
void Start()
{
initialPosition = transform.position;
}
void Update()
{
if (Input.touchCount > 0 && !correctPosition)
{
Touch touch = Input.GetTouch(0);
Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
Ray raycast = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
RaycastHit raycastHit;
switch (touch.phase)
{
case TouchPhase.Began:
if (Physics.Raycast(raycast, out raycastHit))
{
if (raycastHit.collider.name == this.name)
{
deltaX = touchPos.x;
deltaY = touchPos.y;
}
}
break;
case TouchPhase.Moved:
if (Physics.Raycast(raycast, out raycastHit))
{
if (raycastHit.collider.name == this.name)
{
Debug.Log("move " + " " + this.name);
transform.position = new Vector3(touchPos.x = deltaX, touchPos.y = deltaY, initialPosition.z);
}
}
break;
case TouchPhase.Ended:
if (Mathf.Abs(transform.position.x - objectPosition.position.x) <= snapdifficulty
&& Mathf.Abs(transform.position.y - objectPosition.position.y) <= snapdifficulty)
{
transform.position = new Vector3(objectPosition.position.x, objectPosition.position.y, initialPosition.z);
correctPosition = true;
}
else
{
transform.position = new Vector3(initialPosition.x, initialPosition.y, initialPosition.z);
}
break;
}
}
}
}
Upvotes: 0
Views: 93
Reputation: 90813
You are passing
transform.position = new Vector3(touchPos.x = deltaX, touchPos.y = deltaY, initialPosition.z);
in
case TouchPhase.Moved:
if (Physics.Raycast(raycast, out raycastHit))
{
if (raycastHit.collider.name == this.name)
{
Debug.Log("move " + " " + this.name);
transform.position = new Vector3(touchPos.x = deltaX, touchPos.y = deltaY, initialPosition.z);
}
}
break;
which makes your object stick to the initial position where the touch started until you reach the TouchPhase.Ended
case.
I guess what you rather would want is store the initial Delta:
private Vector2 initialDelta;
and set it in
case TouchPhase.Began:
if (Physics.Raycast(raycast, out raycastHit))
{
if (raycastHit.collider.name == this.name)
{
initialDelta = transform.position - touchPos;
}
}
break;
And then later use this Delta to position the object
case TouchPhase.Moved:
if (Physics.Raycast(raycast, out raycastHit))
{
if (raycastHit.collider.name == this.name)
{
Debug.Log("move " + " " + this.name);
transform.position = touchPos + initialDelta + Vector3.forward * initialPosition.z;
}
}
break;
I would not let every object handle the raycast! This is pretty expensive.
Rather put your script on one single controller object in the scene and additionally store which object you hit.
You can then put all your moveable objects into a special Layer and filter your Raycast to only hit this specific layer.
Something like e.g.
// Set via the Inspector
public LayerMask raycastLayers;
private Transform currentlyDraggedObject;
and then get it in
case TouchPhase.Began:
if (Physics.Raycast(raycast, out raycastHit, layermask = (int)raycastLayers))
{
currentlyDraggedObject = raycastHit.transform;
initialDelta = currentlyDraggedObject.position - touchPos;
// Your component would now only store and provide public the target position
objectPosition = currentlyDraggedObject.GetComponent<Moveable>().objectPosition;
}
break;
and then later do the manipulation on the dragged object
case TouchPhase.Moved:
if (currentlyDraggedObject)
{
Debug.Log("move " + " " + currentlyDraggedObject.name);
currentlyDraggedObject.position = touchPos + initialDelta + Vector3.forward * initialPosition.z;
}
break;
case TouchPhase.Ended:
if(currentlyDraggedObject)
{
if (Mathf.Abs(currentlyDraggedObject.position.x - objectPosition.position.x) <= snapdifficulty
&& Mathf.Abs(currentlyDraggedObject.position.y - objectPosition.position.y) <= snapdifficulty)
{
currentlyDraggedObject.position = new Vector3(objectPosition.position.x, objectPosition.position.y, initialPosition.z);
correctPosition = true;
}
else
{
currentlyDraggedObject.position = new Vector3(initialPosition.x, initialPosition.y, initialPosition.z);
}
currentlyDraggedObject = null;
}
break;
Typed on smartphone but I hope the idea gets clear
Upvotes: 2