效果如下:

代码如下:

public class TPSCamera : MonoBehaviour
{
/// <summary>
/// 目标对象
/// </summary>
[SerializeField]
Transform target = null; /// <summary>
/// 旋转参数
/// </summary>
[SerializeField]
Vector2 rotate; /// <summary>
/// 旋转速度
/// </summary>
[SerializeField]
float rotateSpeed = ; /// <summary>
/// 视口大小
/// </summary>
[SerializeField]
float viewSize = ; /// <summary>
/// 默认角度
/// 在目标对象的哪个方向
/// </summary>
[SerializeField]
float defaultAngle = -; /// <summary>
/// 离目标对象的距离
/// </summary>
[SerializeField]
float radius = ; /// <summary>
/// 离目标对象的高度
/// </summary>
[SerializeField]
float height = 1.5f; public bool Aim; public bool visiable = false; public CursorLockMode lockMode; Camera cam; /// <summary>
/// 绕任意轴旋转的参考点
/// 暂时用这个办法替代
/// </summary>
Transform tr; static TPSCamera _inst; public static TPSCamera inst
{
get {
return _inst;
}
} void Awake ()
{
_inst = this;
} void Start ()
{
cam = this.GetComponent<Camera> ();
tr = new GameObject ().transform;
} void FixedUpdate ()
{
rotate.x += Input.GetAxis ("Mouse X") * rotateSpeed;
rotate.y += Input.GetAxis ("Mouse Y") * rotateSpeed;
viewSize -= Input.mouseScrollDelta.y * ; //一些约束,不用管
if (viewSize < )
{
viewSize = ;
} else if (viewSize > )
{
viewSize = ;
} if (rotate.y < -)
{
rotate.y = -;
} else if (rotate.y > )
{
rotate.y = ;
} cam.fieldOfView = viewSize;
Cursor.visible = visiable;
Cursor.lockState = lockMode;
} void LateUpdate ()
{
Transform self = this.transform;
Vector3 targetPos = target.position;
targetPos.y += height; //旋转y轴,左右滑动
Vector2 v1 = IMath.CalcAbsolutePoint (rotate.x, radius);
self.position = targetPos + new Vector3 (v1.x, 0, v1.y); //相机的观察点
Vector2 v2 = IMath.CalcAbsolutePoint (rotate.x + defaultAngle, radius);
Vector3 viewPoint = new Vector3 (v2.x, , v2.y) + targetPos; //计算2点之间的距离
float dist = Vector3.Distance (self.position, viewPoint); //取中点作为旋转轴
Vector3 center = Vector3.MoveTowards (self.position, viewPoint, dist / ); //这里我不知道怎么计算这个任意轴,暂时先用这个方法替代
tr.position = center;
tr.LookAt (targetPos);
tr.eulerAngles += new Vector3 (, , rotate.y); //旋转x轴,上下滑动
Vector3 temp = tr.right * dist / ;
self.position = tr.position - temp;
self.LookAt (tr.position + temp); } }
public static Vector2 CalcAbsolutePoint (float angle, float dist)
{
angle += ;
dist = -dist;
float x = dist * Mathf.Cos (-angle * Mathf.PI / );
float y = dist * Mathf.Sin (-angle * Mathf.PI / );
return new Vector2 (x, y);
}

