【Unity】 Unity目标跟随效果 及 fbx模型导入的相关问题

Unity学习过程中问题记录

一. 目标移动和转向

要学会使用Unity的API手册,里面有一些示范代码是可以直接拿来使用的,而且简单易于理解。

其中Java的示例代码中有相应注释,而C#没有,想要进一步理解C#代码可以参考Java中的相关注释加以理解。以下我所使用的都是C#代码。

回到题目,目标移动和转向功能需要使用的是UnityEngine中Input类中所提供的方法,该方法可以获得水平方向和竖直方向的键盘或鼠标输入,我们此处使用键盘输入,相关介绍如图所示:

void Update()
    {
    	// Get the horizontal and vertical axis.
		// By default they are mapped to the arrow keys.
		// The value is in the range -1 to 1
        float translation = Input.GetAxis("Vertical") * moveSpeed;

        float rotation = Input.GetAxis("Horizontal") * rotationSpeed;
        
        // Make it move 10 meters per second instead of 10 meters per frame...
        translation *= Time.deltaTime;

        rotation *= Time.deltaTime;

		// Move translation along the object's z-axis
        transform.Translate(0, 0, translation);

        // Rotate around our y-axis
        transform.Rotate(0, rotation, 0);
    }

Input.GetAxis(“…”)此中参数是轴的名称,是否有对应该轴向的输入需要检测按键是否被触动,轴的名称以及对应按键要到Edit->Project Setting->input manager中去查看,默认都是AD和左右方向键对应水平方向;WS和上下方向键对应垂直方向。

然后把该脚本挂载到想要控制的物体上就可以进行移动了。

二. 目标跟随的问题

目标跟随是指物体1(Capsule collider)先移动,然后物体2(Camera)以线性插值的方式缓动跟随过去,以达到一个缓冲效果,看起来不那么生硬。如图所示,是Camera跟随Capsule collider的起点和终点。

此效果的实现需要用到Vector3中的线性插值Lerp方法:

参数一应为追随物体坐标,即起点坐标;
参数二应为被追随物体坐标,即终点坐标;
参数三应为追随速度,最好乘以Time.deltaTime转化为物理时间下的速度。

注:物体的父子关系如下图所示。

该代码块调用FollowAngle()的前一行使用该方法,以达到Camera的Position追随Capsule Collider的效果:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraCtrl : MonoBehaviour
{

    public float moveSpeed = 1.0f;

    public float rotationSpeed = 10.0f;

    public float followSpeed = 2.0f;

    Transform cameraTarget;
    // Start is called before the first frame update
    void Start()
    {
        cameraTarget = GameObject.Find("CameraTarget").transform;
    } 

    // Update is called once per frame
    void Update()
    {
        float translation = Input.GetAxis("Vertical") * moveSpeed;

        float rotation = Input.GetAxis("Horizontal") * rotationSpeed;

        translation *= Time.deltaTime;

        rotation *= Time.deltaTime;

        transform.Translate(0, 0, translation);

        transform.Rotate(0, rotation, 0);

        //cameraTarget.position = transform.position;

        cameraTarget.position = Vector3.Lerp(cameraTarget.position, transform.position, Time.deltaTime * followSpeed);
        
        FollowAngle();
    }
}

private void FollowAngle()
    {
        //cameraTarget.rotation = Quaternion.Slerp(cameraTarget.rotation, transform.rotation, Time.deltaTime * followRotate);
        targetSon.rotation = Quaternion.Slerp(targetSon.rotation, transform.rotation, Time.deltaTime * followRotate);
    }

此处为了实现相机后续的朝向追随效果,把相机放到一个组合体(小正方体前方插了一个小长方体,准备分别控制左右摆动和上下摆动)下作为子物件,因此在追随的时候一定要把组合体的碰撞盒关掉,否则永远追随不上,会出现一直碰撞,碰撞后向前运动再追随,这样就是个死循环,所以要关掉组合体的碰撞盒。

前面部分是在阐述移动位置的缓动跟随,即对Position的跟随,而角度的跟随是由 FollowAngle()函数完成的,Rotation和Position的数据类型是不同的,Position是Vector3类型的数据,Rotation是Quaternion类型数据,但为了实现跟随使用方法都是类似的,都属于插值的方法,此处为了实现更自然的效果,我们使用球形插值方法实现角度跟随,描述如下:

至此,位置跟随和角度跟随就完成了。

三. 鼠标左键行为

