2018-07-02 13:02:31 coldwind811201 阅读数 1028

Unity3D 控制摄像机(一)

摄像机跟随

Main Camera上按 Ctrl+Alt+F 使镜头对齐当前视角

参考:Unity3D中摄像机跟随方法https://blog.csdn.net/bobowang1991/article/details/54097075


直接把Camera拖动到被角色下作为角色子物体

角色移动时 镜头作为子物体一起移动

优点:最省事


只旋转摄像机自身 和 Player无关 作为第一人称摄像机

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

public class RotateCamera001 : MonoBehaviour {
    //本例是第一人称摄像机

    public float xSpeed = 2f; //左右旋转摄像机的速度
    public float ySpeed = 2f; //上下旋转摄像机的速度
    public float yMinLimit = -90f; //上下旋转摄像机的最小角度限制
    public float yMaxLimit = 90f;  //上下旋转摄像机的最大角度限制


    //是否旋转镜头 鼠标右键按下时启用
    private bool isRotate;
    //左右旋转的角度 相对世界原始位置 非transform初始位置(沿三维Y轴)
    private float x;
    //上下旋转的角度 相对世界原始位置 非transform初始位置(沿三维X轴)
    private float y;


    void Start ()
    {
        Vector3 angles = transform.eulerAngles;
        //鼠标的左右移动 在三维中相当于沿Y轴转动
        x = angles.y;
        //鼠标的上下移动 在三维中相当于沿X轴转动
        y = angles.x;
    }


    void LateUpdate ()
    {
        //在LateUpdate中更新摄像机 可以更平滑 在Update中会有抖动
        RotateCamera();
    }


    void RotateCamera()
    {
        //鼠标右键按下状态启用旋转摄像机
        if (Input.GetMouseButtonDown(1))
        {
            isRotate = true;
        }

        //鼠标右键抬起状态停止旋转摄像机
        if (Input.GetMouseButtonUp(1))
        {
            isRotate = false;
        }

        if (isRotate)
        {
            //x 和 y 是绝对值 相对于世界坐标没有转动的位置的最终转动位置

            //鼠标的上下移动 移动的Y值 在三维中相当于沿X轴转动
            y -= Input.GetAxis("Mouse Y") * ySpeed;
            //上下需要限定范围 在完全俯视 和 完全仰视之间
            //去掉该限制的话可以使摄像机倒置
            y = Mathf.Clamp(y, yMinLimit, yMaxLimit);


            //鼠标的左右移动 移动的X值 在三维中相当于沿Y轴转动
            //左右是允许360度旋转的 不需要限制到最大最小范围
            x += Input.GetAxis("Mouse X") * xSpeed;

            //Quaternion rotation = Quaternion.Euler(y, x, 0);
            //transform.rotation = rotation;

            //和上面2句等价
            transform.eulerAngles = new Vector3(y, x, 0);
        }
    }
}

该脚本效果 图示为Local坐标系 旋转引发Local坐标系的变化

这里写图片描述

几点说明

  • Input.GetMouseButtonDown 只会在鼠标按键变化时触发一次 保持按住状态不会触发 因此需要使用全局变量IsRotate来判断是否旋转
    比如下述方法就是错误的:
    if (Input.GetMouseButtonDown(1))
    {
    直接处理旋转
    }
  • transform.eulerAngles欧拉角必须三个值一起设置
  • transform.eulerAngles欧拉角设置的是最终位置 最终位置是相对于世界坐标系 而非Local坐标系 也不是相对当前位置的改变量
  • 第一人称摄像机鼠标右键按下时 本身只改变Rotation而不改变Position
  • 上下的旋转需要限定位置 上下旋转即沿红色轴(X)轴旋转(世界坐标系) 左右旋转目前没有限定位置 正常人只能看左右-90 至90
2018-07-02 12:03:06 coldwind811201 阅读数 4672

Unity3D 控制角色(一)

