Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果

梗概:

一. 摄像机围绕目标物体旋转, 即摄像机离目标物体有一定的距离且旋转轴心为该物体的位置.

二. 当目标物体被障碍物挡住后, 需要将摄像机移动到障碍物前方能看见目标物体的位置.

思路:

一. 摄像机绕轴心旋转, 可以在轴心处创建一个空物体, 将摄像机设为该轴心的子物体. 如图:

这样便可以简单地实现摄像机旋转轴心 (注意: 旋转时应旋转轴心而不是单独旋转摄像机) . 还应注意, 如果摄像机的目标物体可以移动的话, 就应每帧将轴心的坐标设为目标物体的坐标 (尽量不要直接将轴心设为目标物体的子物体! 除非有特别需要) .

二. 当目标物体被障碍物挡住后, 可以在目标物体处发射一条射线, 射线原点就是目标物体的坐标 (也就是轴心) , 射线方向就是从原点到摄像机的方向. 此时射线的碰撞点就是将要把摄像机调整到的位置.

三. 当将摄像机移动到后方没有障碍物的位置时, 就应将摄像机移回至原距离.

过程:

  1. 创建任意目标物体;

  2. 创建一个空物体并命名, 这个空物体就是轴心, 并将其 Tag 设为 "3rdCameraAxle":

    或者将其 Tag 设为你喜欢的一个都可以;

  3. 创建摄像机, 将其 Tag 设为 "MainCamera", 并设为刚创建的轴心的子物体;

  4. 创建任意障碍物.

代码:

一. 此时绕物体旋转摄像机便可简化为直接旋转轴心, 代码也简化了许多:

  1. 定义鼠标灵敏度:

    public float mouseSensitivity = ;
  1. 定义目标物体的  Transform  :

    public Transform targetTrans;
  1. 定义轴心  Transform  与轴心旋转角度:

    Transform thirdPCamAxle;
    Vector3 thirdPCamEuler;

    在  void Start()  下对其赋值:

    void Start () {
    thirdPCamAxle = GameObject.FindGameObjectWithTag("3rdCameraAxle").transform; //括号里的引号中也可以写上你自己对轴心设的 Tag.
    thirdPCamEuler = thirdPCamAxle.localEulerAngles; //推荐写 localEulerAngles, 要不之后处理起来会比较麻烦.
    }
  2. 定义摄像机:

    Camera thirdPCam;

    在  void Start()  下对其赋值:

    void Start () {
    thirdPCam = Camera.main;
    }
  3. 定义并赋值摄像机离物体的最大距离, 摄像机离物体的当前距离:

    float camForwardMaxDistance = ;
    float camForwardDistance;
    float camBackDistance;
  4. 在  void Update()  下写:

    thirdPCamAxle.position = targetTrans.position; //将摄像机旋转轴心位置设为目标物体位置
    //定义旋转量
    float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;
    float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity;
    thirdPCamEuler.y += mouseX; //控制摄像机左右旋转
    //控制摄像机上下旋转, 并且上下旋转范围不能超过90°或-90°, 此方法适用于 localEulerAngles.
    if (thirdPCamEuler.z < && mouseY > ) { thirdPCamEuler.z += mouseY; }
    if (thirdPCamEuler.z > - && mouseY < ) { thirdPCamEuler.z += mouseY; }
    thirdPCamAxle.localEulerAngles = thirdPCamEuler; //将旋转量应用到摄像机上.

至此, 控制摄像机旋转完成. 此部分代码如下:

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

public class ThirdPCamC : MonoBehaviour {
public float mouseSensitivity = ;
public Transform targetTrans;

Transform thirdPCamAxle;
Vector3 thirdPCamEuler;

Camera thirdPCam;
float camForwardMaxDistance = ;
float camForwardDistance;
float camBackDistance;

void Start () {
thirdPCamAxle = GameObject.FindGameObjectWithTag("3rdCameraAxle").transform;
thirdPCamEuler = thirdPCamAxle.localEulerAngles;

thirdPCam = Camera.main;
} void Update () {
thirdPCamAxle.position = targetTrans.position;

float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity;
thirdPCamEuler.y += mouseX;
if (thirdPCamEuler.z < && mouseY > ) { thirdPCamEuler.z += mouseY; }
if (thirdPCamEuler.z > - && mouseY < ) { thirdPCamEuler.z += mouseY; }
thirdPCamAxle.localEulerAngles = thirdPCamEuler;
}
}

