一、前言
其实之前已经写了关于如何控制模型的旋转、移动、缩放效果:
【虚拟仿真】Unity3D中实现控制物体的旋转、移动、缩放 之前写的这篇文章是使用鼠标的位置以及鼠标的滑动量以及控制摄像机的远近来实现对模型的旋转、移动、缩放,简而言之就是直接控制在模型上。
那么这篇文章就通过控制摄像机来实现对模型的旋转、缩放效果的实现。
效果图:
二、正文
(1)新建脚本,命名为CameraTargetMove.cs,双击打开代码编辑代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraTargetMove : MonoBehaviour
{
public Transform target;
public Vector3 pivotOffset = Vector3.zero;
public float distance = 10.0f;
public float minDistance = 2f;
public float maxDistance = 15f;
public float zoomSpeed = 1f;
public float xSpeed = 250.0f;
public float ySpeed = 250.0f;
public bool allowYTilt = true;
public float yMinLimit = -90f;
public float yMaxLimit = 90f;
private float x = 0.0f;
private float y = 0.0f;
private float targetX = 0f;
private float targetY = 0f;
public float targetDistance = 0f;
private void Start()
{
var angles = transform.eulerAngles;
targetX = x = angles.x;
targetY = y = ClampAngle(angles.y, yMinLimit, yMaxLimit);
targetDistance = distance;
}
private void LateUpdate()
{
if (!target) return;
var scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll > 0.0f) targetDistance -= zoomSpeed;
else if (scroll < 0.0f)
targetDistance += zoomSpeed;
targetDistance = Mathf.Clamp(targetDistance, minDistance, maxDistance);
if (Input.GetMouseButton(1) || (Input.GetMouseButton(0) && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))))
{
targetX += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
if (allowYTilt)
{
targetY -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
targetY = ClampAngle(targetY, yMinLimit, yMaxLimit);
}
}
x = targetX;
y = targetY;
Quaternion rotation = Quaternion.Euler(y, x, 0);
distance = targetDistance;
Vector3 position = rotation * new Vector3(0.0f, 0.0f, -distance) + target.position + pivotOffset;
transform.rotation = rotation;
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);
}
}
(2)将脚本附加到摄像机上:
(3)将目标点拖入摄像机上面的CameraTargetMove脚本组件的Target属性的卡槽中:
效果图:
按照往常来说,文章到这里就应该结束了,但是有一个粉丝问我,你写的某某某篇文章实现了什么什么效果,到底有什么用。
在那个时候我都在想,或许应该做出一些改变,比如说,不仅仅把功能如何实现写出来,也要写出来,这个功能应用在什么地方,才能更好的帮助读者。
那么就接着往下看吧,
三、实例
首先,解释一下,这个功能用在什么地方。
使用地方:
(1)对于某个模型的3D展示
(2)设备的展示(通常有设备的3D展示+文字解释+切换设备)
实例:
设备的3D展示、切换设备、文字解释
(1)搭建UI
就很简单的UI,分成左中右结构,需要注意的是中间的模型展示需要用RawImage组件,后面将摄像机的图像渲染到这个框里面,大小需要注意一下,需要跟后面新建的Render Texture大小一致,不然画面可能被拉伸:
(2)新建脚本,命名为EquipmentDisplay.cs,双击打开脚本编辑代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EquipmentDisplay : MonoBehaviour
{
public Button[] BtnEquipmentList;//按钮列表
public Text TextDetails;//显示的文字
public GameObject[] AllModels;//所有的模型
private int Index;//记录上一次点击的下标
private string[] StrDetails = new string[] { "立方体", "球体", "胶囊体", "圆柱体" };//文字提示列表
void Start()
{
// 按钮绑定事件
for (int i = 0; i < BtnEquipmentList.Length; i++)
{
int index = i;
BtnEquipmentList[i].onClick.AddListener(() => BtnEquipmentListEvent(index));
}
// 所有的模型隐藏
for (int i = 0; i < AllModels.Length; i++)
{
AllModels[i].SetActive(false);
}
// 初始化
Index = 0;
AllModels[0].gameObject.SetActive(true);
TextDetails.text = StrDetails[0];
}
void BtnEquipmentListEvent(int index)
{
AllModels[Index].SetActive(false);
AllModels[index].SetActive(true);
Index = index;
TextDetails.text = StrDetails[index];
}
}
(3)将脚本附加到Maincamera对象上,将对应的UI拖到对应的卡槽中:
(4)新建一个Render Texture用来渲染摄像机的图像:
大小设置的跟你RawImage一致即可:
(5)设置将摄像机的图像渲染到RawImage上面:
(6)运行程序:
有点违和?没关系,只需要设置一下摄像机的属性即可:
效果图:
(7)再次运行程序:
四、后记
源代码
源代码已上传:
https://gitcode.net/q764424567/demo_model_rs
错误1:
如果有下图的错误,这是没有摄像机渲染场景了:
新建一个摄像机即可:
错误2:
模型有重影:
将新添加的摄像机设置一下属性,跟渲染模型的摄像机的Background设置成一样:
错误3:
如果有下图的错误,这是因为场景中始终只能有一个音频监听器,
去掉一个摄像机的Audio Listener组件即可: