Unity中实现360度预览模型(修改版)

最近一直很多人私信问去年写的一篇:Unity中实现360°预览模型的文章,回看了一下去年写的文章,简直惨不忍睹,结构和思路都不太清晰,鉴于问的小伙伴有点多,这里重新写一下这篇文章,希望可以帮到大家。

一、实现方式

要实现模型的360°预览,主要有两种方式:

1. 旋转模型本身,通过改变模型在世界空间的欧拉角或者自身的旋转角来实现。

(将脚本挂载到需要旋转的物体上)

void Update () {
        //transform.Rotate(0,30*Time.deltaTime,0);
        if (Input.GetMouseButton (0)) {
            //将屏幕坐标转化为世界坐标
            var pos = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x,
                Input.mousePosition.y, Camera.main.farClipPlane));
            //求弧度
            var radian = Mathf.Atan2 (-pos.y, pos.x);
            //将弧度转化为角度
            var angle = Mathf.Rad2Deg * radian;
            //改变当前对象在世界空间中的旋转角度
            transform.localEulerAngles = new Vector3 (0, angle, 0);

        }
    }

这种实现方式有很大的局限性,而且对于不规则的模型,比如人物,建筑物,这种实现方式看起来特别别扭,本文不在这里对这种实现方式做过多研究。

2.通过控制摄像机的旋转角度来达到模型旋转的目的,其原理就和我们用手机对一个物体进行360°拍照一样,使手机摄像头始终注视着物体,人拿着手机围绕着物体进行旋转,其呈现效果就好像模型自身在旋转一样。

其实要实现这样的效果很简单,Unity官方已经为我们提供了一个强大的相机插件包了,我们只需要将Unity自带的Cameras包导入到场景中,稍加按照我们的需求修改官方的源码,就能很轻易的实现。

1.导入资源包

image

2.从Asset中找到FreeLookCameraRig 预制体,放入场景中。

image

image

3.在使用前首先阅读以下Cameras下的CameraGuidelines使用说明书。

Camera Rig          <- position will move towards target.
    Pivot           <- adjust Y position for height, X position for horizontal offset
        Camera      <- adjust Z position for distance away from target

Camera Rig 相机操控,移动相机的目标位置上,即将这个GameObject的position移动到
需要旋转查看的目标对象上,使二者的世界左边重合。

Pivot 锚点  改变Pivot的GameObject的Y最表调节高度,改变X坐标调节水平偏移
(最终效果是,物体在视窗中呈现的位置,如果X和Y均为0,则物体在视窗中居中显示,否则根据X和Y的值调整距离屏幕的距离)

Camera 主摄相机  调整这个对象的坐标的Z值来该表物体距离相机的远近程度,这里一般用来实现缩放效果

实现方式和插件的使用注意项大致到这里,下面开始代码部分。

二、实现过程

首先分析一下,我们需要通过手指滑动屏幕(或者是鼠标移动,或者是键盘输入的方式)来控制模型的旋转,当滑动手指时,模型旋转,当手指移开屏幕时,模型旋转速度逐渐变慢,直至速度变为0(停止),由于Unity官方已经封装了一个跨平台输入的插件,我们直接导入(CrossPlatformInput)使用就可以了。
1. 首先创建一个Image,用于接收用户输入,并附加一个TouchPad脚本。

image

在TouchPad.cs中声明两个变量,如下:

    //水平输入值
    public float XValue = 0;
    //垂直输入值
    public float YValue = 0;

修改UpdateVirtualAxes函数如下:

 void UpdateVirtualAxes(Vector3 value)
        {
            value = value.normalized;
            if (m_UseX)
            {
                m_HorizontalVirtualAxis.Update(value.x);
                XValue = value.x;
            }

            if (m_UseY)
            {
                m_VerticalVirtualAxis.Update(value.y);
                YValue = value.y;
            }
        }

修改Update()函数如下:

    void Update()
        {
            if (!m_Dragging)
            {
                return;
            }
            if (Input.touchCount >= m_Id)
            {              
                Vector2 pointerDelta;
                pointerDelta.x = Input.mousePosition.x - m_PreviousMouse.x;
                pointerDelta.y = Input.mousePosition.y - m_PreviousMouse.y;
                m_PreviousMouse = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f);
                UpdateVirtualAxes(new Vector3(pointerDelta.x, pointerDelta.y, 0));
            }
        }

以上函数尽量保持和我的一致,并将宏定义注释掉。如果不注释宏定义,导出真机测试时会达不到预想的效果。读者有时间的话也可以仔细读一下这个插件包的源代码,当时项目比较急,没有空做深入研究,用了这种暴力的方式,其实是不太好的。

2.在场景中找到FreeLookCameraRig对象,修改挂载的FreeLookCam.cs的脚本,增加以下代码:

    //获取用户的输入值 
    public TouchPad touchPad;
    //添加这个脚本目的是:有时需要禁用用户控制模型旋转,
    //可以通过设置组件enabled=false的方式禁用组件,再次通过enabled=true的方式启用组件时,
    //不会出现相机跳动的情况
    private void OnEnable()
        {
            m_LookAngle = transform.localEulerAngles.y;
            m_TiltAngle = transform.localEulerAngles.x;
        }

接下来修改HandleRotationMovement()函数中的代码如下:


 private void HandleRotationMovement()
        {
            if(Time.timeScale < float.Epsilon)
            return;

            // Read the user input
            var x = touchPad.XValue;
            var y = touchPad.YValue;

            // Adjust the look angle by an amount proportional to the turn speed and horizontal input.
            m_LookAngle += x*m_TurnSpeed;

            // Rotate the rig (the root object) around Y axis only:
            m_TransformTargetRot = Quaternion.Euler(0f, m_LookAngle, 0f);

            if (m_VerticalAutoReturn)
            {
                // For tilt input, we need to behave differently depending on whether we're using mouse or touch input:
                // on mobile, vertical input is directly mapped to tilt value, so it springs back automatically when the look input is released
                // we have to test whether above or below zero because we want to auto-return to zero even if min and max are not symmetrical.
                m_TiltAngle = y > 0 ? Mathf.Lerp(0, -m_TiltMin, y) : Mathf.Lerp(0, m_TiltMax, -y);
            }
            else
            {
                // on platforms with a mouse, we adjust the current angle based on Y mouse input and turn speed
                m_TiltAngle -= y*m_TurnSpeed;
                // and make sure the new value is within the tilt range
                m_TiltAngle = Mathf.Clamp(m_TiltAngle, -m_TiltMin, m_TiltMax);
            }

            // Tilt input around X is applied to the pivot (the child of this object)
            m_PivotTargetRot = Quaternion.Euler(m_TiltAngle, m_PivotEulers.y , m_PivotEulers.z);

            if (m_TurnSmoothing > 0)
            {
                m_Pivot.localRotation = Quaternion.Slerp(m_Pivot.localRotation, m_PivotTargetRot, m_TurnSmoothing * Time.deltaTime);
                transform.localRotation = Quaternion.Slerp(transform.localRotation, m_TransformTargetRot, m_TurnSmoothing * Time.deltaTime);
            }
            else
            {
                m_Pivot.localRotation = m_PivotTargetRot;
                transform.localRotation = m_TransformTargetRot;
            }
        }

为FreeLookCam的Touchpad变量赋值,将之前创建的Image拖入到对应位置:

image

预览一下最终效果:

image

具体的大家可以下载工程文件研究一下,这里我就不坐过多的说明了,说的再多还不如看源码。强烈建议看源码,你会收获一些关于欧拉角、线性插值等等一些开发中常用的数学知识。如果有什么问题,可以在公众号私信我互相交流。

欢迎关注公众号:

码码小虫
工程文件地址: https://pan.baidu.com/s/1pL0YyJT,提取码:a47h

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值