引言

游戏中很多地方用得到传送门,就跟哆啦A梦的任意门一样,从这边走进去,从那边走出来,用Unity实现一下它吧。
先来个效果图,请原谅没有给门添加漂亮的门框、或者特效,因为手头没有合适的素材,但这不影响任意门的功能,也不影响介绍它的原理。另外,机器上也没有按装gif截屏,所以不带动态,但图中的“能量波动花纹”是带动态的哦,请自行脑补。

这里是另一个,传送门嘛,至少得两个。

从一端走进去,就会从另一端走出来。效果还是可以的。
下面介绍一下原理和制作方法:
原理是这样的,用一个摄像机,观察传送门另一边的图像,然后渲染到本端传送门的平面上,这样,就能在本端门内看到远端的画面了。

一、创建shader

用ShaderGraph制作一个Shader如下图:

这个shader的原理比较简单,事实上最关键的是下面两个节点,上面的那一堆都是为了加能量波动的效果的。将摄像机画面也就是一张纹理连接到BaseColor节点即可,最关键的是UV节点,要使用屏幕空间,否则的话,摄像机画面会被压缩到门的尺寸,就变形了。还要注意,这个shader勾选一下双面渲染,否则跑到门的后面就看不到了。
然后用这个Shader制作一个材质,右键刚刚建好的ShaderGraph文件,选创建材质即可。

二、创建门

建一个Quad平面,作为传送门。将上面的材质赋给它。然后在门的下面创建一个相机、两个空物体,结构如下图:

由于要在门上显示另一个门外的场景,所以,本地门材质上显示的是远端门相机的画面。另外需要注意的是,上面shader中所说过了,一定要使用屏幕空间作为纹理UV,这还有一个问题,那就是纹理尺寸,要跟屏幕尺寸相符,至少比例要一致,否则门上的画面是要变形的。这个其实很容易解决,纹理使用动态创建的就好,根据屏幕尺寸动态建一张纹理即可:

    // 获取门底下的相机组件Camera cam = m_ProtalCamera.GetComponent<Camera>();// 根据屏幕尺寸建一张纹理ProtalCameraTexture = new RenderTexture(Screen.width, Screen.height, 32){name = "ProtalCameraTargetTexture"};// 将门下相机的渲染目标设置为该纹理cam.targetTexture = ProtalCameraTexture;// 设置相机不要观察门本身cam.cullingMask &= ~(1 << gameObject.layer);

然后就是将纹理设置到门的材质了,也是用代码:

if( TargetDoor != null )
{// 获取到门的渲染组件MeshRenderer renderer = GetComponent<MeshRenderer>();foreach (var m in renderer.materials){// 将本地门的材质纹理,设置为目标门摄像机的渲染纹理m.SetTexture("_MainTex", TargetDoor.ProtalCameraTexture);}
}

那么,为啥还要有两个空物体呢?介绍一下原理:

如上图所示,由于传送门的两端朝向是任意的,所以搞清楚摄像机的相对位置尤为重要,否则在A门看到的B门处的图像角度就会不正确。有了上面那个空物体,这一切就变得简单多了,甚至不需要计算,也不需要什么数学知识。

    // 将主相机(角色)的世界坐标和朝向赋予A门表示主相机的空物体m_MainCameraPos.position = m_Camera.position; m_MainCameraPos.rotation = m_Camera.rotation;// 将A门下表示主相机的空物体相对于A门的相对位置,赋予B门的相机,使得B门相机相对于B的相对位置与主相机相对于A门的相对位置相同TargetDoor.m_ProtalCamera.localPosition = m_MainCameraPos.localPosition;TargetDoor.m_ProtalCamera.localRotation = m_MainCameraPos.localRotation;

请看上述代码中的注释,文字有点绕,但道理比较容易理解。

三、实现传送

上面步骤中共建了两个空物体,但目前只说了其中一个的用途,另一个是干嘛的呢?试想一下,当角色被传送时,从A门离开时相对于A的位置,应该与他到达B门时相对于B门的相对位置是相同的。这样才不会显得突兀,画面跳转也会比较正常。那么剩下的这个空物体,就是解决这个的,原理跟上面相机相对位置的原理是一模一样的:

