m0_57965808 2024-07-01 18:45 采纳率: 91.2%
浏览 6
已结题

unity如何实现控制视角的同时实现拖拽物体移动

在使用UNITY有两个脚本,我在unity写了两个C#脚本,一个是通过键盘鼠标控制视角的,另一个是通过鼠标拖拽移动物体的。但是当通过键盘鼠标控制视角的脚本运行之后,通过鼠标拖拽移动物体的脚本就很难起作用,具体表现为:键盘鼠标控制视角的脚本运行之后,多次点击并尝试拖拽物体失败,被拖拽物体不会有任何反应,这主要是因为代码无法准确识别点击的对象,常常会认为鼠标点击的是其它物体,例如物体下方的地板。代码如下,请各位不吝赐教:

// 通过键盘鼠标控制视角的脚本
using UnityEngine;
 
public class FirstPersonController : MonoBehaviour
{
    public float moveSpeed = 5.0f;

    public float lookSpeed = 2.0f;

    public float lookXLimit = 45.0f;
 
    private float rotationY;

    private float rotationX;

    private CharacterController controller;
 
    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;

        controller = GetComponent<
CharacterController>
();

    } 
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            rotationX -= Input.GetAxis("
Mouse Y"
) * lookSpeed;

            rotationY += Input.GetAxis("
Mouse X"
) * lookSpeed;

            rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit);

            transform.localRotation = Quaternion.Euler(rotationX, rotationY, 0);

            transform.GetChild(0).localRotation = Quaternion.Euler(0, rotationY, 0);

        } 
        float moveX = Input.GetAxis("
Horizontal"
);

        float moveZ = Input.GetAxis("
Vertical"
);
 
        Vector3 moveDir = new Vector3(moveX, 0, moveZ).normalized;

        moveDir = transform.TransformDirection(moveDir);

        moveDir.y = 0;

        controller.Move(moveDir * moveSpeed * Time.deltaTime);

    }
}

// 通过鼠标拖拽移动物体的脚本
using UnityEngine;
 
public class DragObject : MonoBehaviour
{
    private bool dragging = false;

    private Vector3 screenPoint;

    private Vector3 offset;
 
    void OnMouseDown()
    {
        screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);

        offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));

        dragging = true;

    } 
    void OnMouseUp()
    {
        dragging = false;

    } 
    void OnMouseDrag()
    {
        if (dragging)
        {
            Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);

            gameObject.transform.position = Camera.main.ScreenToWorldPoint(mousePosition) + offset;

        }
    }
}

  • 写回答

2条回答 默认 最新

  • 阿里嘎多学长 2024-07-01 18:45
    关注

    以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


    在Unity中,当你同时使用两个脚本控制视角和拖拽物体时,确实可能会遇到冲突问题。这主要是因为两个脚本都试图处理鼠标输入,而Unity的事件系统默认是线性处理这些输入的,所以当第一个脚本处理了鼠标输入后,第二个脚本可能就无法正确识别鼠标事件了。

    要解决这个问题,你可以考虑以下几种方法:

    1. 使用Layer和Raycast: 你可以将视角控制和拖拽物体的逻辑分开处理。首先,确保你的物体和地板(或背景)在不同的层(Layer)。然后,在拖拽脚本中使用射线检测(Raycast)来确定鼠标点击的是物体还是地板。如果射线检测到的是物体,就执行拖拽逻辑。

    2. 修改事件处理顺序: 你可以调整两个脚本的事件处理顺序。在Unity中,可以通过改变脚本的执行顺序来解决一些冲突问题。你可以在Inspector面板中调整脚本的执行顺序,使得拖拽物体的脚本在控制视角的脚本之前执行。

    3. 使用Input.GetMouseButtonDown: 在拖拽物体的脚本中,使用Input.GetMouseButtonDown(0)代替OnMouseDown(),这样可以确保只有在鼠标按下时才触发拖拽逻辑,而不是在鼠标按下和移动的过程中。

    4. 使用事件监听: 在Unity中,你可以使用事件监听来处理鼠标输入。在你的拖拽脚本中,创建一个事件监听器,当鼠标按下时注册监听,鼠标释放时取消监听。这样可以避免在视角控制脚本处理鼠标输入时,拖拽脚本也尝试处理鼠标输入。

    5. 使用Unity的EventSystem: 如果你的项目中使用了Unity的UI系统,你可以利用EventSystem来管理事件。通过设置合适的selectablecanvas组,你可以控制哪些对象可以接收鼠标事件。

    6. 优化你的代码逻辑: 检查你的代码逻辑,确保没有不必要的鼠标事件处理。例如,你可能需要在拖拽物体的脚本中添加一些条件判断,以确保只有在特定情况下才处理鼠标事件。

    这里是一个简化的示例,展示如何使用Layer和Raycast来解决冲突:

    // 通过鼠标拖拽移动物体的脚本
    using UnityEngine;
    
    public class DragObject : MonoBehaviour
    {
        private bool dragging = false;
        private Vector3 screenPoint;
        private Vector3 offset;
        private Camera mainCamera;
    
        void Start()
        {
            mainCamera = Camera.main;
        }
    
        void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;
    
                if (Physics.Raycast(ray, out hit))
                {
                    if (hit.collider.gameObject == gameObject) // 确保点击的是物体本身
                    {
                        screenPoint = mainCamera.WorldToScreenPoint(gameObject.transform.position);
                        offset = gameObject.transform.position - mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
                        dragging = true;
                    }
                }
            }
    
            if (dragging && Input.GetMouseButton(0))
            {
                Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
                gameObject.transform.position = mainCamera.ScreenToWorldPoint(mousePosition) + offset;
            }
    
            if (Input.GetMouseButtonUp(0))
            {
                dragging = false;
            }
        }
    }
    

    请注意,这只是一个示例,你可能需要根据你的具体需求调整代码。希望这些建议能帮助你解决问题。如果需要更详细的帮助,可以提供更多的信息或者具体的代码问题。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 7月10日
  • 已采纳回答 7月2日
  • 创建了问题 7月1日