学习了B站UP主OneCredit【Unity快速教学】鼠标拖曳甩动物件BV1qK4y1d7iZ的教学视频后
拓展了一下功能,实现多个物体也可以拖拽,互不受影响
主要是做了一个检测,在鼠标上物体才能被拖拽
目录
bool Drag
拖拽物体的实现
解决摄像机视角的影响
bool Drag
绑定刚体,写好需要用到的变量
Drag用于判断鼠标是否在物体上,只有鼠标放在物体上或者拖拽物体,Drag才为真
Drag为真时,关于拖拽计算的代码才会运行,这样就不会出现,同一套代码,你拖动一个球,其他所有球跟着动的情况。
using UnityEngine;
public class MouseDrag : MonoBehaviour
{
public float moveForce = 10;
public Rigidbody mD;//绑定目标刚体
Vector3 startPos;//起点
Vector3 endPos;//终点
Vector3 moveDir;//moveDirection
Vector3 actualMoveDir;//实际的moveDirection
private bool Drag;//是否在拖拽-检测多物体拖拽
private void OnMouseEnter()
{
Drag = true;
print("enter work");//当鼠标在物体上
}
private void OnMouseExit()
{
Drag = false;
print("exit work");//当鼠标离开物体
}
private void OnMouseDrag()
{
Drag = true;
print("drag work");//当鼠标在物体上->单击->拖拽
}
拖拽物体的实现
实际上是先得到拖拽开始时鼠标的初始位置,拖拽动作完成瞬间,得到松手时鼠标位置,得到两个向量,分别为startPos和endPos
endPos减去startPos就能得到以物体为起点指向鼠标松开位置的一个向量
void Update()
{
if (Drag)//只有if为真时,即鼠标在物体上或者拖拽该物体时,以下代码才会生效
{
if (Input.GetKeyDown(KeyCode.Mouse0))//KeyDown鼠标按下瞬间startPos收到鼠标松手位置
{
startPos = Camera.main.ScreenToViewportPoint(Input.mousePosition);
//startPos收到鼠标起始位置
}
if (Input.GetKeyUp(KeyCode.Mouse0))//Keyup,鼠标松开瞬间endPos收到鼠标松手位置
{
endPos = Camera.main.ScreenToViewportPoint(Input.mousePosition);
Vector3 dir = endPos - startPos;
moveDir = new Vector3(dir.x, 0, dir.y);
actualMoveDir = Quaternion.AngleAxis(Camera.main.transform.eulerAngles.y, Vector3.up) * moveDir;
movetheball();
OnMouseExit();
}
}
void movetheball()
{
mD.AddForce(actualMoveDir * moveForce, ForceMode.Impulse);
//给刚体对象mD添加一个力,向量是真实位移actualMoveDir * 力moveForce * (力的作用模式)给物体一个瞬间的力 ForceMode.Impulse
}
}
}
关于Camera.ScreenToViewportPoint 描述为将 position 从屏幕空间变换为视口空间
参考https://docs.unity.cn/cn/current/ScriptReference/Camera.ScreenToViewportPoint.html
参数Input.mousePosition 意为以像素坐标表示的当前鼠标位置
得到的向量放进startPos中,endPos同理
Vector3 dir = endPos - startPos;
物体要移动的方向 = 松手处末向量 - 点下鼠标处初始向量
这样得到的向量,缺少Z值,因为Input.mousePosition没有提供Z方向(X,Z为平面上的方向)
但是物体需要在XZ平面上移动
所以moveDir = new Vector3(dir.x, 0, dir.y);实际上是把dir的y值放到了Z轴上
解决摄像机视角的影响
但是新的问题是,如果你移动摄像机的Y轴,当你拖动物体时,物体会依然按照摄像机原方向移动
actualMoveDir = Quaternion.AngleAxis(Camera.main.transform.eulerAngles.y, Vector3.up) * moveDir;
这个代码的作用是--旋转Y轴,如果摄像机的Y轴被旋转了,你得让moveDir同步旋转,物体才会跟着你的鼠标拖动方向走~
Transform.eulerAngles 表示世界空间中的旋转
Quaternion.AngleAxis的用法:Quaternion-AngleAxis - Unity 脚本 API
public static Quaternion AngleAxis (float angle, Vector3 axis);
transform.rotation = Quaternion.AngleAxis(转动的角度, 围绕的轴);
代码中是以摄像机的y轴旋转了多少放到参数1,围绕转动的轴为 Vector3.up(y轴)
得到旋转和摄像机相同y轴数值的actualMoveDir
最终无论方向怎么改变,只要你能看到物体,拖动它时,总能向着你觉得它应该去的方向前进。文章来源:https://www.toymoban.com/news/detail-843002.html
完整代码
使用mainCamera,设置物体Rigidbody,MouseDrag需要添加进目标物体上文章来源地址https://www.toymoban.com/news/detail-843002.html
using UnityEngine;
public class MouseDrag : MonoBehaviour
{
public float moveForce = 10;
public Rigidbody mD;//绑定目标刚体
Vector3 startPos;//起点
Vector3 endPos;//终点
Vector3 moveDir;//moveDirection
Vector3 actualMoveDir;//实际的moveDirection
private bool Drag;//是否在拖拽-检测多物体拖拽
private void OnMouseEnter()
{
Drag = true;
print("enter work");//当鼠标在物体上
}
private void OnMouseExit()
{
Drag = false;
print("exit work");//当鼠标离开物体
}
private void OnMouseDrag()
{
Drag = true;
print("drag work");//当鼠标在物体上->单击->拖拽
}
// Start is called before the first frame update
void Start()
{
//前面有声明刚体对象 Rigidbody mD
//这里是在游戏运行前,获取当前游戏对象的刚体组件
mD = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Drag)
{
if (Input.GetKeyDown(KeyCode.Mouse0))//KeyDown鼠标按下瞬间startPos收到鼠标松手位置
{
//关于Camera.ScreenToViewportPoint 意为将 position 从屏幕空间变换为视口空间
//屏幕空间(屏幕空间以像素定义。屏幕的左下角为(0, 0),右上角 为(pixelWidth, pixelHeight)。z 位置为与摄像机的距离)
//视口空间(摄像机左下角为 (0,0),右上角为 (1,1),Z为与摄像机的距离)
//https://docs.unity.cn/cn/current/ScriptReference/Camera.ScreenToViewportPoint.html
//参数Input.mousePosition 意为以像素坐标表示的当前鼠标位置。
//https://docs.unity.cn/cn/current/ScriptReference/Input-mousePosition.html
startPos = Camera.main.ScreenToViewportPoint(Input.mousePosition);
//startPos收到鼠标起始位置
}
if (Input.GetKeyUp(KeyCode.Mouse0))//Keyup,鼠标松开瞬间endPos收到鼠标松手位置
{
endPos = Camera.main.ScreenToViewportPoint(Input.mousePosition);//同上的操作
Vector3 dir = endPos - startPos;
//松手处末向量 - 点下鼠标处初始向量 = 物体要移动的方向
//一个ADB三角,起点为世界原点,AD - AB = DB
moveDir = new Vector3(dir.x, 0, dir.y);
//Input.mousePosition没有提供Z方向(X,Z为平面上的方向)
//将临时向量dir的y方向放到moveDir的z方向上
actualMoveDir = Quaternion.AngleAxis(Camera.main.transform.eulerAngles.y, Vector3.up) * moveDir;
//旋转Y轴,如果你摄像机的Y轴被旋转了,你要让moveDir同步旋转,才能让物体跟着你的鼠标走
movetheball();
OnMouseExit();
}
}
}
void movetheball()
{
mD.AddForce(actualMoveDir * moveForce, ForceMode.Impulse);
//给刚体对象mD添加一个力,向量是真实位移actualMoveDir * 力moveForce * (力的作用模式)给物体一个瞬间的力 ForceMode.Impulse
}
}
到了这里,关于Unity实现鼠标拖拽多物体(拖拽单物体的拓展)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!