Unity中做连线选择题
在网上找到一个教程,但是我的画布模式是camera,使用的时候会产生偏移,如下图,鼠标和线不在同一指向附代码(鼠标此时指向的是右侧第一个),该怎么调整呢(我猜有可能是我坐标转换的问题,但是不会调),还有重置键,点击之后可以出现连线(现在是线会消失但是不可以重新连),最后点击提交出现新的界面判断对错
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
public class line : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler, IEndDragHandler
{
[Header("线宽度")]
public float lineWidth = 3f;
[Header("线颜色")]
public Color lineColor = Color.white;
[Header("限制多选")]
bool isUP = true;
//连线
GameObject lineObj = null;
RectTransform lineObjRT = null;
Image lineObjImg;
//初始点
Vector3 startPos = Vector3.zero;
Vector3 endPos = Vector3.zero;
// 最后落脚的物体
GameObject GetObj;
public void Decide()
{
if (GetObj != null)
{
if (GetObj.name == transform.name)
{
Debug.Log("回答正确");
lineObjImg.color = Color.green;
}
else
{
lineObjImg.color = Color.red;
Debug.Log("回答错误");
}
}
else
{
Debug.Log("回答错误");
// DestroyImmediate(lineObjRT.gameObject);
}
}
public void OnDrag(PointerEventData eventData)
{
if (isUP)
{
endPos = Input.mousePosition;
Vector3 durationPos = endPos - startPos;
lineObjRT.sizeDelta = new Vector3(durationPos.magnitude, lineWidth,transform.position.z);
float angle = Mathf.Atan2(durationPos.y, durationPos.x) * Mathf.Rad2Deg;
lineObjRT.localRotation = Quaternion.Euler(0, 0, angle);
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (isUP)
{
if (eventData.pointerEnter != null)
{
print(eventData.pointerEnter.name);
endPos = eventData.pointerEnter.transform.position;
Vector3 durationPos = endPos - startPos;
lineObjRT.sizeDelta = new Vector3(durationPos.magnitude, lineWidth,transform.position.z);
float angle = Mathf.Atan2(durationPos.y, durationPos.x) * Mathf.Rad2Deg;
lineObjRT.localRotation = Quaternion.Euler(0, 0, angle);
isUP = false;
}
else
{
print("未选中,结果为空");
}
}
}
public void OnPointerDown(PointerEventData eventData)
{
//限制多选
if (isUP)
{
lineObj = new GameObject("LineObj");
lineObj.SetActive(false);
lineObjRT = lineObj.AddComponent<RectTransform>();
lineObjRT.pivot = new Vector2(0, 0.5f);
lineObjRT.localScale = Vector3.one;
lineObjImg = lineObj.AddComponent<Image>();
lineObjImg.color = lineColor;
lineObjImg.raycastTarget = false;
lineObjRT.SetParent(transform);
startPos = transform.position;
lineObjRT.position = startPos;
lineObjRT.sizeDelta = Vector2.zero;
lineObj.SetActive(true);
};
}
public void OnPointerUp(PointerEventData eventData)
{
if (isUP)
{
if (eventData.pointerEnter != null)
{
GetObj = eventData.pointerEnter;
//添加数据
Line_chose.dic_add.Add(int.Parse(transform.name), int.Parse(eventData.pointerEnter.name));
Line_chose.number++;
}
if (eventData.pointerEnter == null)
{
DestroyImmediate(lineObjRT.gameObject);
}
}
if (eventData.button == PointerEventData.InputButton.Right)
{
if (Line_chose.dic_add.ContainsKey(int.Parse(transform.name)))
{
//移除数据
Line_chose.dic_add.Remove(int.Parse(transform.name));
Line_chose.number--;
}
DestoryAll();
isUP = true;
}
}
//销毁自身所有的线
public void DestoryAll()
{
for (int i = 0; i < transform.childCount; i++)
{
Destroy(transform.GetChild(i).gameObject);
}
}
}
问题可能出在两个地方:画布模式和重置键。
首先,关于画布模式的偏移问题,你可以尝试调整画布的设置以解决这个问题。在Canvas组件上,将Render Mode(渲染模式)设置为Screen Space - Camera,并将Render Camera(渲染相机)字段设置为你的相机对象。这样,画布将根据相机的视角进行定位,解决偏移问题。
其次,关于重置键不能重新连线的问题,你需要在重置键的点击事件中重置连线的状态。例如,可以在点击重置键时销毁当前的连线对象,同时将线对象设置为null,这样就可以重新连线了。
以下是可能的修改代码示例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
public class line : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler, IEndDragHandler
{
[Header("线宽度")]
public float lineWidth = 3f;
[Header("线颜色")]
public Color lineColor = Color.white;
[Header("限制多选")]
bool isUP = true;
//连线
GameObject lineObj = null;
RectTransform lineObjRT = null;
Image lineObjImg;
//初始点
Vector3 startPos;
// 重置键
public Button resetButton;
void Start()
{
resetButton.onClick.AddListener(ResetLine);
}
public void OnPointerDown(PointerEventData eventData)
{
startPos = eventData.position;
lineObj = new GameObject("Line");
lineObjRT = lineObj.AddComponent<RectTransform>();
lineObjImg = lineObj.AddComponent<Image>();
lineObjImg.color = lineColor;
lineObjRT.pivot = new Vector2(0.5f, 0f);
lineObjRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, lineWidth);
lineObjRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, lineWidth);
lineObj.transform.SetParent(transform);
}
public void OnDrag(PointerEventData eventData)
{
if (lineObj == null)
return;
float angle = Mathf.Atan2(eventData.position.y - startPos.y, eventData.position.x - startPos.x) * Mathf.Rad2Deg;
lineObjRT.eulerAngles = new Vector3(0, 0, angle);
float distance = Vector3.Distance(startPos, eventData.position);
lineObjRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, distance);
}
public void OnEndDrag(PointerEventData eventData)
{
if (lineObj == null)
return;
Destroy(lineObj);
lineObj = null;
}
// 重置连线
public void ResetLine()
{
if (lineObj != null)
{
Destroy(lineObj);
lineObj = null;
}
}
public void OnPointerUp(PointerEventData eventData)
{
if (lineObj == null)
return;
if (isUP)
{
lineObj.transform.SetParent(null);
lineObj = null;
}
}
}
这样,你应该可以解决偏移和重置问题。
首先,偏移的原因可能是坐标系转换的问题,因为鼠标点击的坐标是以屏幕为基准,而连线的终点坐标是在世界坐标系中确定的。因此,在进行坐标系转换时,可能需要对屏幕坐标进行转换,以便与世界坐标系中的坐标匹配。
其次,建议检查以下几点:
确保画布的位置和大小与相机视图匹配。如果画布和相机的位置或大小不匹配,则可能会导致绘制出现偏移。
检查是否使用了正确的相机。如果不是,可能会导致坐标转换错误,从而导致偏移。确保使用正确的相机来进行坐标转换。
检查是否正确设置了画布的缩放比例。如果画布的缩放比例与相机不匹配,则可能会导致绘制出现偏移。
最后,建议在代码中加入调试输出,以帮助定位问题所在。例如,可以输出鼠标点击的屏幕坐标和绘制连线的世界坐标,以便更好地了解偏移的原因,并找出解决方案。
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
public class Line : MonoBehaviour, IPointerDownHandler, IDragHandler, IEndDragHandler
{
public Camera camera;
public Color lineColor;
public float lineWidth;
private RectTransform lineObjRT;
private Image lineObjImg;
private GameObject lineObj;
private Vector3 startPos;
private Vector3 endPos;
private void Start()
{
lineObj = new GameObject("LineObj");
lineObjRT = lineObj.AddComponent<RectTransform>();
lineObjImg = lineObj.AddComponent<Image>();
lineObjImg.color = lineColor;
lineObjImg.raycastTarget = false;
lineObj.transform.SetParent(transform);
camera = Camera.main;
}
public void OnPointerDown(PointerEventData eventData)
{
startPos = camera.ScreenToWorldPoint(Input.mousePosition);
}
public void OnDrag(PointerEventData eventData)
{
endPos = camera.ScreenToWorldPoint(eventData.position);
Vector3 startPosUI = camera.WorldToScreenPoint(startPos);
Vector3 endPosUI = camera.WorldToScreenPoint(endPos);
lineObjRT.position = startPosUI;
lineObjRT.sizeDelta = new Vector2((endPosUI - startPosUI).magnitude, lineWidth);
float angle = Mathf.Atan2(endPosUI.y - startPosUI.y, endPosUI.x - startPosUI.x) * Mathf.Rad2Deg;
lineObjRT.rotation = Quaternion.Euler(0, 0, angle);
}
public void OnEndDrag(PointerEventData eventData)
{
endPos = camera.ScreenToWorldPoint(eventData.position);
Vector3 startPosUI = camera.WorldToScreenPoint(startPos);
Vector3 endPosUI = camera.WorldToScreenPoint(endPos);
lineObjRT.position = startPosUI;
lineObjRT.sizeDelta = new Vector2((endPosUI - startPosUI).magnitude, lineWidth);
float angle = Mathf.Atan2(endPosUI.y - startPosUI.y, endPosUI.x - startPosUI.x) * Mathf.Rad2Deg;
lineObjRT.rotation = Quaternion.Euler(0, 0, angle);
Destroy(lineObj);
lineObj = new GameObject("LineObj");
lineObjRT = lineObj.AddComponent<RectTransform>();
lineObjImg = lineObj.AddComponent<Image>();
lineObjImg.color = lineColor;
lineObjImg.raycastTarget = false;
lineObj.transform.SetParent(transform);
Line_chose.dic_add[int.Parse(transform.name)] = int.Parse(eventData.pointerEnter.name);
}
public void DestoryAll()
{
Destroy(lineObj);
}
}
你方便发源项目吗,方便的话我下班可以帮你改一下。
已经自己解决啦,底下的回答我都看了,可能和我用的画布和相机模式有关都会有问题,我在自己的脚本的基础上做了一些修改,且我发现我自己在计算鼠标在屏幕上的位置的时候带错了相机(我把主相机带进去了,但实际上应该是用UIcam)修改如下:
public void OnDrag(PointerEventData eventData)
{
Debug.Log("点击成功");
if (isUP)
{
endPos = Input.mousePosition; //鼠标终点
Vector3 worldEndPos = UICam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, transform.position.z));
//Debug.Log("Pose" + worldEndPos);
Vector3 durationPos = worldEndPos - startPos;
lineObjRT.sizeDelta = new Vector3(6, lineWidth, transform.position.z);
float angle = Mathf.Atan2(durationPos.y, durationPos.x) * Mathf.Rad2Deg;
lineObjRT.rotation = Quaternion.Euler(0, 0, angle);
//Debug.Log("Euler=" + lineObjRT.localRotation);
}
}
有需要的大家可以试试~