【游戏开发创新】上班通勤时间太长,做一个任意门,告别地铁与塞车(Unity | 建模 | ShaderGraph | 摇杆 | 角色控制)
文章目錄
- 一、前言
- 二、最終效果
- 三、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,創建一個PBR的ShaderGraph,
重命名為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,即屏幕左下角,調整坐標和寬高,
像這樣子,
把它的Color的alpha調為0,因為我們只需要利用它的區域來檢測觸碰,我們不需要肉眼看見它,
接著在它的子節點下創建兩個Image,分別命名為bg和center,
它們的Source Image都設置為搖桿的圖片資源,
分別調整下bg和center的大小和顏色透明度,效果如下:
同理再做一個右搖桿,
效果如下:
接下來需要給搖桿加上邏輯,Unity的UGUI提供了ScrollRect組件,非常適合用來制作搖桿,我們繼承ScrollRect然后實現OnDrag和OnEndDrag方法,可以很方便地獲取到搖桿的遙控數據,另外,為了檢測區域點擊,我們再實現IPointerDownHandler接口。
創建搖桿腳本JointedArm.cs,代碼如下:
把JointedArm.cs分別掛到leftJointedArm和rightJointedArm上,賦值對應的center,
運行Unity,搖桿測試效果如下:
接下來我們要實現左搖桿控制主角移動并播放跑的動畫,右搖桿控制攝像機角度旋轉。
3、主角移動控制
3.1、動畫控制
注:關于Animator組件的詳細使用可以參見我之前寫的這篇文章:《Unity動畫狀態機Animator使用》
打開角色的動畫控制器文件CharacterController,
可以看到,兩個動作,一個idle(站立)一個Run(跑),
到Parameters(參數)里面有一個AnimationPar參數,這個參數就是用來控制站立與跑著兩個動畫的過渡條件的,
從Idle過渡到Run的條件是AnimationPar等于1,
從Run過渡到Idle的條件是AnimationPar等于0,
這樣,我們就可以在代碼中通過這個參數來控制動畫的過渡了,例:
3.2、移動控制
主角的移動控制包括坐標和角度的變化,當搖桿向左滑,主角向左移動,同時主角的朝向也跟著轉向左邊。
移動我們可以設置transfrom的position屬性來實現,轉向我們可以設置transfrom的forward屬性來實現,例:
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,把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組件,并根據主角模型大小設置Radius和Height,
如下:
運行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 Lifttime和Size 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 | 摇杆 | 角色控制)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实习第一个月体会和总结
- 下一篇: word 添加页眉页脚,添加不同页码