// 当角色进入门的碰撞范围,触发碰撞器
private void OnTriggerEnter(Collider other)
{// 将角色的世界位置和朝向赋予门记录目标位置的空物体m_TargetPos.position = other.transform.position;m_TargetPos.rotation = other.transform.rotation;// 使目标门用于记录角色位置的空物体相对于目标门的相对位置与源门的相同TargetDoor.m_TargetPos.localPosition = m_TargetPos.localPosition;TargetDoor.m_TargetPos.localRotation = m_TargetPos.localRotation;// 将角色传送过去other.transform.position = TargetDoor.m_TargetPos.position;other.transform.rotation = TargetDoor.m_TargetPos.rotation;
}

四、完善一下

是不是很简单,完事了么?NO,还需要处理几个小问题。试想一下,如果角色进入A门的触发器,那么A门会把它传送到B门去,但是,角色一旦到达B门,就会立即触发B门的触发器,然后B门又会把他传送到A,然后,你的玩家就会被两个门传来传去。。。怎么解决这个问题呢?还有,测试中发现,如果你的角色控制器用的是unity自带的CharacterController组件的话,那么就会有点小问题,一并解决一下:

private void OnTriggerEnter(Collider other)
{// 加一个接受传送的变量,只有在接受传送时,角色才能被传过去。// 另外,顺便判断一下目标物体是否允许被传送(通过层来判断)if (bAcceptTrans && (((1 << other.gameObject.layer) & TransformTargetLayer) != 0)){// 暂时关闭目标门传送触发TargetDoor.bAcceptTrans = false;// 计算角色相对本地门的相对位置,保证传送到目标门后,与目标门的相对位置一致。m_TargetPos.position = other.transform.position;m_TargetPos.rotation = other.transform.rotation;TargetDoor.m_TargetPos.localPosition = m_TargetPos.localPosition;TargetDoor.m_TargetPos.localRotation = m_TargetPos.localRotation;// 如果是CharacterController组件控制的角色,先禁用一下,传送完了再打开// 如果你的代码不是用这个组件,可以删掉CharacterController cc = other.GetComponent<CharacterController>();if (cc != null)cc.enabled = false;other.transform.position = TargetDoor.m_TargetPos.position;other.transform.rotation = TargetDoor.m_TargetPos.rotation;if (cc != null)cc.enabled = true;}
}

五、更多的门

好了,把传送门做成预制体,尽情在你的游戏中摆放吧。。A传到B,B再传回A,或者A传到B,B传到C,C又传到D…只要你愿意,你可以一直这么摆下去。摆完之后,只要把目标门拖到Inspector面板即可。如下图:

Transform Target Layer :允许被传送的物体层,比如玩家层、子弹层…
Target Door:这个门的目标门(要把待传送物体传送到哪个门,就把哪个门拖到这里即可)
使用起来很简单吧。。

六、还能完善吗

本文到这里就结束了,它已经可以实现基本的传送门的功能,但仍有很多优化和完善的余地,比如,shader可以写的更炫酷一点,可以添加启用或者禁用传送门的效果和机关,传送的瞬间添加一些特效…如果要继续完善,那么就尽情的发挥想象力吧。

七、相关下载

猛击此处下载可执行演示
猛击此处下载工程源码

