文章目录

  • 一、前言
  • 二、最终效果
  • 三、Blender建模
    • 1、Blender下载安装
    • 2、传送门建模
    • 3、房子建模
    • 4、公司大楼建模
    • 5、文字模型
  • 四、Blender导出FBX
  • 五、FBX导入Unity中
  • 六、制作材质
    • 1、传送门
      • 1.1、ShaderGraph准备
      • 1.2、创建ShaderGraph
      • 1.3、编辑ShaderGraph
      • 1.4、材质球使用ShaderGraph
      • 1.5、模型引用材质球
    • 2、房子材质球
    • 3、公司大楼材质球
  • 七、地面
    • 1、广州地铁图
    • 2、地面(Plane)
  • 八、主角
    • 1、主角资源
    • 2、双摇杆制作
    • 3、主角移动控制
      • 3.1、动画控制
      • 3.2、移动控制
      • 3.3、主角脚本代码
      • 3.4、主角移动测试
    • 4、摄像机跟随
    • 5、摄像头角度控制
  • 九、导航烘焙
  • 十、传送门触发器
  • 十一、特效
  • 十二、最终效果
  • 十三、工程源码
  • 十四、完毕

一、前言

嗨,大家好,我是新发。
现在每天上班的通勤时间是一个多小时,加上下班的通勤时间,每天在路上就是两个半小时,在广州早高峰坐地铁简直要命,这里我不得不吐槽一下广州21号线,人流量超多,发车频率还低,导致每趟都堆积特别多人,每次都要等至少两三趟才能挤上,而且都好暴力,太疯狂了,这样真的容易出事,每次出地铁心里都在重复一句话:下次不搭21号线了!
还好有热心同事经常开车搭我上下班,老麻烦别人也很不好意思,不过,搭了几次车又感觉脸皮厚了-_-

要是有一个任意门可以连接家门口和公司门口就好了,现实中没有,那就在虚拟世界里做一个吧~

二、最终效果

我做的Demo最终效果如下,
家门口:

从家门口穿过传送门:

从公司经过传送门回家:

下面,我就来讲讲我的制作过程吧~

三、Blender建模

看过我前面两篇文章的同学应该知道,我最近自学了Blender建模,感兴趣的同学可以看下我之前两篇文章,
【游戏开发创新】当我学了Blender 建模,自制3D电脑桌面,回收站爆发了,把我做的模型都吐了出来(Blender | Unity | FBX),
【游戏开发创新】自学Blender建模,自制孔明灯,在Unity中点亮整个星空,愿新年,胜旧年(Unity | 建模 | 粒子系统 | 预设)

1、Blender下载安装

Blender官网:https://www.blender.org/
Blender中国社区:https://www.blendercn.org/
Blender中文手册:https://docs.blender.org/manual/zh-hans/2.79/about/introduction.html

我使用的Blender版本是2.93.4

注:关于Blender的教程网上蛮多的,这里我就不过多讲了,掌握基本操作和快捷键,很快就可以上手建模啦~

2、传送门建模

传送门最终模型如下:

3、房子建模

房子最终模型如下:

4、公司大楼建模

公司大楼最终模型如下:

5、文字模型

再做一些文字模型,

四、Blender导出FBX

Blender中点击菜单File / Export / FBX,将模型导出成FBX格式,

如下:

五、FBX导入Unity中

FBX文件导入到Unity工程中,

把模型放入场景中,现在都是默认的材质,所以都是灰白色的,不着急,下面我们就来做材质~

六、制作材质

1、传送门

材质球使用的shader我打算使用ShaderGraph来制作,我之前写过一篇ShaderGraph的文章:《ShaderGraph使用教程与各种特效案例:Unity2020》,推荐先看下这篇文章。

1.1、ShaderGraph准备

安装Universal RP插件,

Project视图中右键鼠标,点击菜单Create / Rendering / Universal Render Pipeline / Pipeline Asset (Forward Renderer)

创建UniversalRenderPipelineAsset,如下

点击菜单Edit / Project Settings...,打开Project Settings窗口,选择Graphics分页,把UniversalRenderPipelineAsset拖到Scriptable Render Pipeline Settings中,

1.2、创建ShaderGraph

Project视图中右键鼠标,点击菜单Create / Shader / Universal Render Pipeline / Lit Shader Graph,创建一个PBRShaderGraph

重命名为PortalCenter,作为传送门中心的shader

1.3、编辑ShaderGraph

