需求来源:北京中教启星科技股份有限公司的寰宇地理VR教学系统中的基本功能
代码参考:在zCore6.3自带的Draggable.cs的基础上进行编写
正题:
1.实现触控笔左按钮(鼠标中键)前后移动时 对拖拽中的物体进行缩放
思路:触控笔的前后移动体现在其z坐标的变化上,在拖拽物体时,不断记录其z坐标距上一次的差值,差值为正时,触控笔向前,物体应该缩小,否则相反。(不同坐标系可能会不一样)
2.实现触控笔右按钮(鼠标右键)左右移动时 对拖拽中的物体进行旋转
思路:触控笔的左右移动体现在其x坐标的变化上,在拖拽物体时,不断记录其x坐标距上一次的差值,差值为正时,触控笔向右,物体应该向右旋转(从上往下逆时针转),否则相反。(不同坐标系可能会不一样)
3.代码
[Tooltip("能否缩放")]
public bool IsCanScaling = true;
[Tooltip("缩放速率")]
public float ScalingRate = 1.0f;
[Tooltip("能否旋转")]
public bool IsCanRotatingOption01 = true;
[Tooltip("旋转速率")]
public float RotationRate = 3.0f;
private float _initialGrabPositionZ = 0;//Z axis of Postion of Stylus or Mouse
private float _initialGrabPositionX = 0;//触控笔的初始X坐标
public void OnBeginDrag(PointerEventData eventData)
{
ZPointerEventData pointerEventData = eventData as ZPointerEventData;
if (pointerEventData == null )
{
return;
}
Pose pose = pointerEventData.Pointer.EndPointWorldPose;
// Cache the initial grab state.
this._initialGrabOffset =
Quaternion.Inverse(this.transform.rotation) *
(this.transform.position - pose.position);
this._initialGrabRotation =
Quaternion.Inverse(pose.rotation) *
this.transform.rotation;
//newly added
this._initialGrabPositionZ = pose.position.z;
this._initialGrabPositionX = pose.position.x;
//
// If the grabbable object has a rigidbody component,
// mark it as kinematic during the grab.
var rigidbody = this.GetComponent<Rigidbody>();
if (rigidbody != null)
{
this._isKinematic = rigidbody.isKinematic;
rigidbody.isKinematic = true;
}
// Capture pointer events.
pointerEventData.Pointer.CapturePointer(this.gameObject);
}
public void OnDrag(PointerEventData eventData)
{
ZPointerEventData pointerEventData = eventData as ZPointerEventData;
if (pointerEventData == null)
{
return;
}
if (pointerEventData.button == PointerEventData.InputButton.Left)
{
Pose pose = pointerEventData.Pointer.EndPointWorldPose;
// Update the grab object's rotation.
this.transform.rotation = pose.rotation * this._initialGrabRotation;
// Update the grab object's position.
this.transform.position = pose.position + (this.transform.rotation * this._initialGrabOffset);
}
if (pointerEventData.button == PointerEventData.InputButton.Right&& IsCanRotatingOption01)
{
Pose pose = pointerEventData.Pointer.EndPointWorldPose;
//x坐标变化
float XPosChange = pose.position.x - this._initialGrabPositionX;
this._initialGrabPositionX = pose.position.x;
//旋转
if (XPosChange > 0)//向右(逆时针转
{
this.transform.RotateAround(this.transform.position, Vector3.down, 1 * RotationRate);
}
if (XPosChange < 0)//向左(顺时针转
{
this.transform.RotateAround(this.transform.position, Vector3.up, 1 * RotationRate);
}
}
if (pointerEventData.button == PointerEventData.InputButton.Middle&&IsCanScaling)
{
Pose pose = pointerEventData.Pointer.EndPointWorldPose;
//获取z的位置变化
float ZPosChange = pose.position.z - this._initialGrabPositionZ;
this._initialGrabPositionZ = pose.position.z;//更新记录的z坐标(只有z坐标发生变化,才能缩放
if (ZPosChange > 0)//缩小
{
//限制最小scale
if (this.transform.localScale.x >= 0.1f)
this.transform.localScale = this.transform.localScale - new Vector3(0.01f, 0.01f, 0.01f) * ScalingRate;
}
if (ZPosChange < 0)//放大
{
//限制最大scale
if (this.transform.localScale.x <= 20f)
this.transform.localScale = this.transform.localScale + new Vector3(0.01f, 0.01f, 0.01f) * ScalingRate;
}
}
}
public void OnEndDrag(PointerEventData eventData)
{
ZPointerEventData pointerEventData = eventData as ZPointerEventData;
if (pointerEventData == null )
{
return;
}
// Release the pointer.
pointerEventData.Pointer.CapturePointer(null);
// If the grabbable object has a rigidbody component,
// restore its original isKinematic state.
var rigidbody = this.GetComponent<Rigidbody>();
if (rigidbody != null)
{
rigidbody.isKinematic = this._isKinematic;
}
}