最简单的移动 脚本挂到需要控制的角色上

    public float MoveSpeed = 15.0f;
    public float RotateSpeed = 80.0f;

    void Update () {
        if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
        {
            transform.Translate(0, 0, 1 * MoveSpeed * Time.deltaTime, Space.Self);
        }
        if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
        {
            transform.Translate(0, 0, -1 * MoveSpeed * Time.deltaTime, Space.Self);
        }
        if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
        {
            transform.Translate(-1 * MoveSpeed * Time.deltaTime, 0, 0, Space.Self);
        }
        if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
        {
            transform.Translate(1 * MoveSpeed * Time.deltaTime, 0, 0, Space.Self);
        }


        if (Input.GetKey(KeyCode.Q))
        {
            transform.Rotate(0, -1 * RotateSpeed * Time.deltaTime, 0, Space.Self);
        }
        if (Input.GetKey(KeyCode.E))
        {
            transform.Rotate(0, 1 * RotateSpeed * Time.deltaTime, 0, Space.Self);
        }
    }

所在代码

ControlCharacter001.cs

对上述方法的说明

  • 方法直接操作对象的tranform组件
  • 写在Update中每帧调用
  • translate中的三个坐标值表示的是相对当前位置的位移向量 位移(距离)=速度*时间 时间则是time.deltaTime(单位是秒 表述的是从上一帧到本帧经过的时间 是变化的 速度的单位是米每秒)
  • 对外部暴露2个速度变量可修改(移动和旋转)
  • Time.deltaTime用于协调线性,保证帧与帧之间速度一致,因为帧间隔随机器性能不同,使用Time.deltaTime可以保证是匀速运动
  • 不使用Time.deltaTime的后果是在前端表现出卡顿 速度虽然可以通过2个公有变量进行调整
    关于Time.deltaTime参看 https://blog.csdn.net/wdjhzw/article/details/73433658?locationNum=7&fps=1

需求增加

  • 按键需要可以修改

控制使用的按键可自定义 增加平滑的功能

使用Input,按键不再使用KeyCode这种方式
使用按键轴名定义 Axis
参数位置 Edit -> Project Settings -> Input
这里写图片描述

  • 可以增加自定义轴名称
  • 一个功能分为正向和反向(Negative->反向 Positive->正向)
  • 有第2按键的功能(Alt部分)
  • 平滑的功能(Gravity Dead) 使用GetAxis可以得到平滑滤波的值
  • 使用GetAxisRaw则依然是 -1 0 1三个值
  • 使用GetAxis对应按下键有一个逐渐增加到1的过滤 放开按键逐渐变回0
    这里写图片描述

Positive Button:使用GetButton()时,引用的字符串名
Gravity:使用GetAxis()时,返回0的速度,越大越快
Sensitivity:使用GetAxis()时,达到1或-1的速度,越大越快
Dead:当使用摇杆时,当Dead越大需要移动越大的距离才会有返回值(当不需要过小的返回值时使用)
snap:使用GetAxis()时,如果勾选,正反按键同时按下会返回0

导出后的项目可以给用户修改按键

这里写图片描述

代码

    public float MoveSpeed = 15.0f;
    public float RotateSpeed = 80.0f;

    void Update () {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");

        //Debug.Log(string.Format("h: {0} v: {1}", h, v));

        transform.Translate(h * MoveSpeed * Time.deltaTime, 0, v * MoveSpeed * Time.deltaTime, Space.Self);
    }

增加一项Input Axis 名称为Rotate后 使用 Q 和 E 键旋转

这里写图片描述

    public float MoveSpeed = 15.0f;
    public float RotateSpeed = 80.0f;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        float r = Input.GetAxisRaw("Rotate");

        //Debug.Log(string.Format("h: {0} v: {1}", h, v));

        transform.Translate(h * MoveSpeed * Time.deltaTime, 0, v * MoveSpeed * Time.deltaTime, Space.Self);
        transform.Rotate(0, r * RotateSpeed * Time.deltaTime, 0, Space.Self);
    }

整个平滑的过程

按下按键 值从0逐渐变为1 放开按键从1逐渐变回0
变化的量由Gravity

这里写图片描述

效果 起步和停止都有一个缓冲

这里写图片描述

如果使用GetAxisRaw替换GetAxis则没有缓冲效果
参看 https://blog.csdn.net/cui240558023/article/details/50448013?_t=t

2018-07-02 13:54:04 coldwind811201 阅读数 1023

Unity3D 控制摄像机(二)

摄像机对准Player 围绕Player进行旋转 作为第三人称摄像机

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

