Почему мои игровые объекты не перетаскиваются? - PullRequest
0 голосов
/ 26 февраля 2020

Я делаю простую головоломку в Unity. У меня есть два объекта и две цели. Я написал скрипт для перетаскивания своих объектов в их целевое местоположение. Я хочу, чтобы мои объекты привязывались в разных местах. Мой код не позволяет мне перетаскивать игровой объект так, как я хотел. Я могу переместить только один из объектов, даже если переместлю его. Я не могу тащить это. Он просто появляется в целевом положении через секунду, он переходит к другому объекту.

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;
            }
        }
    }
}

1 Ответ

2 голосов
/ 26 февраля 2020

Вы передаете

transform.position = new Vector3(touchPos.x = deltaX, touchPos.y = deltaY, initialPosition.z);

в

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;

, что заставляет ваш объект придерживаться начальной позиции, с которой началось касание, до достижения случая TouchPhase.Ended.

Полагаю, вам скорее всего хотелось бы сохранить начальную Дельту:

private Vector2 initialDelta;

и установить ее в

case TouchPhase.Began:   
    if (Physics.Raycast(raycast, out raycastHit))
    {
        if (raycastHit.collider.name == this.name)
        {
            initialDelta = transform.position - touchPos;
        }
    }
    break;

А затем использовать эту Дельту для позиционирования объекта

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;

В общем

Я бы не позволил каждому объекту обрабатывать raycast! Это довольно дорого

Вместо этого поместите ваш сценарий на один единственный контроллер объект на сцене и дополнительно сохраните, какой объект вы ударили.

Затем вы можете поместить все свои подвижные объекты в специальный Layer и отфильтруйте ваш Raycast, чтобы он попал только в этот указанный c слой.

Что-то вроде, например,

// Set via the Inspector
public LayerMask raycastLayers;

private Transform currentlyDraggedObject;

и затем получите его в

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;

, а затем выполните манипуляции с перетаскиваемым объектом

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;

Печатается на смартфоне, но я надеюсь, что идея проясняется

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...