项目工程:unity模型显示在UI上并交互(点击、旋转、缩放)资源-CSDN文库
1.在Assets创建 Render Texture(下面会用到),根据需要设置Size
2.创建UIRawImage,并把Render Texture赋上
3.创建相机,如下图:
4.基本UI的准备工作完成,剩下的就是代码了,值得一提:相机我不喜欢单独拿出去管理,就和UI一起就好。如图:
5.相机控制,直接上代码(添加了一个判断,鼠标必须在rawImage上,其他UI上无效):
/**********************************************************************
文件信息
文件名(File Name): CameraController.cs
作者(Author): TianWenQuan
创建时间(CreateTime): #CREATETIME#
Unity版本(UnityVersion): #UNITYVERSION#
项目:
**********************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace Twq
{
/// <summary>
/// 该脚本需要挂在摄像机上
/// </summary>
public class CameraController : MonoBehaviour
{
public Transform targetObject;
public Vector3 targetOffset;
public float averageDistance = 5.0f;//初始位置 镜头远近
public float maxDistance = 20;
public float minDistance = .6f;
public float xSpeed = 200.0f;
public float ySpeed = 200.0f;
public int yMinLimit = -80;
public int yMaxLimit = 80;
public int xMinLimit = -80;
public int xMaxLimit = 80;
public int zoomSpeed = 40;
public float panSpeed = 0.3f;
public float zoomDampening = 5.0f;
public float rotateOnOff = 1;
private float xDeg = 0.0f;
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private Quaternion currentRotation;
private Quaternion desiredRotation;
private Quaternion rotation;
private Vector3 position;
private float idleTimer = 0.0f;
private float idleSmooth = 0.0f;
void Start() { Init(); }
void OnEnable() { Init(); }
public void Init()
{
tt();
}
public void tt()
{
if (!targetObject)
{
GameObject go = new GameObject("Cam Target");
go.transform.position = transform.position + (transform.forward * averageDistance);
targetObject = go.transform;
}
currentDistance = averageDistance;
desiredDistance = averageDistance;
position = transform.position;
rotation = transform.rotation;
currentRotation = transform.rotation;
desiredRotation = transform.rotation;
xDeg = Vector3.Angle(Vector3.right, transform.right);
yDeg = Vector3.Angle(Vector3.up, transform.up);
position = targetObject.position - (rotation * Vector3.forward * currentDistance + targetOffset);
}
void LateUpdate()
{
if (IsPointerOverGameObject(Input.mousePosition))
{
if (Input.GetMouseButton(2) && Input.GetKey(KeyCode.LeftAlt) && Input.GetKey(KeyCode.LeftControl))
{
desiredDistance -= Input.GetAxis("Mouse Y") * 0.02f * zoomSpeed * 0.125f * Mathf.Abs(desiredDistance);
}
else if (Input.GetMouseButton(0))
{
xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
xDeg = ClampAngle(xDeg, xMinLimit, xMaxLimit);
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.rotation;
rotation = Quaternion.Lerp(currentRotation, desiredRotation, 0.02f * zoomDampening);
transform.rotation = rotation;
idleTimer = 0;
idleSmooth = 0;
}
else
{
//自动旋转
//idleTimer += 0.02f;
//if (idleTimer > rotateOnOff && rotateOnOff > 0)
//{
// idleSmooth += (0.02f + idleSmooth) * 0.005f;
// idleSmooth = Mathf.Clamp(idleSmooth, 0, 1);
// xDeg += xSpeed * 0.001f * idleSmooth;
//}
//yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
//desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
//currentRotation = transform.rotation;
//rotation = Quaternion.Lerp(currentRotation, desiredRotation, 0.02f * zoomDampening * 2);
//transform.rotation = rotation;
}
desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * 0.02f * zoomSpeed * Mathf.Abs(desiredDistance);
desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
currentDistance = Mathf.Lerp(currentDistance, desiredDistance, 0.02f * zoomDampening);
position = targetObject.position - (rotation * Vector3.forward * currentDistance + targetOffset);
transform.position = position;
}
}
private static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
/// <summary>
/// 检测是否点击UI
/// </summary>
/// <param name="mousePosition">鼠标位置</param>
/// <returns></returns>
private bool IsPointerOverGameObject(Vector2 mousePosition)
{
//创建一个点击事件
PointerEventData eventData = new PointerEventData(EventSystem.current);
eventData.position = mousePosition;
List<RaycastResult> raycastResults = new List<RaycastResult>();
//向点击位置发射一条射线,检测是否点击UI
EventSystem.current.RaycastAll(eventData, raycastResults);
if (raycastResults.Count > 0)
{
// Debug.Log("raycastResults[0].gameObject.name="+ raycastResults[0].gameObject.name);
if (raycastResults[0].gameObject.name == "RawImage")//判断是否 是 自己要点击的UI
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
/// <summary>
/// 获取鼠标停留处UI
/// </summary>
/// <param name="canvas"></param>
/// <returns></returns>
public string GetOverUI(GameObject canvas)
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
pointerEventData.position = Input.mousePosition;
GraphicRaycaster gr = canvas.GetComponent<GraphicRaycaster>();
List<RaycastResult> results = new List<RaycastResult>();
gr.Raycast(pointerEventData, results);
if (results.Count != 0)
{
Debug.Log("");
return results[0].gameObject.name;
}
return null;
}
}
}
6.鼠标点击 模型 触发事件
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace App.UI.Event
{
public class RaycastFromMouse : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler, IBeginDragHandler, IEndDragHandler
{
public Camera renderCamera;
public RawImage rawImage;
public void OnPointerClick(PointerEventData eventData)
{
// 获取鼠标点击位置
Vector2 clickPosition = eventData.position;
// 将屏幕坐标转换为 RawImage 的本地坐标
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rawImage.rectTransform, clickPosition, eventData.pressEventCamera, out localPoint);
// 将 RawImage 的本地坐标映射到 RenderTexture 的分辨率范围内
Rect rect = rawImage.rectTransform.rect;
Vector2 normalizedPoint = new Vector2((localPoint.x - rect.x) / rect.width, (localPoint.y - rect.y) / rect.height);
// 将转换后的坐标转换为射线
Ray ray = renderCamera.ViewportPointToRay(normalizedPoint);
// 发射射线,检测是否与3D模型交互
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
// 获取物体上的 EventTrigger 组件
EventTrigger eventTrigger = hit.collider.gameObject.GetComponent<EventTrigger>();
// 如果组件存在,触发 Pointer Click 事件
if (eventTrigger != null)
{
ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.pointerClickHandler);
}
}
}
private GameObject selectedObject;
public void OnPointerDown(PointerEventData eventData)
{
RaycastHit hit;
if (RaycastToRenderTexture(eventData, out hit))
{
EventTrigger eventTrigger = hit.collider.gameObject.GetComponent<EventTrigger>();
if (eventTrigger != null)
{
ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.pointerDownHandler);
selectedObject = eventTrigger.gameObject;
}
}
}
public void OnPointerUp(PointerEventData eventData)
{
if (selectedObject != null)
{
EventTrigger eventTrigger = selectedObject.GetComponent<EventTrigger>();
if (eventTrigger != null)
{
ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.pointerUpHandler);
selectedObject = null;
}
}
}
public void OnBeginDrag(PointerEventData eventData)
{
if (selectedObject != null)
{
EventTrigger eventTrigger = selectedObject.GetComponent<EventTrigger>();
if (eventTrigger != null)
{
ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.beginDragHandler);
}
}
GlobalEvent.Dispatch(UIExecuteEvent.OnBeginDragEvent, eventData);
}
public void OnDrag(PointerEventData eventData)
{
if (selectedObject != null)
{
EventTrigger eventTrigger = selectedObject.GetComponent<EventTrigger>();
if (eventTrigger != null)
{
ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.dragHandler);
}
}
GlobalEvent.Dispatch(UIExecuteEvent.OnDragEvent, eventData);
}
public void OnEndDrag(PointerEventData eventData)
{
if (selectedObject != null)
{
EventTrigger eventTrigger = selectedObject.GetComponent<EventTrigger>();
if (eventTrigger != null)
{
ExecuteEvents.Execute(eventTrigger.gameObject, eventData, ExecuteEvents.endDragHandler);
}
}
GlobalEvent.Dispatch(UIExecuteEvent.OnEndDragEvent, eventData);
}
private bool RaycastToRenderTexture(PointerEventData eventData, out RaycastHit hit)
{
Vector2 clickPosition = eventData.position;
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rawImage.rectTransform, clickPosition, eventData.pressEventCamera, out localPoint);
Rect rect = rawImage.rectTransform.rect;
Vector2 normalizedPoint = new Vector2((localPoint.x - rect.x) / rect.width, (localPoint.y - rect.y) / rect.height);
Ray ray = renderCamera.ViewportPointToRay(normalizedPoint);
return Physics.Raycast(ray, out hit);
}
}
}