【问题标题】:Dragging and moving 2D gameObject拖动和移动 2D 游戏对象
【发布时间】:2018-06-22 02:15:05
【问题描述】:

正如我之前的线程所示,我正在使用以下代码在运行时从精灵图像创建gameObject

 tex = Resources.Load<Texture2D>("pig") as Texture2D;
 Sprite sprite = new Sprite();
 sprite = Sprite.Create(tex, new Rect(0, 0, 250, 150), new Vector2(0.5f, 0.5f));
 GameObject newSprite = new GameObject();
 newSprite.AddComponent<Rigidbody2D>();
 newSprite.GetComponent<Rigidbody2D>().gravityScale = 0f;
 newSprite.AddComponent<ObjectMovement>();
 newSprite.AddComponent<SpriteRenderer>();
 SR = newSprite.GetComponent<SpriteRenderer>();
 SR.sprite = sprite;

如你所见,我添加了一个脚本“ObjectMovement”,如果有人拖动这个特定的gameObject,我想检查这个脚本,如果是这样,让它跟随触摸位置,只是提一下 - 这个游戏是二维。我从未使用过RaysRaycast,所以我不确定我哪里出错了。无论如何,这是我的脚本代码:

public SpriteRenderer selection=null;
    void Update()
    {
        if (Input.touchCount >= 1)
        {
            foreach (Touch touch in Input.touches)
            {
                Ray ray = Camera.main.ScreenPointToRay(touch.position);
                RaycastHit hit;
                switch (touch.phase)
                {
                    case TouchPhase.Began:
                        if (Physics.Raycast(ray, out hit, 100))
                            selection = hit.transform.gameObject.GetComponent<SpriteRenderer>();
                        break;
                    case TouchPhase.Moved:
                        selection.transform.position = new Vector2(selection.transform.position.x + touch.position.x / 10, selection.transform.position.y + touch.position.y / 10);
                        break;
                    case TouchPhase.Ended:
                        selection = null;
                        break;
                }
            }
        }
    }

所以基本上 - 触摸屏幕时,触发ray 并检查哪个gameObject 在这个位置,移动手指时让它跟随它。拖放。谢谢。

编辑:我注意到脚本附加到每个 gameObject 上,这是无效的,有什么想法吗?

【问题讨论】:

  • 请务必勾选下面的慷慨答案
  • @JoeBlow 当然,他帮了我很多。我正在等待他的评论。

标签: c# android unity3d


【解决方案1】:

对于 2D,您使用 RaycastHit2DPhysics2D.Raycast 而不是 RaycastHitPhysics.Raycast。那些是3D的。其次,确保将碰撞器附加到Sprite。由于这是一个 2D 游戏,所以对撞机中必须包含“2D”字样。例如,来自编辑器的Box Colider 2D。你也可以使用Circle Collider 2D

我注意到脚本附加到每个不是 有效,有什么想法吗?

只需创建一个空的 GameObject 并将该脚本附加到它上面。就是这样。

这是您的代码的固定版本:

float tempZAxis;
public SpriteRenderer selection;
void Update()
{
    Touch[] touch = Input.touches;
    for (int i = 0; i < touch.Length; i++)
    {
        Vector2 ray = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
        RaycastHit2D hit = Physics2D.Raycast(ray, Vector2.zero);
        switch (touch[i].phase)
        {
            case TouchPhase.Began:
                if (hit)
                {
                    selection = hit.transform.gameObject.GetComponent<SpriteRenderer>();
                    if (selection != null)
                    {
                        tempZAxis = selection.transform.position.z;
                    }
                }
                break;
            case TouchPhase.Moved:
                Vector3 tempVec = Camera.main.ScreenToWorldPoint(touch[i].position);
                tempVec.z = tempZAxis; //Make sure that the z zxis never change
                if (selection != null)
                {
                    selection.transform.position = tempVec;
                }
                break;
            case TouchPhase.Ended:
                selection = null;
                break;
        }

    }
}

这仅适用于移动设备,但不适用于桌面构建。我建议你实现IBeginDragHandlerIDragHandlerIEndDragHandler 并覆盖它们附带的函数。现在,它将适用于移动和桌面平台。

注意:对于第二种解决方案,您必须将下面的脚本附加到您要拖动的所有 Sprite 上,这与上面的第一个脚本不同。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class Dragger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{

    Camera mainCamera;
    float zAxis = 0;
    Vector3 clickOffset = Vector3.zero;

    // Use this for initialization
    void Start()
    {
        //Comment this Section if EventSystem system is already in the Scene
        addEventSystem();


        mainCamera = Camera.main;
        mainCamera.gameObject.AddComponent<Physics2DRaycaster>();

        zAxis = transform.position.z;
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        clickOffset = transform.position - mainCamera.ScreenToWorldPoint(new Vector3(eventData.position.x, eventData.position.y, zAxis));
    }

    public void OnDrag(PointerEventData eventData)
    {
        //Use Offset To Prevent Sprite from Jumping to where the finger is
        Vector3 tempVec = mainCamera.ScreenToWorldPoint(eventData.position) + clickOffset;
        tempVec.z = zAxis; //Make sure that the z zxis never change

        transform.position = tempVec;
    }

    public void OnEndDrag(PointerEventData eventData)
    {

    }

    //Add Event Syste to the Camera
    void addEventSystem()
    {
        GameObject eventSystem = new GameObject("EventSystem");
        eventSystem.AddComponent<EventSystem>();
        eventSystem.AddComponent<StandaloneInputModule>();
    }
}

【讨论】:

  • 第二个脚本出现错误 - 场景中有多个事件系统...
  • 通过评论这部分你的意思是用 if 语句包围?
  • @DAVIDBALAS1 否。这意味着将// 放在addEventSystem(); 前面,或者只是从Start() 函数中删除addEventSystem();。添加// 将告诉编译器不要编译该行代码。因此,将addEventSystem(); 替换为//addEventSystem(); 或将其删除。
  • 哦,当然,我不知道这叫评论一行。第二个脚本在手机和桌面上都对我不起作用...
  • @DAVIDBALAS1 它适用于我的移动和桌面。除了我谈到的评论内容外,不要更改其中的任何内容。它应该可以工作,您必须将其附加到您单击的 Sprite。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-25
  • 1970-01-01
相关资源
最近更新 更多