public class RotateCamera002 : MonoBehaviour {
    //本例是第三人称摄像机

    public GameObject Player;

    public float xSpeed = 2f; //左右旋转摄像机的速度
    public float ySpeed = 2f; //上下旋转摄像机的速度
    public float yMinLimit = -90f; //上下旋转摄像机的最小角度限制
    public float yMaxLimit = 90f;  //上下旋转摄像机的最大角度限制


    //是否旋转镜头 鼠标右键按下时启用
    private bool isRotate;
    //左右旋转的角度(沿三维Y轴)
    //private float x;
    //上下旋转的角度(沿三维X轴)
    private float y;


    void Start ()
    {
        if (Player == null)
        {
            Player = GameObject.FindGameObjectWithTag("Player");

            if (Player == null)
            {
                Debug.LogWarning("Don't found player tag please change player tag to Player");
            }
        }

        Vector3 angles = transform.eulerAngles;
        //鼠标的左右移动 在三维中相当于沿Y轴转动
        //x = angles.y;
        //鼠标的上下移动 在三维中相当于沿X轴转动
        y = angles.x;
    }


    void LateUpdate ()
    {
        //在LateUpdate中更新摄像机 可以更平滑 在Update中会有抖动
        RotateCamera();
    }

    void RotateCamera()
    {
        //鼠标右键按下状态启用旋转摄像机
        if (Input.GetMouseButtonDown(1))
        {
            isRotate = true;
        }

        //鼠标右键抬起状态停止旋转摄像机
        if (Input.GetMouseButtonUp(1))
        {
            isRotate = false;
        }

        if (isRotate)
        {
            //deltaX是相对值 相对原来玩家垂直位置的转动量 对应的操作是鼠标按住右键左右移动
            float deltaX = Input.GetAxis("Mouse X") * xSpeed;
            //围绕Player的Y轴进行旋转 不需要限制范围 可360度环绕观察
            transform.RotateAround(Player.transform.position, Player.transform.up, deltaX);

            //deltaY是相对值 相对原来相机x轴方向的转动量 对应的操作是鼠标按住右键上下移动
            //负值主要是修正上下对应视角的移动相反
            float deltaY = Input.GetAxis("Mouse Y") * -ySpeed;
            //如果使用了deltaY后的最终位置
            float newY = y + deltaY;
            //限制最终位置的范围 不能在地面下 不能越过头顶到另一侧
            newY = Mathf.Clamp(newY, yMinLimit, yMaxLimit);
            //在限制旋转位置后 计算真正需要的旋转量
            deltaY = newY - y;
            //更新转动后新的位置
            y = newY;
            //围绕摄像机的X轴进行旋转
            transform.RotateAround(Player.transform.position, transform.right, deltaY);
        }
    }
}

几点说明

  • Player是公有变量 需要摄像机注视的对象 可以直接从面板拖拽指定 如果没有设置 则从Tag标签中标为Player的查找指定
  • transform.RotateAround同时改变对象的旋转(rotation)和位置(position) 第一个参数是需要注视的位置 第二个参数是旋转的轴(注意2个方向的旋转必须针对不同的轴) 最后一个参数是角度改变量

Unity3D编辑器中Transform下的Rotation 3个值 实际上对应的值是该组件的欧拉角值(这句话不完全正确看下面)
eulerAngles的属性是Vector3
x -> transform.eulerAngles.x
y -> transform.eulerAngles.y
z -> transform.eulerAngles.z
而transform.rotation的属性是Quaterion(四元数)
quaterion.x .y .z .w 和 欧拉角的 x y z不相等
关于角度参考:https://blog.csdn.net/candycat1992/article/details/41254799
关于角度参考:https://blog.csdn.net/juice521cai/article/details/78970560
关于旋转和缩放摄像机的改进步骤参考:https://blog.csdn.net/yuxikuo_1/article/details/44988215
关于旋转和缩放摄像机参考:https://www.jianshu.com/p/c2fbb22eac05

-