双击PortalCenter打开编辑器,编辑节点如下,核心就是对泰森多边形(Voronio)进行UV旋涡旋转(Twirl)。

1.4、材质球使用ShaderGraph

创建一个材质球Material, 重命名为PortalCenter

设置材质球的shader为刚刚的ShaderGraph文件,

1.5、模型引用材质球

将材质球赋值给传送门模型,

效果如下,

2、房子材质球

同理,制作房子的材质,

效果如下,

3、公司大楼材质球

制作房子的材质,

效果如下,

七、地面

1、广州地铁图

找一张广州最新的地铁地图,我找到的是下面这张,

2、地面(Plane)

在场景中创建一个Plane平面,制作材质并引用这张图片,


效果如下:

八、主角

1、主角资源

主角我在AssetStore上找到了一个心仪的模型,推荐给大家,
AssetStore地址:https://assetstore.unity.com/packages/3d/characters/humanoids/sci-fi/stylized-astronaut-114298

将模型下载导入Unity中,

2、双摇杆制作

主角的移动和摄像头的角度旋转我想通过摇杆来控制,我们做一个双摇杆功能。
Canvas节点上右键点击菜单UI / Panel,创建一个Panel

Image组件禁用掉,因为我们不需要Panel显示出来,

Panel下创建一个Image,重命名为leftJointedArm,作为左摇杆的父节点,

设置它的锚点为bottom - left,即屏幕左下角,调整坐标和宽高,

像这样子,

把它的Coloralpha调为0,因为我们只需要利用它的区域来检测触碰,我们不需要肉眼看见它,

接着在它的子节点下创建两个Image,分别命名为bgcenter

它们的Source Image都设置为摇杆的图片资源,

分别调整下bgcenter的大小和颜色透明度,效果如下:

同理再做一个右摇杆,

效果如下:

接下来需要给摇杆加上逻辑,UnityUGUI提供了ScrollRect组件,非常适合用来制作摇杆,我们继承ScrollRect然后实现OnDragOnEndDrag方法,可以很方便地获取到摇杆的遥控数据,另外,为了检测区域点击,我们再实现IPointerDownHandler接口。

