效果如下:

代码如下:

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. php 实现hash表

    hash表又称散列表,通过把关键字key经过hash函数映射到hash表中某个位置获取记录. 存放记录的数组又称为hash表,映射函数称为hash函数 下面是php中实现hash表的方法 <?p ...

  2. Spring-IOC 在非 web 环境下优雅关闭容器

    当我们设计一个程序时,依赖了Spring容器,然而并不需要spring的web环境时(Spring web环境已经提供了优雅关闭),即程序启动只需要启动Spring ApplicationContex ...

  3. [SHOI2008]小约翰的游戏

    题目 不会,抄论文 这是一个非常牛逼的东西,叫做\(anti\)博弈,就是进行最后一次操作的人输 我们考虑一下这道题 显然如果石子个数都是\(1\),那么有奇数堆石子先手必败,有偶数堆石子先手必胜 如 ...

  4. 《Java程序设计》第15周课堂实践总结

    <Java程序设计>第15周课堂实践总结 实践一 教材代码检查-p242 要求 在IDEA中或命令行中运行P242 StackTraceDemo2.java 代码运行结果和教材一致吗?为什 ...

  5. 三、用Delphi10.3 创建一条JSON数据的第三种方法,非常简洁的写法

    一.用Delphi10.3构造一个JSON数据的第三种方法,并格式化输出,代码如下: uses // System.JSON, System.JSON.Types, System.JSON.Write ...

  6. 嵌入式C语言自我修养 02:Linux 内核驱动中的指定初始化

    2.1 什么是指定初始化 在标准 C 中,当我们定义并初始化一个数组时,常用方法如下: ] = {,,,,,,,,}; 按照这种固定的顺序,我们可以依次给 a[0] 和 a[8] 赋值.因为没有对 a ...

  7. 时间序列深度学习:状态 LSTM 模型预测太阳黑子

    目录 时间序列深度学习:状态 LSTM 模型预测太阳黑子 教程概览 商业应用 长短期记忆(LSTM)模型 太阳黑子数据集 构建 LSTM 模型预测太阳黑子 1 若干相关包 2 数据 3 探索性数据分析 ...

  8. net辅助工具列表

    最近对.net的辅助工具比较感兴趣,网上也已经有.net的十个必备工具的帖子了,这里提供了一份全面的工具列表: Code generation NVelocity CodeSmith X-Code . ...

  9. 2017-2018-1 20155306 《信息安全系统设计基础》嵌入式C语言———提取设置时分秒

    2017-2018-1 20155306 <信息安全系统设计基础>嵌入式C语言---提取设置时分秒 要求:根据下图,完成对时分秒的设置和提取. 示例及思路分析: 思路分析:以分钟为例,根据 ...

  10. python基础学习1-装饰器在登陆模块应用

    LOGIN_USER ={"islogin":False} def outer(func): def inner(*args,**kwargs): if LOGIN_USER[&q ...