RawImage和RenderTexture在UI界面上投影

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

 

 

在Unity中通过点击RawImage来获取RenderTexture的映射物体需要编写一些脚本逻辑。首先,在场景中创建一个RawImage和一个空物体,并将RawImage设为UI元素。接下来,我们需要在脚本中实现点击RawImage的功能。 首先,在需要实现点击事件的脚本中添加以下代码段: ```csharp using UnityEngine; using UnityEngine.EventSystems; public class ClickRawImage : MonoBehaviour, IPointerClickHandler { public GameObject mappedObject; // 映射的物体 public RenderTexture renderTexture; // 渲染纹理 public void OnPointerClick(PointerEventData eventData) { // 获取点击的位置 Vector2 localCursor; RectTransformUtility.ScreenPointToLocalPointInRectangle(GetComponent<RectTransform>(), eventData.position, null, out localCursor); // 将点击的位置转换为纹理坐标 Vector2 textureCoordinates = new Vector2(localCursor.x / GetComponent<RectTransform>().rect.width + 0.5f, localCursor.y / GetComponent<RectTransform>().rect.height + 0.5f); // 根据纹理坐标获取映射的位置 Ray ray = Camera.main.ViewportPointToRay(textureCoordinates); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { // 获取点击位置的映射物体 mappedObject = hit.transform.gameObject; } } } ``` 在脚本中,我们需要实现接口`IPointerClickHandler`来响应RawImage的点击事件。在点击事件回调函数`OnPointerClick`中,首先计算出点击的位置`localCursor`,然后将其转换为纹理坐标`textureCoordinates`。接着,根据纹理坐标通过Raycast来获取点击位置的映射物体,并将其赋值给`mappedObject`。 最后,将该脚本挂载到RawImage上,并将相应的RenderTexture赋值给脚本中的`renderTexture`变量。这样,当点击RawImage时,就可以通过点击位置获取到映射的物体了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>