一、网上能见到的拖拽旋转代码
它们都是沿着自身的某两个轴进行rotate,代码通常如下:
float XaxisRotation = Input.GetAxis("Mouse X") * RotationSpeed;
float YaxisRotation = Input.GetAxis("Mouse Y") * RotationSpeed;
go.Rotate(Vector3.down, XaxisRotation);
go.Rotate(Vector3.right, -YaxisRotation);
结局: 第一次拖拽都是母慈子孝——拖它往左,它就往左转,拖它往右,它就往右转,but(一看见but你就应该想到,要反转了),当物体转到背面后,你会发现:你往左拖,它往右转…简直鸡飞狗跳…
请看下面的效果:
如何修改呢?
二、请先欣赏这种母慈子孝的拖动效果
如何?向左拖向左转,向下拖向下转,始终都不会乱!!!
- 脚本的参数:
三、实现的思路
-
旋转前:beginDrag 1、生成旋转的root 2、root对正方向:lookAt摄像机 3、绑定父子关系:要旋转的物体作为root的子物体 -
旋转中:Drag 1、旋转root,带动子物体旋转 -
停止旋转:endDrag 1、撤销父子关系 2、销毁root -
什么时候拖呢 如上所示,你发现当鼠标悬停到物体上的时候,物体变成红色,此时物体才能拖动
四、代码
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;
using static txlib;
using UnityEngine.EventSystems;
public class DragObjectRotate : MonoBehaviour
{
public Transform cam;
public Transform objectToRotate;
public float RotationSpeed;
private Transform rotateRoot;
private Transform parent;
public List<GameObject> childrenObjs = new List<GameObject>();
void Start()
{
childrenObjs.Clear();
childrenObjs = GetChildren(objectToRotate);
parent = objectToRotate.parent;
childrenObjs.ForEach(obj=>
{
if (obj.GetComponent<EventTrigger>() == null)
{
obj.gameObject.AddComponent<EventTrigger>();
}
if (obj.GetComponent<Collider>() == null)
{
obj.gameObject.AddComponent<BoxCollider>();
}
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.BeginDrag, (PointerEventData eventData) =>
{
Debug.Log($"BeginDrag:");
rotateRoot = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
rotateRoot.position = objectToRotate.position;
rotateRoot.LookAt(cam);
rotateRoot.transform.localScale = new Vector3(50, 50, 50);
objectToRotate.parent = rotateRoot;
});
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.EndDrag, (PointerEventData eventData) =>
{
Debug.Log($"EndDrag:");
objectToRotate.parent = parent;
Destroy(rotateRoot.gameObject);
obj.GetComponent<MeshRenderer>().material.color = Color.white;
});
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.Drag, (PointerEventData eventData) =>
{
Debug.Log($"Dragging......");
RotateOjb(RotationSpeed, rotateRoot);
});
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerEnter, (PointerEventData eventData) =>
{
obj.GetComponent<MeshRenderer>().material.color = Color.red;
});
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerExit, (PointerEventData eventData) =>
{
obj.GetComponent<MeshRenderer>().material.color = Color.white;
});
});
}
void RotateOjb(float RotationSpeed,Transform go)
{
float XaxisRotation = Input.GetAxis("Mouse X") * RotationSpeed;
float YaxisRotation = Input.GetAxis("Mouse Y") * RotationSpeed;
go.Rotate(Vector3.down, XaxisRotation);
go.Rotate(Vector3.right, -YaxisRotation);
}
#if UNITY_EDITOR
[ContextMenu("获取物体的子物体测试")]
#endif
void Test()
{
childrenObjs = GetChildren(objectToRotate);
}
public List<GameObject> GetChildren(Transform root)
{
return root.GetComponentsInChildren<Transform>().Where(x => x.GetComponent<MeshRenderer>() != null).Select(x => x.gameObject).ToList();
}
}
五、备注:代码中用到的一个AddListener扩展方法【using static txlib;】
public static void AddListener(this EventTrigger trigger, EventTriggerType eventType, Action<PointerEventData> listenedAction)
{
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = eventType;
entry.callback.AddListener(data => listenedAction.Invoke((PointerEventData)data));
trigger.triggers.Add(entry);
}
|