using UnityEngine;
using UnityEngine.UI;
using System.Collections;
///
/// RawImage模型控制器
/// 功能:在RawImage上显示3D模型,并支持旋转和缩放操作
///
public class RawImageModelController : MonoBehaviour
{
[Header("【模型设置】")]
[Tooltip("要显示的3D模型")]
[SerializeField] private GameObject model;
[Header("【UI组件】")]
[Tooltip("显示模型的RawImage组件")]
[SerializeField] private RawImage displayImage;
[Tooltip("渲染模型的相机")]
[SerializeField] private Camera renderCamera;
[Tooltip("渲染纹理,相机将画面渲染到此,再由RawImage显示")]
[SerializeField] private RenderTexture renderTexture;
[Header("【控制设置】")]
[Tooltip("旋转速度")]
[SerializeField] private float rotationSpeed = 2.0f;
[Tooltip("缩放速度")]
[SerializeField] private float zoomSpeed = 0.5f;
[Tooltip("最小缩放值")]
[SerializeField] private float minZoom = 0.5f;
[Tooltip("最大缩放值")]
[SerializeField] private float maxZoom = 3.0f;
[Tooltip("默认缩放值")]
[SerializeField] private float defaultZoom = 1.0f;
[Header("【相机设置】")]
[Tooltip("相机相对于模型的初始偏移")]
[SerializeField] private Vector3 cameraOffset = new Vector3(0, 0, 5);
[Tooltip("相机视野")]
[SerializeField] private float fieldOfView = 60f;
[Header("【初始变换】")]
[Tooltip("模型的初始旋转")]
[SerializeField] private Vector3 initialRotation = Vector3.zero;
[Tooltip("模型的初始缩放")]
[SerializeField] private Vector3 initialScale = Vector3.one;
// 内部状态变量
private Vector2 currentRotation = Vector2.zero;
private float currentZoom = 1.0f;
private float targetZoom = 1.0f;
private Vector2 lastMousePosition;
private bool isDragging = false;
private bool isInitialized = false;
///
/// 设置要显示的模型
///
/// 要显示的模型对象
public void SetModel(GameObject modelObj)
{
model = modelObj;
if (model != null)
{
InitializeModel();
}
}
///
/// 获取当前显示的模型
///
/// 当前模型对象
public GameObject GetModel()
{
return model;
}
///
/// 初始化组件
///
void Start()
{
Initialize();
}
///
/// 初始化所有组件
///
private void Initialize()
{
if (isInitialized) return;
// 验证必要组件
if (displayImage == null)
{
Debug.LogError("RawImageModelController: 未设置Display Image组件!", this);
return;
}
if (renderCamera == null)
{
Debug.LogError("RawImageModelController: 未设置Render Camera!", this);
return;
}
if (renderTexture == null)
{
Debug.LogError("RawImageModelController: 未设置Render Texture!", this);
return;
}
// 配置渲染相机
ConfigureRenderCamera();
// 设置RawImage的纹理
displayImage.texture = renderTexture;
// 如果已有模型,则初始化
if (model != null)
{
InitializeModel();
}
// 设置初始状态
currentZoom = defaultZoom;
targetZoom = defaultZoom;
currentRotation = new Vector2(initialRotation.y, -initialRotation.x);
isInitialized = true;
}
///
/// 配置渲染相机
///
private void ConfigureRenderCamera()
{
renderCamera.targetTexture = renderTexture;
renderCamera.fieldOfView = fieldOfView;
renderCamera.enabled = true; // 默认启用相机
// 设置相机的初始位置
if (model != null)
{
renderCamera.transform.position = model.transform.position + cameraOffset;
renderCamera.transform.LookAt(model.transform);
}
else
{
renderCamera.transform.position = cameraOffset;
renderCamera.transform.LookAt(Vector3.zero);
}
}
///
/// 初始化模型
///
private void InitializeModel()
{
if (model == null) return;
// 设置模型的初始状态
model.transform.localRotation = Quaternion.Euler(initialRotation);
model.transform.localScale = initialScale;
// 将相机定位到模型前方
renderCamera.transform.position = model.transform.position + cameraOffset;
renderCamera.transform.LookAt(model.transform);
}
///
/// 每帧更新
///
void Update()
{
if (!isInitialized || model == null) return;
HandleInput();
UpdateModelTransform();
}
///
/// 处理用户输入
///
private void HandleInput()
{
// 检查鼠标是否在RawImage区域内
if (IsMouseOverDisplayImage())
{
// 旋转控制(鼠标左键拖拽)
if (Input.GetMouseButtonDown(0))
{
isDragging = true;
lastMousePosition = Input.mousePosition;
}
if (Input.GetMouseButton(0) && isDragging)
{
Vector2 currentMousePos = Input.mousePosition;
Vector2 delta = currentMousePos - lastMousePosition;
// 根据鼠标移动增量更新旋转角度
currentRotation.x += delta.y * rotationSpeed * 0.1f; // 绕X轴旋转
currentRotation.y -= delta.x * rotationSpeed * 0.1f; // 绕Y轴旋转
// 限制垂直旋转角度,避免过度翻转
currentRotation.x = Mathf.Clamp(currentRotation.x, -85f, 85f);
lastMousePosition = currentMousePos;
}
if (Input.GetMouseButtonUp(0))
{
isDragging = false;
}
// 缩放控制(鼠标滚轮)
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (Mathf.Abs(scroll) > 0.01f)
{
// 根据滚轮方向调整目标缩放值
targetZoom -= scroll * zoomSpeed;
targetZoom = Mathf.Clamp(targetZoom, minZoom, maxZoom);
}
}
// 重置视图(R键)
if (Input.GetKeyDown(KeyCode.R))
{
ResetView();
}
}
///
/// 检测鼠标是否在显示图像的区域内
///
/// 如果鼠标在区域内返回true,否则返回false
private bool IsMouseOverDisplayImage()
{
if (displayImage == null) return false;
RectTransform rect = displayImage.rectTransform;
Vector2 localPoint;
// 将屏幕鼠标坐标转换为UI矩形内的本地坐标
return RectTransformUtility.ScreenPointToLocalPointInRectangle(
rect, Input.mousePosition, null, out localPoint)
&& rect.rect.Contains(localPoint);
}
///
/// 更新模型的变换
///
private void UpdateModelTransform()
{
if (model == null) return;
// 平滑插值缩放
currentZoom = Mathf.Lerp(currentZoom, targetZoom, 5f * Time.deltaTime);
// 应用旋转
Quaternion targetRotation = Quaternion.Euler(currentRotation.x, currentRotation.y, 0);
model.transform.rotation = targetRotation;
// 应用缩放
model.transform.localScale = initialScale * currentZoom;
// 更新相机位置以保持相对距离
Vector3 cameraDirection = (renderCamera.transform.position - model.transform.position).normalized;
Vector3 targetCameraPosition = model.transform.position + cameraDirection * (cameraOffset.magnitude * currentZoom);
renderCamera.transform.position = targetCameraPosition;
renderCamera.transform.LookAt(model.transform);
}
///
/// 重置视图到初始状态
///
public void ResetView()
{
currentRotation = new Vector2(initialRotation.y, -initialRotation.x);
currentZoom = defaultZoom;
targetZoom = defaultZoom;
if (model != null)
{
model.transform.localRotation = Quaternion.Euler(initialRotation);
model.transform.localScale = initialScale;
}
// 重置相机位置
if (model != null)
{
renderCamera.transform.position = model.transform.position + cameraOffset;
renderCamera.transform.LookAt(model.transform);
}
else
{
renderCamera.transform.position = cameraOffset;
renderCamera.transform.LookAt(Vector3.zero);
}
}
///
/// 设置旋转速度
///
/// 新的旋转速度
public void SetRotationSpeed(float speed)
{
rotationSpeed = speed;
}
///
/// 设置缩放速度
///
/// 新的缩放速度
public void SetZoomSpeed(float speed)
{
zoomSpeed = speed;
}
///
/// 设置缩放限制
///
/// 最小缩放值
/// 最大缩放值
public void SetZoomLimits(float min, float max)
{
minZoom = min;
maxZoom = max;
targetZoom = Mathf.Clamp(targetZoom, minZoom, maxZoom);
}
///
/// 获取当前缩放值
///
/// 当前缩放值
public float GetCurrentZoom()
{
return currentZoom;
}
///
/// 设置当前缩放值
///
/// 目标缩放值
public void SetZoom(float zoom)
{
targetZoom = Mathf.Clamp(zoom, minZoom, maxZoom);
}
///
/// 启用/禁用控制器
///
/// 是否启用
public void SetEnabled(bool enabled)
{
gameObject.SetActive(enabled);
}
///
/// 在编辑器中绘制调试信息
///
void OnValidate()
{
if (renderCamera != null)
{
// 确保相机设置正确
if (fieldOfView > 0)
{
renderCamera.fieldOfView = fieldOfView;
}
}
}
}