鼠标左键行为的设定是为了实现原地不动时四处张望的效果,之我们就再次需要使用input中“获得轴”的方法,与上面不同的是,上面使用键盘输入,而这里要使用的是鼠标输入,预期效果:按住鼠标左键拖动,返回鼠标坐标的变化量,从而让摄像机进行旋转。
注1:下面的代码块前面功能都保留了,若只想了解该部分的代码实现,可以直接看MouseAction()函数体部分;
注2:此处把前面所使用的CameraTarget移除了,只使用TargetSon就能够完成所有相关功能,没有必要多一个物体。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraCtrl : MonoBehaviour
{

    public float moveSpeed = 1.0f;

    public float rotationSpeed = 50.0f;

    public float followSpeed = 2.0f;

    public float followRotate = 2.0f;

    Transform targetSon;

    // Start is called before the first frame update
    void Start()
    {
        targetSon = GameObject.Find("TargetSon").transform;
    } 

    // Update is called once per frame
    void Update()
    {
        float translation = Input.GetAxis("Vertical") * moveSpeed;

        float rotation = Input.GetAxis("Horizontal") * rotationSpeed;

        translation *= Time.deltaTime;

        rotation *= Time.deltaTime;

        transform.Translate(0, 0, translation);

        transform.Rotate(0, rotation, 0);

        targetSon.position = Vector3.Lerp(targetSon.position, transform.position, Time.deltaTime * followSpeed);

        if (translation == 0 && rotation == 0) 
        {
            MouseAction();
        }

        if (translation != 0 || rotation != 0)
        {
            //防止和目标旋转冲突,要在有方向键输入的时候进行角度追随,没有键盘输入的时候才会检测鼠标的动作,即上一个判断语句,
            //如果使用内插跟随,放到这个判断里就意味着这个角度跟随效果就会变差,没有按键输入马上就会停止跟随,
            //所以两物体之间总会有一个角度差。下次移动旋转的时候又会继续跟随,看起来很奇怪,但若直接使用赋值语句会更生硬,待完善。
            
            FollowAngle();
        }
    }

    private void FollowAngle()
    {
        //targetSon.rotation = transform.rotation;
        
        targetSon.rotation = Quaternion.Slerp(targetSon.rotation, transform.rotation, Time.deltaTime * followRotate);
    }

    private void MouseAction()
    {
        if (Input.GetMouseButton(0))
        {
            float mouseX = Input.GetAxis("Mouse X");

            float mouseY = -Input.GetAxis("Mouse Y");

            targetSon.Rotate(Vector3.up * mouseX * Time.deltaTime * 200f, Space.World);

            targetSon.Rotate(Vector3.right * mouseY * Time.deltaTime * 200f, Space.Self);
           
        }
    }
}


需要注意的是,FollowAngle()和MouseAction()都在控制targetSon的旋转,FollowAngle()是在键盘方向键输入的时候,使targetSon进行角度跟随,是间接的;MouseAction()是鼠标左键控制,使targetSon进行角度旋转,是直接的。如果不加判断,将两个函数同时执行,会产生冲突,例如当鼠标向左拖动,MouseAction()产生作用,而同时FollowAngle()进行角度跟随,即跟随到transform.rotation这个角度,这样无论如何都不会用鼠标拉到你想看的方向,会看到过去又回来的效果。
所以此时要加入判断,在键盘有输入时,则不接收鼠标行为;只有当停止键盘输入时,才可以实现四周张望的效果,这就有了如下的判断语句。

       if (translation == 0 && rotation == 0) 
        {
            MouseAction();
        }

        if (translation != 0 || rotation != 0)
        {            
            FollowAngle();
        }

但这样又会产生一个问题,一旦键盘没有输入,角度跟随马上就会停止,即球形内插未完成就会停止,如下图所示,所以两物体之间总会有一个角度差。下次移动旋转的时候才会继续跟随,看起来很奇怪,这里如果有相关完善方法的读者,希望不吝赐教。

四. 3DS MAX模型制作与导出

1. 模型制作的几个点

1.挤出要将轴锁定,否则会七扭八歪;
2.要进行编辑某个元素要记得右键>转换为>可编辑多边形/网格/面片;
3.到Unity需要使用贴图的部位,要记得使用修改器列表中的UVW贴图,制作UV坐标(目前还不熟练,只是知道需要这个东西);
4.修改器列表中的倒角功能,可以制作有层次变化的物体,比如门四周的切角;
5.到Unity当中需要调整材质的部分,在3DS MAX当中就要预先添加好,但不用很具体,最简单给一个颜色就可以。

2. 导出

按照什么尺寸做的就要选择对应的单位,默认为英寸;
轴一般我们都是以Z轴朝上建立模型,但默认是Y轴朝上。

3. 导出后材质调整

导入的模型一般使用.fbx格式,此时材质Shader栏如果显示Autodesk Interactive且为灰色,则不可编辑,需要到导入模型的Material一栏进行调整,在Location下拉栏中选择“Use External Materials(Legacy)”,生成材质文件夹,Shader栏变为Standard或其他模式,这样就可以进行接下来的材质调整了。

一些材质需要反射场景,则需要添加反射探针,一些动态物体需要接收周围光照的时候则需要添加光线探针若干,在进行光线烘焙的时候,如果模型的UV制作并不完美,可能需要打开模型中的Generate Lightmap UVs to UV2,但这个功能可能有判断失误的风险。

猜你喜欢

转载自blog.csdn.net/zbx727259615/article/details/126655818