创建摇杆脚本JointedArm.cs,代码如下:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System;/// <summary>
/// 摇杆
/// </summary>
public class JointedArm : ScrollRect, IPointerDownHandler
{public Action<Vector2> onDragCb;public Action onStopCb;protected float radius = 0f;private Transform trans;private RectTransform bgTrans;private Camera uiCam;private Vector3 originalPos;protected override void Awake(){base.Awake();trans = transform;bgTrans = trans.Find("bg") as RectTransform;uiCam = GameObject.Find("UICamera").GetComponent<Camera>();originalPos = trans.localPosition;}void Update(){if (Input.GetMouseButtonUp(0)){//松手时,摇杆复位trans.localPosition = originalPos;this.content.localPosition = Vector3.zero;}}protected override void Start(){base.Start();//计算摇杆块的半径radius = bgTrans.sizeDelta.x * 0.5f;}public override void OnDrag(PointerEventData eventData){base.OnDrag(eventData);var contentPostion = this.content.anchoredPosition;if (contentPostion.magnitude > radius){contentPostion = contentPostion.normalized * radius;SetContentAnchoredPosition(contentPostion);}// Debug.Log("摇杆滑动,方向:" + contentPostion);if(null != onDragCb)onDragCb(contentPostion);}public override void OnEndDrag(PointerEventData eventData){base.OnEndDrag(eventData);// Debug.Log("摇杆拖动结束");if (null != onStopCb)onStopCb();}public void OnPointerDown(PointerEventData eventData){//点击到摇杆的区域,摇杆移动到点击的位置trans.position = uiCam.ScreenToWorldPoint(eventData.position);trans.localPosition = new Vector3(trans.localPosition.x, trans.localPosition.y, 0);}
}

JointedArm.cs分别挂到leftJointedArmrightJointedArm上,赋值对应的center

运行Unity,摇杆测试效果如下:

接下来我们要实现左摇杆控制主角移动并播放跑的动画,右摇杆控制摄像机角度旋转。

3、主角移动控制

3.1、动画控制

注:关于Animator组件的详细使用可以参见我之前写的这篇文章:《Unity动画状态机Animator使用》

打开角色的动画控制器文件CharacterController

可以看到,两个动作,一个idle(站立)一个Run(跑),

Parameters(参数)里面有一个AnimationPar参数,这个参数就是用来控制站立与跑着两个动画的过渡条件的,

Idle过渡到Run的条件是AnimationPar等于1

Run过渡到Idle的条件是AnimationPar等于0

这样,我们就可以在代码中通过这个参数来控制动画的过渡了,例:

// public Animator anim; // 站立 -> 跑
anim.SetInteger("AnimationPar", 1);
// 跑 -> 站立
anim.SetInteger("AnimationPar", 0);
3.2、移动控制

主角的移动控制包括坐标和角度的变化,当摇杆向左滑,主角向左移动,同时主角的朝向也跟着转向左边。
移动我们可以设置transfromposition属性来实现,转向我们可以设置transfromforward属性来实现,例:

// Vector3 moveDirection; 摇杆向量
// float speed; 移动速度
// float turnSpeed; 转向速度transform.position += moveDirection * speed * Time.deltaTime;
transform.forward = Vector3.Lerp(transform.forward, moveDirection, turnSpeed * Time.deltaTime);
3.3、主角脚本代码

综上,我们封装一个主角脚本Player.cs,代码如下:

// Player.cs
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.AI;/// <summary>
/// 主角脚本
/// </summary>
public class Player : MonoBehaviour
{// 移动速度public float speed = 1f;// 转向速度public float turnSpeed = 20f;public Animator anim;// 跟节点public Transform rootTrans;// 模型节点public Transform modelTrans;// 导航Agentpublic NavMeshAgent navAgent;// 是否在移动private bool moving = false;// 移动向量private Vector3 moveDirection = Vector3.zero;// 是否可移动private bool canMove = true;private void Awake() {companyPosParticle.Stop();homePosParticle.Stop();}void Update(){if (canMove && moving){anim.SetInteger("AnimationPar", 1);rootTrans.position += moveDirection * speed * Time.deltaTime;modelTrans.forward = Vector3.Lerp(modelTrans.forward, moveDirection, turnSpeed * Time.deltaTime);}else{anim.SetInteger("AnimationPar", 0);}}public void Move(Vector3 direction){moveDirection = direction;moving = true;}public void Stand(){moving = false;}

Player.cs脚本挂到主角物体上,在Inspector面板赋值脚本的成员变量,

我们再创建一个GameMgr.cs脚本来调度,

// GameMgr.cspublic Player player;
public JointedArm leftJointedArm;
private Transform playerTrans;
private Transform camTrans;// ...// 左摇杆 -------------------------------------------
leftJointedArm.onDragCb = (direction) =>
{var realDirect = camTrans.localToWorldMatrix * new Vector3(direction.x, 0, direction.y);realDirect.y = 0;realDirect = realDirect.normalized;player.Move(realDirect);
};
leftJointedArm.onStopCb = () => { player.Stand(); };

创建一个空物体重命名为GameMgr,把GameMgr.cs挂到这个物体上,并在Inspector面板中赋值脚本的成员变量。

3.4、主角移动测试

运行测试效果如下:

4、摄像机跟随

我们创建一个CameraControler.cs脚本,实现摄像机跟随主角的逻辑,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 摄像机控制器
/// </summary>
public class CameraControler : MonoBehaviour
{// 限制摄像机角度范围private const float Y_ANGLE_MIN = 10f;private const float Y_ANGLE_MAX = 50.0f;// 摄像机看向的物体public Transform lookAt;// 摄像机Transformpublic Transform camTransform;// 摄像机距离目标物体的距离public float distance = 1.2f;// 原始距离private float originalDistance;// 旋转速度public float rotateSpeed = 0.01f;public float currentX = 0.0f;public float currentY = 20.0f;private void Start(){camTransform = transform;originalDistance = distance;}private void Update(){if (rotating){currentX += rotateDelta.x;currentY += rotateDelta.y;currentY = Mathf.Clamp(currentY, Y_ANGLE_MIN, Y_ANGLE_MAX);}}private void LateUpdate(){Vector3 dir = new Vector3(0, 0, -distance);Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);camTransform.position = lookAt.position + rotation * dir;camTransform.LookAt(lookAt.position);}
}

CameraControler.cs脚本挂到主摄像机上,在Inspector面板赋值脚本的成员变量,运行Unity,可以看到有跟随效果了,

5、摄像头角度控制

我们在上面的CameraControler.cs脚本中添加两个方法,如下:

// CameraControler.csprivate bool rotating;
private Vector2 rotateDelta;public void RotateCam(Vector2 delta)
{rotateDelta = delta * rotateSpeed;rotating = true;
}public void StopRotate()
{rotating = false;
}

然后在GameMgr.cs中添加右摇杆的调度,

// GameMgr.cs// 右摇杆 ------------------------------------------
rightJointedArm.onDragCb = (direction) =>
{camCtrler.RotateCam(direction);
};
rightJointedArm.onStopCb = () => { camCtrler.StopRotate(); };

运行Unity,可以控制摄像头角度旋转了,

九、导航烘焙

如果我们想要实现点击地图某个位置,让主角走到目标点,可以使用Unity的寻路导航功能,另外,这个功能也可以限制主角的移动区域,为了防止主角走到地图外面,我们使用Navigation对场景进行导航烘焙。
首先选中地面,把地面设置为Static

然后点击菜单Window / AI / Navigation

点击Bake分页,点击Bake按钮,

看到地面蒙上了一层蓝色的网,就说明烘焙成功了,

你可以在场景文件所在目录中看到它生成了一个NavMesh文件,

另外,我们需要给主角添加NavMeshAgent组件,并根据主角模型大小设置RadiusHeight

如下:

运行Unity,测试一下移动到地面边界的效果,

十、传送门触发器

传送门传送,我使用了触发器,检测主角是否通过了传送门,然后出发传送逻辑。
给传送门的前后添加两个碰撞体,并勾选Is Trigger

如下:

分别在两个冲送门位置添加一个标记传送目标位置的空物体,

给主角脚本Player.cs添加传送的逻辑,

// Player.cspublic Transform homePos;
public Transform companyPos;
private string lastTrigger;private void OnTriggerEnter(Collider other)
{if("trigger1" == other.name || "trigger3" == other.name)        {lastTrigger = other.name;}else{if("trigger1" == lastTrigger && "trigger2" == other.name){// 执行传送,从公司到家rootTrans.position = homePos.position;}else if("trigger3" == lastTrigger && "trigger4" == other.name){// 执行传送,从家到公司rootTrans.position = companyPos.position;}}
}

这样,当主角传过传送门的时候就会按顺序触发触发器,最终指向传送逻辑。

十一、特效

传送时加多一个特效吧,使用PhotoShop画一个菱形,如下:

再画个菱形边框,

使用粒子系统制作特效,效果如下:

主要利用的是粒子系统的color over LifttimeSize over Lifetime来达到上面的效果,

关于粒子系统的相关教程,可以参见我之前写的这几篇文章:
【游戏开发实战】权游红袍女在火中看到了什么,我看到了…(Unity | 粒子系统 | 火焰特效 | ParticleSystem | 手把手制作)
【游戏开发实战】Unity使用ShaderGraph配合粒子系统,制作子弹拖尾特效(Fate/stay night金闪闪的大招效果)
【学Unity的猫】——第十五章:Unity粒子系统ParticleSystem,下雪啦下雪啦
【游戏开发实战】手把手教你使用Unity制作一个飞机喷射火焰尾气的粒子效果

十二、最终效果

家门口:

从家门口穿过传送门:

从公司经过传送门回家:

十三、工程源码

本工程我已上传到CODE CHINA,感兴趣的同学可自行下载学习。
地址:https://codechina.csdn.net/linxinfa/UnityPortalDemo
注:我使用的Unity版本为Unity 2021.1.9f1c1 (64-bit)

十四、完毕

好了,就到这里吧,最后希望广州地铁21号线高峰期可以提高发车频率,不然真的很痛苦。
我是林新发:https://blog.csdn.net/linxinfa
原创不易,若转载请注明出处,感谢大家~
喜欢我的可以点赞、关注、收藏,如果有什么技术上的疑问,欢迎留言或私信,我们下期见~

【游戏开发创新】上班通勤时间太长,做一个任意门,告别地铁与塞车(Unity | 建模 | ShaderGraph | 摇杆 | 角色控制)相关推荐

  1. Systemctl stop XXX 时间太长

    一.背景 假如我们自己开发了一个系统,例如web,想要通过systemd来控制.但使用过程中,出现了问题,systemctl stop XXX 的时间太长了. 二.问题原因 先说结论:我们的系统停止的 ...

  2. spark SQL读取ORC文件从Driver启动到开始执行Task(或stage)间隔时间太长(计算Partition时间太长)且产出orc单个文件中stripe个数太多问题解决方案...

    1.背景: 控制上游文件个数每天7000个,每个文件大小小于256M,50亿条+,orc格式.查看每个文件的stripe个数,500个左右,查询命令:hdfs fsck viewfs://hadoop ...

  3. Android 系统(161)---N/O版本上图库打开一张图片,图片从模糊到清晰的时间太长

    N/O版本上图库打开一张图片,图片从模糊到清晰的时间太长 与M版本比较,N版本上进图库打开一张图片,图片从模糊到清晰的时间太长 N上Google默认没有多线程encode而只有单线程encode,导致 ...

  4. win10 更新计算机时间,win10更新时间太长怎么回事_windows10更新时间太久解决教程...

    在使用win10系统的时候,经常会需要电脑进行更新,而我们会发现每次更新都会耗时1-2个小时时间.让人等的不耐烦,遇到win10更新时间太长怎么回事呢?接下来给大家分享一下windows10更新时间太 ...

  5. 苹果电脑开机长android,苹果笔记本开机白屏时间太长

    朋友,我的现在用"优化大师"优化了,开机才用:"13秒"! 1.电脑开机时间太长(建议你关机重启),或一次打开的网页过多,造成电脑"超载运行" ...

  6. java压缩mp4大小_压缩的mp4视频播放时间太长(exoplayer)

    视频(mp4)从Android摄像头录制并发送到后端,这里我使用ffmpeg包装器压缩视频[44mb视频到5.76mb] . 压缩效果很好,但是当我在android(exo播放器)发送视频播放时,开始 ...

  7. 【幻灯片制作软件】Focusky教程 | 帧的播放时间太长,该如何调整?

    (Focusky动画演示大师简称为"FS软件")设置适当的帧的播放时间能有效地展示内容,达到更好的演示效果.但如果帧的播放时间太长,所有演示动作完成后,还需等待一段时间后才能播放下 ...

  8. 计算机启动时间过长,开机时间太长怎么办【图解】

    现在人们生活娱乐.工作.学习都会或多或少的用到电脑,在电脑被使用越发频繁的今天,电脑出现的问题也就相应得多了,最常见的问题之一就是电脑的开机时间太长,导致的原因可能是因为电脑的使用时间太久了,当然,也 ...

  9. 语言做一个自动售货机软件_软件开发手机app系统软件高端定制做一个app软件要多少钱...

    软件开发手机app系统软件高端定制-做一个app软件要多少钱 APP开发分原生APP开发和在线制作,我们来看下这两种都需要多少费用吧. 1.原生APP开发(定制开发) 互联网是个神奇的大网,大数据开发 ...

  10. vue项目下拉框内容过长做一个滚动条的效果

    vue项目下拉框内容过长做一个滚动条的效果 如下图: 关键代码如下:

最新文章

  1. 网络营销外包——网络营销外包专员如何帮助企业挑选网站建设类型
  2. python r语言 结合 部署_(转)python中调用R语言通过rpy2 进行交互安装配置详解...
  3. JS之Boolean的valueOf方法
  4. 学会了这些技术,你离BAT大厂不远了
  5. 从历史角度讲现代数学
  6. 软件设计师--面向对象技术
  7. 人工智能为什么要从本科生抓起?
  8. excel导入Mysql之间的转换
  9. 给Emacs安装一个脚踏板: 用Windows/Menu键作为key modifier
  10. 《项目经验》静态页面图片找不到
  11. SPSS做因子分析(非常细致的过程)
  12. XBOX360游戏发售表(12月1日)
  13. 谈《西游记》和泛项目
  14. win10 计算机磁盘加内存,内存不够用?教你给Win10系统增加C盘空间
  15. 日文配列键盘修改和映射自定义
  16. 用boot camp助理装win 7时卡在了“正在拷贝windows文件”
  17. ALTER TABLE 语句添加字段
  18. 学校学生计算机教室解决方案,学校学生计算机教室解决方案设计.docx
  19. java其他框架杂记
  20. STM32MP157驱动开发——Linux自带的LED灯驱动

热门文章

  1. 微型计算机的应用形式,微型计算机基本原理与应用
  2. Tomcat运行原理
  3. 恶意样本分析流程记录
  4. xmind思维导图(下载、使用——超级详细)
  5. IDEA背景颜色及背景图片设置
  6. 微信抖音社区团购小程序源码开发方案怎么做
  7. 计算机应用cad题库,cad试题库
  8. Linux常用远程连接工具介绍,总有一款适合你
  9. 一个基于.NET Core3.1的开源项目帮你彻底搞懂WPF框架Prism
  10. 音频系统测试软件:Smaart for Mac