网上所有的文章写的都是Unity3D编辑器中Transform下的Rotation 3个值 实际上对应的值是该组件的欧拉角值
实测并不是永远相等 在一定角度范围内相等
可用如下代码验证
transform.eulerAngles = new Vector3(135, 0, 0); 之后 读取eulerAngles.x的值是45
也就是说Unity3D编辑器中Transform下的Rotation 3个值可正向一直加超过360 可负向一直减-360 -720 等等
但是eulerAngles的范围只在0-360之间

以下图的位置方向锁定y和z轴 只转动X轴 观察eulerAngles值 和 编辑器的Rotation值
摄像机完全向下 相当于顶视图时 eulerAngles的x值是90 完全平视 相当于前视图是即是0也是360 这一段eulerAngles和Rotation是完全相等的
这里写图片描述
这里写图片描述
也就意思味相同的eulerAngles.x值都是有2个指向(如果仅判断x值 欧拉的三值是有顺序,x值相同 位置不同的话 y和z是不同的,使用ShowEulerAngles.cs脚本观察)
同时对应编辑器Rotation的值如下图 不转动超过2圈的前提下
这里写图片描述
如果继续转动数值继续增加 反向转动则减少 增减都无限制

2019-09-22 14:05:19 fengliaoai 阅读数 12376

每周更新unity3d视频教程,从入门到就业,官方unity3d培训,上千门实时更新课程,供学员在线观看学习,unity3d游戏开发,可以让学员随时随地学习!
免费网上学习unity3d自学教程,国内名师机构专业授课,O基础快速学习,1小时快速入门,7天unity3d自学教程学习,能力快速提升,优质作品随手呈现!

unity3d菜鸟自学教程介绍

unity3d难学吗?

unity3d自学教程目录

unity3d视频教程百度网盘下载

unity3d难学吗?
学习unity3d特效,多来学习路线网看教程,一线游戏特效老师,游戏特效就业安排!学习unity3d特效入门+进阶+精通选择专业才能学得专业!

unity3d自学教程目录
课程介绍:
Unity3d史诗 MMO ARPG 课程《泰斗破坏神》,精心设计将包含200+课时,由视频课时+直播课时+测试课时混合组成。最重头unity3d ARGP课程,完整的 ARPG 网络游戏开发教学。包含多人合作,在线多人游戏开发,角色创建系统,作战系统,RPG系统,技能系统,任务系统,商店系统。

课程大纲:

单机版功能实现

项目概要
登录系统
角色创建、选择、自定义系统
场景加载与游戏存储记录
角色控制
聊天通讯
游戏AI
战斗系统
游戏角色与玩家信息系统
商店系统
道具系统
装备系统
装备与道具掉落
仓库与背包系统
副本系统
任务系统
地图与寻路系统

网络版功能实现

服务端搭建
登录系统
角色选择
游戏场景
聊天功能
角色具体信息
商店系统
道具系统
装备系统
仓库和背包
副本系统
任务系统

unity3d视频教程百度网盘下载
http://www.xuexiluxian.net/unity3d-cainiao-zixue.html

2018-07-02 12:20:34 coldwind811201 阅读数 172

接上文
Unity3D 控制角色(一)
https://blog.csdn.net/coldwind811201/article/details/80882593

Unity3D 控制角色(二)

对于使用(一)方法的问题

  • 模型会穿透地形
  • 如果给控制对象简单增加Rigidbody刚体组件会引起翻转
  • 使用角色控制的Move和SimpleMove可以简单粗爆解决

    这里写图片描述

    public float MoveSpeed = 15.0f;

    private CharacterController cc;

    // Use this for initialization
    void Start () {
        cc = GetComponent<CharacterController>();
    }

    // Update is called once per frame
    void Update () {
        cc.SimpleMove(transform.TransformDirection(Vector3.forward) * MoveSpeed * Input.GetAxis("Vertical"));
        cc.SimpleMove(transform.right * MoveSpeed * Input.GetAxis("Horizontal"));
    }

简单说明

  • SimpleMove和Move的区别 SimpleMove自动使用了重力 Move则没有 需要自行处理重力引发的速度
  • 和刚体不同 有刚体的特性 又不完全基于物理 对角色控制更适合
  • 启用后原Colider不再有作用 直接使用的是角色控制器的Colider

Unity3d版本控制

阅读数 963

UNITY3D常用资源网址

阅读数 1829

没有更多推荐了,返回首页