Unity 实现一个简单的 TPS 相机的更多相关文章

  1. Unity 3D 一个简单的角色控制脚本

    之所以写这个脚本,是因为我想起了我还是新手的时候,那时为了一个角色控制脚本百度了半天还是一无所获,因为看不懂啊,都写的太高级了 希望这个脚本能够帮助那些 像曾经的我一样迷失于代码中的新手们能够清晰的理 ...

  2. Hololens开发笔记之使用Unity开发一个简单的应用

    一.Hololens概述 Hololens有以下特性 1.空间映射借助微软特殊定制的全息处理单元(HPU),HoloLens 实现了对周边环境的快速扫描和空间匹配.这保证了 HoloLens能够准确地 ...

  3. 【Unity】UGUI系列教程——拼接一个简单界面

    0.简介: 在目前的游戏市场上,手游依然是市场上的主力军,而只有快速上线,玩法系统完善的游戏才能在国内市场中占据份额.而在手游开发过程中,搭建UI系统是非常基本且重要的技能,极端的说如果对Unity的 ...

  4. Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏

    Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏 即使是如今,非常多初学游戏开发的同学.在谈到Unity的时候.依旧会觉得Unity仅仅能用于制作3D游戏的. 实际上.Unity在2013 ...

  5. IOS开发之小实例--使用UIImagePickerController创建一个简单的相机应用程序

    前言:本篇博文是本人阅读国外的IOS Programming Tutorial的一篇入门文章的学习过程总结,难度不大,因为是入门.主要是入门UIImagePickerController这个控制器,那 ...

  6. 使用Unity3D的设计思想实现一个简单的C#赛车游戏场景

    最近看了看一个C#游戏开发的公开课,在该公开课中使用面向对象思想与Unity3D游戏开发思想结合的方式,对一个简单的赛车游戏场景进行了实现.原本在C#中很方便地就可以完成的一个小场景,使用Unity3 ...

  7. 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

    这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...

  8. Unity NGUI 创建简单的按钮

    Unity版本:4.5.1 NGUI版本:3.6.5 注意NGUI版本,网上的大部分教程都是2.x版本的,在步骤上面略有不同,此文适合初学者. 示例: 通过NGUI创建一个背景和按钮. 1.首先创建一 ...

  9. 实现一个简单的Unity3D三皮卡——3D Picking (1)

    3D Picking 其原理是从摄像机位置到空间发射的射线.基于光线碰到物体回暖. 这里我们使用了触摸屏拿起触摸,鼠标选择相同的原理,仅仅是可选API不同. 从unity3D官网Manual里找到下面 ...

随机推荐

  1. 【笔记】JS脚本为什么要放在body最后面以及async和defer的异同点

    1.没有defer或async 浏览器遇到脚本的时候会暂停渲染并立即加载执行脚本(外部脚本),"立即"指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的 ...

  2. python pandas dataframe 操作记录

    从数据看select出数据后如何转换为dataframe df = DataFrame(cur.fetchall()) 如何更改列名,选取列,进行groupby操作 df.columns = ['me ...

  3. python第二十一课——str中的常用函数(重要)

    演示str中常用的一些函数: 1.join():将容器对象以某种特定的格式(字符串)进行拼接组合,最后以字符串的形式返回 lt=['i','love','you','very','much'] str ...

  4. Java NIO(一)I/O模型概述

    基本概念讲述 什么是同步? 同步就是:如果有多个任务或者事件要发生,这些任务或者事件必须逐个地进行,一个事件或者任务的执行会导致整个流程的暂时等待,这些事件没有办法并发地执行. 什么是异步? 异步就是 ...

  5. Grid Selenium

    python selenium-9 grid模式 grid是进行分布式测试的工具,由一个hub主节点和若干个node代理节点组成 1.下载Selenium Standalone Server 下载地址 ...

  6. 视频直播时的QoS策略

    一.如何判断当前的网络状况 可以以发送一帧视频数据的时间为依据,判断当前网络拥塞情况.    网络中出现丢包和抖动,导致接收端接收数据超时,会激发发送端数据重传,重传机制本身挤占网络带宽,导致send ...

  7. 图片在线处理 webp!

    之前处理图片的方式是,小图标通过gulp配置的spritesmith雪碧图方式,.png会先用ps工具转成.jpg,然后jpg太大则用在线压缩工具来进行压缩(另外gulp系列的gulp-imagemi ...

  8. Cannot obtain block length for LocatedBlock故障分析和解决

    来源:CSDN 作者:Syn良子 原文:https://blog.csdn.net/cssdongl/article/details/77750495  一.问题背景 问题产生的原因可能是由于前几日H ...

  9. uboot-2012.04.01移植编译前准备

    一:准备移植1.从下面的官网下载uboot-2012.04.012.建立sourceinsight工程 a.解压并在E:\colin weidongshan\transplant_u-boot-201 ...

  10. GoLang 命令

    目录 查看可用命令 build 和 run 命令 go build编译时的附加参数 clent命令 fmt 和 doc 命令 get 命令 远程包的路径格式 go get+远程包 go get使用时的 ...