Unity实现360度可旋转、缩放单独看模型
创作时间:
2025-03-15 17:13:39
作者:
@小白创作中心
Unity实现360度可旋转、缩放单独看模型
引用
CSDN
1.
https://m.blog.csdn.net/weixin_48388330/article/details/138290070
本文介绍如何在Unity中实现一个可以360度旋转和缩放的模型展示功能。通过自定义脚本控制模型的旋转和缩放,结合鼠标交互实现直观的模型查看体验。
一、说明
实现模型的单独交互,显示在面板上,可以进行旋转和缩放操作。
二、代码演示
using UnityEngine;
public class ModelShowControl : MonoBehaviour
{
[SerializeField][Header("渲染展示相机")]
private GameObject showCamera;
[SerializeField][Header("展示交互的物品")]
private GameObject showGameObject;
[SerializeField][Header("是否自动旋转")]
private bool isAutoRotate;
[SerializeField][Header("自动旋转方向,例如(0,1,0)按照Y轴旋转")]
private Vector3 autoRotateDirection;
[SerializeField][Header("是否按照自身坐标系轴自动旋转")]
private bool isAutoRotatePivot;
[SerializeField][Header("自动旋转速度")]
private float autoRotationSpeed = 5;
[SerializeField][Header("鼠标旋转速度")]
private float mouseRotateSpeed = 0.5f;
[SerializeField][Header("是否反向旋转X")]
private bool isRotateInvertX;
[SerializeField][Header("是否反向旋转Y")]
private bool isRotateInvertY;
[SerializeField][Header("缩放速度")]
private float zoomSpeed = 0.5f;
[SerializeField][Header("是否反向缩放")]
private bool isZoomInvert;
[SerializeField][Header("最近缩放距离")]
private float minZoomDistance = 1f;
[SerializeField][Header("最远缩放距离")]
private float maxZoomDistance = 10f;
private Vector3 cameraInitPos;
private Vector3 lastMousePosition;
private bool isRotating; //是否正在旋转
private Vector3[] showGameObjectInitTrans = new Vector3[3];
public static ModelShowControl Instance;
private void Awake()
{
Instance = this;
cameraInitPos = showCamera.transform.position;
}
public void SetShowGameObject(GameObject _gameObject)
{
showGameObjectInitTrans[0] = _gameObject.transform.position;
showGameObjectInitTrans[1] = _gameObject.transform.eulerAngles;
showGameObjectInitTrans[2] = _gameObject.transform.localScale;
showGameObject = _gameObject;
showCamera.transform.position = cameraInitPos;
}
public void RestoreShowGameObject()
{
showGameObject.transform.position = showGameObjectInitTrans[0];
showGameObject.transform.eulerAngles = showGameObjectInitTrans[1];
showGameObject.transform.localScale = showGameObjectInitTrans[2];
showGameObject = null;
showCamera.transform.position = cameraInitPos;
isRotating = false;
}
void Update()
{
if (showGameObject == null)
return;
if (isAutoRotate && !Input.GetMouseButton(0)) // 如果鼠标左键没按下
RotateModelContinuously(); // 持续旋转模型
else
RotateModelOnMouseDrag(); // 根据鼠标拖拽旋转模型
ZoomCamera();
}
void RotateModelContinuously()
{
if (!isAutoRotatePivot)
showGameObject.transform.Rotate(autoRotateDirection, autoRotationSpeed * Time.deltaTime, Space.World);
else
{
var rotateEuler = autoRotateDirection * autoRotationSpeed * Time.deltaTime;
// 根据模型当前朝向构造一个围绕轴旋转的四元数
Quaternion deltaRotation = Quaternion.Euler(rotateEuler);
// 将新的旋转应用到模型
showGameObject.transform.rotation *= deltaRotation;
}
}
void RotateModelOnMouseDrag()
{
if (Input.GetMouseButtonDown(0))
{
isRotating = true;
lastMousePosition = Input.mousePosition;
}
else if (Input.GetMouseButtonUp(0))
{
isRotating = false;
}
if (isRotating && (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0))
{
Vector3 currentMousePosition = Input.mousePosition;
Vector3 mouseDeltaPosition = currentMousePosition - lastMousePosition;
float rotationX = -mouseDeltaPosition.y * mouseRotateSpeed;
float rotationY = mouseDeltaPosition.x * mouseRotateSpeed;
showGameObject.transform.Rotate(Vector3.up, isRotateInvertX ? rotationY : -rotationY, Space.World);
showGameObject.transform.Rotate(Vector3.right, isRotateInvertY ? rotationX : -rotationX, Space.World);
lastMousePosition = currentMousePosition;
}
}
void ZoomCamera()
{
// 获取鼠标滚轮的滚动值
float scrollWheelInput = Input.GetAxis("Mouse ScrollWheel");
if (scrollWheelInput == 0) return;
// 计算缩放后的相机距离
float zoomDistance = showCamera.transform.localPosition.z -
scrollWheelInput * (isZoomInvert ? zoomSpeed : -zoomSpeed);
zoomDistance = Mathf.Clamp(zoomDistance, -maxZoomDistance, -minZoomDistance);
// 设置相机距离
showCamera.transform.localPosition = new Vector3(cameraInitPos.x, cameraInitPos.y, zoomDistance);
}
}
三、使用说明
- 设置一个需要显示交互的模型相机
- 将相机拖入ShowCamera中,需要展示的模型可以在运行时直接放入,需要使用
SetShowGameObject(showGameObject);//调用方法
也可以运行时添加显示模型:
ModelShowControl.Instance.SetShowGameObject(showGameObject);//调用方法
配合鼠标射线检测进行如下调用(要展示的模型设置Tag为ModelShow):
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ModelShowManager : MonoBehaviour
{
public GameObject modelShowGameObjectParent;
public GameObject modelShowPanel;
public Button closeModelShowPanelBtn;
private void Awake()
{
closeModelShowPanelBtn.onClick.AddListener(() =>
{
modelShowPanel.SetActive(false);
ModelShowControl.Instance.RestoreShowGameObject();
});
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
if (hitInfo.collider.CompareTag("ModelShow"))
{
modelShowPanel.SetActive(true);
for (int i = 0; i < modelShowGameObjectParent.transform.childCount; i++)
{
var child = modelShowGameObjectParent.transform.GetChild(i).gameObject;
if (child.name == hitInfo.collider.gameObject.name)
{
child.SetActive(true);
ModelShowControl.Instance.SetShowGameObject(child);
}
else
{
child.SetActive(false);
}
}
}
}
}
}
}
- 添加一个New Render Texture给相机上
- 添加Image的UI,创建一个材质,选择
将New Render Texture赋给该材质,然后将材质赋给Image
四、演示结果
现在就可以360度显示模型,可以鼠标交互旋转缩放。
热门推荐
国际海运公司如何调整和优化其全球布局与战略?
南京的“简称”是什么?游客纳闷:难道不是“南”?
新能源车主必看!新规下车辆年检重点变化与注意事项
C4D对电脑配置要求,新手避坑篇!
显微镜的镜头具体分类
福安市适合孩子的景点,福安市适合孩子的景点排名
自媒体摄影师如何脱颖而出?
韩军误炸平民区闯2个大祸 军事失误引发半岛危机
核函数(Kernel function)(举例说明,通俗易懂)
印度种姓制度:古老而严苛的社会结构,历史与文化的一面镜子
股票涨跌的原理是什么?投资者如何根据市场动态做出合理决策?
股票的主力构成是怎样的?这种构成如何影响股价?
民生疾苦之重,诗词关注显真情
如何选择合适的溶剂?这些溶剂的选择依据是什么?
实验目录 | 高中地理实验实操攻略25——模拟褶皱的形成过程
姚孟起:被称为“清朝欧楷第一人”,这么正宗的欧楷,十分难得
工业废水及苦咸水中硼元素脱除与资源化利用技术
揭秘水杨酸在植物免疫中的关键作用——四川大学张跃林课题组最新研究分享
孩子突发高热惊厥,家长该如何正确应对?建议“五步走”…
H3C交换机的配置文件导入
股票的DDE指标是什么?这种指标如何帮助投资者分析市场趋势?
CEO与总经理职责区别探析
记忆力减退怎么回事?4个原因导致记忆力减退
一文带你详细了解边坡失稳的主要发生地、后果、模式及分析方式
买房贷款可提前还款,降低利息成本
3分钟带你了解雅思单科重考注意事项!
所有权绝对消灭的法律界定与实例分析
所有权绝对消灭的法律界定与实例分析
封爵之誓曰:使河如带,泰山若厉,国以永宁,爰及苗裔。
山茶花的养殖方法