二. 摄像机避开障碍物, 并在后方没有障碍物时移回原距离 (原距离可通过设置对  camForwardMaxDistance  的赋值来改变):

在   void Update()   下写:

Ray camForwardRay = new Ray(thirdPCam.transform.position, thirdPCam.transform.forward); //在摄像机处发射一条向前的射线, 用来检测摄像机当前离目标的距离 (此处不必担心射线碰撞处是障碍物的情况).
RaycastHit forwardRayHit; //定义射线碰撞.
if (Physics.Raycast(camForwardRay, out forwardRayHit)) //当射线有碰撞物时 (也就是目标物体),
{
camForwardDistance = Vector3.Distance(thirdPCam.transform.position, forwardRayHit.point); //计算从摄像机到碰撞点的距离 (碰撞点也可以改为目标物体的位置).
}

Vector3 dir = thirdPCam.transform.position - targetTrans.position; //定义从目标物体到摄像机的方向.
dir = dir.normalized; //将方向单位化.
Ray ray = new Ray(targetTrans.position, dir); //在目标物体处发射一条射线, 方向即为刚刚定义的向量.
RaycastHit hit; //定义射线碰撞.
if (Physics.Raycast(ray, out hit)) //当该射线有碰撞, 即目标物体被障碍物挡住时,
{
thirdPCam.transform.position = hit.point; //将摄像机位置设为碰撞点位置.
}
else //如果没有碰撞, 即目标物体没有被障碍物挡住,
{
if (camForwardDistance < camForwardMaxDistance) //并且当前距离没有超过最大距离时,
{
thirdPCam.transform.Translate(Vector3.back * Time.deltaTime * ); //将摄像机缓慢后移至最大距离.
}
}

全部代码如下:

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

public class ThirdPCamC : MonoBehaviour {
public float mouseSensitivity = ;
public Transform targetTrans;

Transform thirdPCamAxle;
Vector3 thirdPCamEuler;

Camera thirdPCam;
float camForwardMaxDistance = ;
float camForwardDistance;
float camBackDistance;

void Start () {
thirdPCamAxle = GameObject.FindGameObjectWithTag("3rdCameraAxle").transform;
thirdPCamEuler = thirdPCamAxle.localEulerAngles;

thirdPCam = Camera.main;
} void Update () {
thirdPCamAxle.position = targetTrans.position;

float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity;
thirdPCamEuler.y += mouseX;
if (thirdPCamEuler.z < && mouseY > ) { thirdPCamEuler.z += mouseY; }
if (thirdPCamEuler.z > - && mouseY < ) { thirdPCamEuler.z += mouseY; }
thirdPCamAxle.localEulerAngles = thirdPCamEuler;

Ray camForwardRay = new Ray(thirdPCam.transform.position, thirdPCam.transform.forward);
RaycastHit forwardRayHit;
if (Physics.Raycast(camForwardRay, out forwardRayHit))
{
camForwardDistance = Vector3.Distance(thirdPCam.transform.position, forwardRayHit.point);
}

Vector3 dir = thirdPCam.transform.position - targetTrans.position;;
dir = dir.normalized;
Ray ray = new Ray(targetTrans.position, dir);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Debug.DrawLine(ray.origin, hit.point, Color.green);
thirdPCam.transform.position = hit.point;
}
else
{
if (camForwardDistance < camForwardMaxDistance)
{
thirdPCam.transform.Translate(Vector3.back * Time.deltaTime * );
}
}
}
}

最终效果图:

希望本篇教程能够帮到大家!

