Unity中使用RawImage和RenderTexture在UI界面上投影其他相机拍摄的内容
a.单纯的用小窗显示物体
个人认为所谓的 “ 物体A跟随物体B运动 ” 表现为:二者表现为运动(平移、旋转)方向,速度在任何时刻表现一致。
1.在Project界面创建RenderTexture
2.在Hierarchy界面创建RawImage
3.选中第二个摄像机,将New Render Texture挂载上
4.选中RawImage,将New Render Texture挂载上
最终效果如下图所示
b.当小窗显示时,可以控制小窗移动
场景中有两个摄像机,分别挂在不同的脚本
第一个脚本MoveScript.cs
using UnityEngine;
using System.Collections;
public class MoveScript : MonoBehaviour {
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
public static bool isEnableMove;
float moveSensitivity = 1.0f;
float rotationX = 0F;
float rotationY = 0F;
//Quaternion originalRotation;
//鼠标缩放
public float sensitivity = 60f;
public float minFov = 50f;
public float maxFov = 70f;
public float speedMove = 10f;
private float speed;
void Start()
{
// Make the rigid body not change rotation
if (GetComponent<Rigidbody>())
GetComponent<Rigidbody>().freezeRotation = true;
// originalRotation = transform.localRotation;
speed = speedMove;
isEnableMove = true;
}
void Update()
{
fnRotate();
if (isEnableMove)
fnMove();
// fnScroll();
}
void fnRotate()
{
CharacterController controller = gameObject.GetComponent<CharacterController>();
if (Input.GetMouseButton(1))//0对应左键 , 1对应右键 , 2对应中键
{
if (axes == RotationAxes.MouseXAndY)
{
float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
else if (axes == RotationAxes.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
}
else
{
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
}
}
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
void fnScroll()
{
float fov = Camera.main.fieldOfView;
fov -= Input.GetAxis("Mouse ScrollWheel") * sensitivity;
fov = Mathf.Clamp(fov, minFov, maxFov);
Camera.main.fieldOfView = fov;
}
void fnMove()
{
if (Input.GetKey(KeyCode.LeftShift))
{
speed = speedMove * 2f;
}
else
speed = speedMove;
float fTranslationV = Input.GetAxis("Vertical") * speed;
float fTranslationH = Input.GetAxis("Horizontal") * speed;
transform.Translate(0, 0, fTranslationV * Time.deltaTime);
transform.Translate(fTranslationH * Time.deltaTime, 0, 0);
if(Input.GetKey(KeyCode.E))
{
transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y + 0.5f * speed * Time.deltaTime, transform.localPosition.z);
}
else if (Input.GetKey(KeyCode.Q))
{
transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y - 0.5f * speed * Time.deltaTime, transform.localPosition.z);
}
}
}
第二个脚本CameraControl.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 摄像机控制类
/// </summary>
public class CameraControl : MonoBehaviour
{
#region Private Variable
/// <summary>
/// 世界坐标X轴与本地坐标X轴之间的夹角
/// </summary>
float angleOfWorldToLocalX;
/// <summary>
/// 世界坐标系Y轴与本地坐标系Y轴之间的夹角
/// </summary>
float angleOfWorldToLocalY;
/// <summary>
/// 摄像机距离观察点的目标距离
/// </summary>
float targetDistance;
/// <summary>
/// 摄像机距离观察点的当前距离
/// </summary>
float currentDistance;
/// <summary>
/// 摄像机的目标朝向
/// </summary>
Quaternion targetRotation;
#endregion
#region Public Variable
/// <summary>
/// 鼠标在X轴方向移动的灵敏度
/// </summary>
public float sensitivityOfX = 5f;
/// <summary>
/// 鼠标在Y轴方向移动的灵敏度
/// </summary>
public float sensitivityOfY = 5f;
/// <summary>
/// 滑轮转动的灵敏度
/// </summary>
public float sensitivityOfScrollWheel = 5f;
/// <summary>
/// 摄像机的旋转速度
/// </summary>
public float rotateSpeed = 10f;
/// <summary>
/// 摄像机的平移速度
/// </summary>
public float translateSpeed = 10f;
/// <summary>
/// 摄像机观察的目标
/// </summary>
public Transform lookTarget;
/// <summary>
/// X轴最小限位角度
/// </summary>
public float minLimitAngleX = -360f;
/// <summary>
/// X轴最大限位角度
/// </summary>
public float maxLimitAngleX = 360f;
/// <summary>
/// Y轴最小限位角度
/// </summary>
public float minLimitAngleY = -360f;
/// <summary>
/// Y轴最大限位角度
/// </summary>
public float maxLimitAngleY = 360f;
/// <summary>
/// 最小观察距离
/// </summary>
public float minLimitDistance = 2f;
/// <summary>
/// 最大观察距离
/// </summary>
public float maxLimitDistance = 10f;
#endregion
#region Private Method
private void Start()
{
//计算世界坐标系与本地坐标系轴向的夹角
angleOfWorldToLocalX = Vector3.Angle(Vector3.right, transform.right);
angleOfWorldToLocalY = Vector3.Angle(Vector3.up, transform.up);
//计算观察目标与摄像机的距离
currentDistance = Vector3.Distance(lookTarget.position, transform.position);
targetDistance = currentDistance;
}
//在Update方法之后,在每一帧被调用(防止摄像机比要移动的物体先移动,造成穿帮)
private void LateUpdate()
{
if (Input.GetMouseButton(1))
{
//在鼠标移动与夹角变化之间建立映射关系
angleOfWorldToLocalX += Input.GetAxis("Mouse X") * sensitivityOfX;
angleOfWorldToLocalY -= Input.GetAxis("Mouse Y") * sensitivityOfY;
//处理摄像机旋转角度的限位
angleOfWorldToLocalX = Mathf.Clamp(angleOfWorldToLocalX,minLimitAngleX, maxLimitAngleX);
angleOfWorldToLocalY = Mathf.Clamp(angleOfWorldToLocalY,minLimitAngleY, maxLimitAngleY);
//计算目标朝向,将欧拉角转换为四元数
targetRotation = Quaternion.Euler(angleOfWorldToLocalY, angleOfWorldToLocalX, 0);
//将摄像机向目标朝向进行移动
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, rotateSpeed * Time.deltaTime);
}
//建立滑轮移动与摄像机移动之间的映射关系
targetDistance += Input.GetAxis("Mouse ScrollWheel")* sensitivityOfScrollWheel;
//处理摄像机移动距离的限位
targetDistance = Mathf.Clamp(targetDistance,minLimitDistance, maxLimitDistance);
//计算摄像机与观察点的当前距离
currentDistance = Mathf.Lerp(currentDistance,targetDistance, translateSpeed * Time.deltaTime);
//更新摄像机的位置
transform.position =lookTarget.position - transform.forward * currentDistance;
}
#endregion
}
注意
在场景中摄像机的移动一般分为:a.摄像机围绕某一固定点移动,b.摄像机无限制的在场景中移动。MoveScript.cs脚本就是摄像机无限制的在场景中移动,CameraControl.cs脚本则是摄像机围绕某一固定点移动,需要注意的是CameraControl.cs脚本挂载到摄像机之后需要从外部找一个需要围绕旋转的目标点拖拽到脚本上,如图所示
最后加一个选择摄像机的脚本SwitchCamRotate.cs 将该脚本挂载到场景中的空物体上即可
// ========================================================
// 描 述:
// 作 者:蔡雨晨
// 创建时间:2019/12/10 08:36:44
// 版 本:v 1.0
// ========================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SwitchCamRotate : MonoBehaviour
{
#region Public Variable
public GameObject MainCam;//第一个摄像机
public GameObject SecondCam;//第二个摄像机
#endregion
#region Private Variable
private static SwitchCamRotate instance;
public static SwitchCamRotate Instance
{
get
{
return instance;
}
set
{
instance = value;
}
}
#endregion
#region Private Function
private void Awake()
{
instance = this;
}
private void Start()
{
SecondCam.SetActive(false);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.M))//按下M键,右上角小窗显示
{
SecondCam.SetActive(true);
}
if (Input.GetKeyDown(KeyCode.N))//按下N键,右上角小窗隐藏
{
SecondCam.SetActive(false);
}
if (SecondCam.activeSelf//当右上角小窗显示时,按住鼠标右键移动,动的是小窗,反之,动的是主摄像机
{
MainCam.GetComponent<MoveScript>().enabled = false;
SecondCam.GetComponent<CameraControl>().enabled = true;
}
else
{
MainCam.GetComponent<MoveScript>().enabled = true;
SecondCam.GetComponent<CameraControl>().enabled = false;
}
}
#endregion
}
转载:https://blog.csdn.net/qq_43511290/article/details/103462540