Unity第一人称可视化传送门制作相关推荐

  1. Unity第一人称手游-左侧控制移动,右侧控制视角和方向(第一人称,类似吃鸡游戏)

    Unity第一人称手游-左侧控制移动,右侧控制视角和方向(第一人称,类似吃鸡游戏) 文章最后会附上 项目下载地址 备注:资源是URP的,普通平台修改资源材质即可 效果图 实现原理及步骤 左侧遥杆移动- ...

  2. unity第一人称射击游戏,枪击游戏,功能完整可以当大作业或者毕设

    unity第一人称射击游戏,枪击游戏(含源码和exe导出文件,下载链接在文末) unity第一人称枪击游戏,分为海岛地图和沙漠地图,可以开镜射击,敌人可以移动,菜单页面有开始游戏,游戏说明,退出三个按 ...

  3. Unity第一人称控制器使用

    简介:本节主要介绍使用官方自带的FPS包来实现第一人称控制,鉴于官方提供的案例已经十分完备,无需重复造轮子,故本文章不含任何代码实现~ 资源商店获取包 众所周知,能在资源商店找到的模型或者脚本就不要自 ...

  4. Unity第一人称控制器

    不得不说,unity最新的轻量级角色控制器搭配新输入系统确实好用.不过我不会(doge).想学习的小伙伴可以直接在Hub里面下载unity的第一人称控制器模板,个人觉得非常适合学习. 简单的第一人称控 ...

  5. Unity 第一人称、第三人称、漫游视角 控制器.

    前言 这是以前写的人物控制器(包含第一人称.第三人称.漫游视角),这里做个记录,方便后续参考使用. 实现 模型使用官方的,操作使用鼠标右键控制视角,键盘WASD.Shift控制人物移动. 切换到漫游视 ...

  6. UE4创建第一人称射击游戏学习教程

    Unreal Engine 4: Create Your Own First-Person Shooter MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言 ...

  7. fps射击HTML网页游戏,关于Unity中FPS第一人称射击类游戏制作(专题十)

    当前Unity最新版本5.6.3f1,我使用的是5.5.1f1 FPS第一人称射击类游戏实例 场景搭建 1.创建Unity项目工程和文件目录,保存场景 2.导入人物模型和子弹碎片的资源包charact ...

  8. 关于Unity中FPS第一人称射击类游戏制作(专题十)

    当前Unity最新版本5.6.3f1,我使用的是5.5.1f1 场景搭建 1: 导入人物模型, 手持一把枪; 2: 导入碎片模型; 3: 创建一个平面; 4: 创建一个障碍物; 5: 导入人物模型; ...

  9. unity中利用cinemachine插件制作玩家视觉效果(第三人称转第一人称视角)

    在很多游戏第三人称中很多时候在拾取道具或者一些时候为了增加游戏的体验感 会将镜头转变为第一人称(特写) 在这篇博客给大家介绍一下用cinemachine插件和一点代码实现镜头的转变 实现过程 首先我给 ...

  10. 【游戏开发实战】Unity手游第一人称视角,双摇杆控制,FPS射击游戏Demo(教程 | 含Demo工程源码)

    文章目录 一.前言 二.实现方案 1.无主之地,第一人称视角 2.我之前做的摇杆控制 3.第一人称视角 + 摇杆控制 三.开始实战 1.资源获取:Unity AssetStore 2.Low Poly ...

最新文章

  1. 几张图帮你弄清楚什么是 RPC
  2. AtCoder AGC035F Two Histograms (组合计数、容斥原理)
  3. jdbc查看网络状态
  4. 迈普路由器访问控制列表配置命令_如何选购企业路由器?选购企业路由器需注意什么...
  5. Spring Cloud Alibaba迁移指南(三):极简的 Config 1
  6. android怎么让图片显示在button上面_网上的图片不知道怎么批量下载?python教你怎么把网站上面的图片都爬下来...
  7. pyqt5实现按钮添加背景图片以及背景图片的切换
  8. 工作开不开心,都在钱上
  9. Dais-CMX系列现代计算机组成原理,dais版本计算机组成原理实验指导.doc
  10. 利用ST-LINK配合ST-LINK Utility 将bin文件下载到STM32的FLASH中
  11. codeblocks下载安装教程(完整详细)
  12. 分布式之CAP原则详解
  13. LaTeX代码: 表格 ← 利用 tabular
  14. Cocos Creator
  15. 看起来简单,实际上复杂
  16. 个人案例 装修公司官网
  17. vs2017python配置opencv_[opencv +VS2017] opencv、vs2017安装配置,环境搭建
  18. ChromeOptions
  19. LSTM 两个激励函数区别sigmoid 和tanh
  20. MySql 查重、去重的实现

热门文章

  1. 解决 psftp local: unable to open 的问题
  2. JSONArray.fromObject(str)
  3. 《学习笔记13》——web前端助手:插件fehelper的使用
  4. 微型计算机原理与应用彭楚武,微型计算机原理及其应用
  5. npm下载和使用(超详细)
  6. C#中pdf转word
  7. LOUVAIN——社交网络挖掘之大规模网络的社区发现算法
  8. matlab损耗函数曲线,MATLAB 损失函数画图
  9. 基于FPGA的三人表决器设计
  10. html rgb 颜色转换,将RGBA颜色转换为HTML颜色代码