源码: [GitHub](https://github.com/JadMax/Unity3D-Miscellaneous/blob/master/ThirdpersonCameraController.cs)

Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果的更多相关文章

  1. Unity摄像机围绕物体旋转两种实现方式

    第一种,使用Transform 函数 RotateAround. 代码如下: public Transform target;//获取旋转目标 private void camerarotate() ...

  2. Unity 3d 实现物体跟随摄像机视野运动

    https://blog.csdn.net/qq_31411825/article/details/61623857 Unity 3d 实现物体跟随摄像机视野运动Created by miccall ...

  3. Unity 3D使用GameObject创建一个简单的可移动物体

    于Unity 3D游戏的开发.游戏脚本需要3D模拟组合,该脚本将被写入阻力3D为了达到效果对象. 以下是一个小实例,使用Unity 3D实现一个可控制移动的小人.小人能够向前.向后.向左和向右移动. ...

  4. Unity KGFMapSystem插件制作小地图

    KGFMapSystem版本:2.3 在我们开发游戏或者虚拟现实中,一般都会用到小地图,如果要我们去写小地图,可以用到unity 3d中就有一个插件,是专门开发小地图用的,这个插件就是KGFMapSy ...

  5. 【Unity 3D 游戏开发】Unity3D 入门 - 工作区域介绍 与 入门示例

    一. 工作区域详解 1. Scence视图 (场景设计面板) scence视图简介 : 展示创建的游戏对象, 可以对所有的游戏对象进行 移动, 操作 和 放置; -- 示例 : 创建一个球体, 控制摄 ...

  6. Unity 3D入门简介

    最近在刚开始学习Unity 3D,在这里记录一下学习心得和学习笔记,边学边写,可能会比较零散.好了,废话不多说,今天从Unity 3D入门写起,主要简要介绍一下Unity 3D的和一些学习资料.以下如 ...

  7. 【Unity 3D 游戏开发】Unity3D 入门 - 工作区域介绍 与 入门演示样例

    一. 工作区域具体解释 1. Scence视图 (场景设计面板) scence视图简单介绍 : 展示创建的游戏对象, 能够对全部的游戏对象进行 移动, 操作 和 放置; -- 演示样例 : 创建一个球 ...

  8. Unity 3D 游戏上线之后的流水总结

    原地址:http://tieba.baidu.com/p/2817057297?pn=1 首先.unity 灯光烘焙 :Unity 3D FBX模型导入.选项Model 不导入资源球.Rig 不导入骨 ...

  9. C#程序员整理的Unity 3D笔记(十五):Unity 3D UI控件至尊–NGUI

    目前,UGUI问世不过半年(其随着Unity 4.6发布问世),而市面上商用的产品,UI控件的至尊为NGUI:影响力和广度(可搜索公司招聘Unity 3D,常常能看到对NGUI关键词). NGUI虽然 ...

随机推荐

  1. ln 硬链接介绍

    硬链接:在linux文件系统中多个文件名指向同一个索引节点(Inode)是正常允许的.硬链接文件就相当于文件的另一个入口. 硬链接的作用:允许一个文件拥有多个有效路径(多个入口),这样用户就可以建立硬 ...

  2. Java 的布局管理器GridBagLayout的使用方法【图文说明】

    https://www.cnblogs.com/taoweiji/archive/2012/12/14/2818787.html GridBagLayout是java里面最重要的布局管理器之一,可以做 ...

  3. Windows 常识大全【all】

    解决电脑卡顿问题 电脑常见技巧大全 电脑运行命令CMD集锦 开启Windows 7系统的“上帝模式” Win7下设置护眼的电脑豆沙绿界面 零基础如何组装电脑?装机之家手把手教您电脑组装教程图解 [Ex ...

  4. Linux运维之——每日小技巧,使用awk命令截取每行的指定列数据

    获取/etc/passwd目录下的UID值小于10的数,并输出第一.三列 [root@:vg_adn_tidbCkhsTest:172.31.30.62 ~]#cat /etc/passwd | aw ...

  5. ansible 增加本机/etc/hosts 下hostsname 与IP

    --- - hosts: all vars: IP: "{{ ansible_eth0['ipv4']['address'] }}" tasks: - name: 将原有的host ...

  6. Pandas Learning

    Panda Introduction Pandas 是基于 NumPy 的一个很方便的库,不论是对数据的读取.处理都非常方便.常用于对csv,json,xml等格式数据的读取和处理. Pandas定义 ...

  7. word怎样从第三页开始设置页码

    一般的文件都是有封面,目录.然后才是正文.所以基本上第一页的封面,第二页是目录,第三页才是正文的开始.但是默认的页码会从第一页开始的,封面上海有页码这会很难看,今天和小编一起来看看怎样将页码从第三页开 ...

  8. Python os.md

    os 便携式访问操作系统的特定功能.os模块提供了对特定平台模块(如posix, nt, mac)的封装, 函数提供的api在很多平台上都可以相同使用, 所以使用os模块会变得很方便. 但不是所有函数 ...

  9. 【转】 [置顶] Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)

    在Android的应用层中,涉及到很多应用框架,例如:Service框架,Activity管理机制,Broadcast机制,对话框框架,标题栏框架,状态栏框架,通知机制,ActionBar框架等等. ...

  10. Linux设置口令复杂度和口令定期更换策略

    Linux 密码复杂度设置pam_pwquality.pam_passwdqc(centos7) 1.Linux对应的密码策略模块有:pam_passwdqc 和 pam_pwquality . 其中 ...