簡述
在傳送門中,核心的玩法是在地上或者牆上打開2個可以聯通的洞來實現傳送的效果。以此擴展加入解謎要素構成游戲的核心。
這里嘗試使用unity來實現傳送門的核心功能,具體功能分析如下:
1、傳送門的模型
2、傳送門的貼圖
3、傳送門的傳送功能
這里我們需要以下軟件:3dmax 2014,unity3d 5.4.0,visual studio 2015
一、傳送門的模型和uv
打開3dmax,確認系統單位和顯示單位都為米,如果不為米,改成米
建立一個圓柱體,高度段數1,端面分段1,邊數32,調整到適當大小,轉化為可編輯多邊形,刪除除了頂部面之外的所有面,位置歸0。再次轉化為可編輯多邊形。
使用uvw展開命令,進行uv展開
更改模型的名稱和材質的名稱,導出fbx文件
二、傳送門的動態貼圖
1、靜態效果實現
打開unity,導入模型,導入一個適當的場景包作為測試場景,創建一個可以用鍵盤控制的Player,用於場景游歷和功能測試
創建一個新的攝像機,放在其他位置,作為傳送的目標點。創建一個RenderTexture,拖拽到攝像機的Target Texture上。將攝像機的Clear flag改為solid color。適當更改相機的Viewport Rect。
將導入的傳送門模型拖拽到場景中,放置在一面牆上,設置模型材質的貼圖為RenderTexture。
可以看到效果如下
2、動態效果實現
傳送門的效果類似與一個洞,在不同的位置看過去,顯示的大小和物件都是有差別的。就類似你通過一個窗戶看外面的世界類似。所以,我們要根據玩家的攝像機相對與傳送門的相對位置關系,來設置目標點攝像機的相關數據,比如,視角,位置,選擇和裁剪等。
- 目標攝像機和傳送點的距離=玩家和傳送門的距離
- 目標攝像機的裁剪距離=目標攝像機和傳送點的距離
- 目標攝像機始終朝向傳送點
- 目標攝像機的視角=2*Atan(傳送門高度/2/目標攝像機和傳送點的距離)
注意Atan在unity中為弧度,需要再乘上Mathf.Rad2Deg轉成角度
部分代碼如下(這里利用父子關系實現位置變化,目標攝像機為傳送點的子物體,所以目標攝像機的localposition也就是相對於傳送點的相對距離)
internal protected void Update() { var cpos = Camera.main.transform.position; var mt = Render.worldToLocalMatrix; mt = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(180, Vector3.up), Vector3.one) * mt; Camera.transform.localPosition = mt.MultiplyPoint(cpos); Camera.transform.LookAt(Point); Camera.nearClipPlane = -Camera.transform.localPosition.z; const float renderHeight = 3f; Camera.fieldOfView = 2 * Mathf.Atan(renderHeight / 2 / Camera.nearClipPlane) * Mathf.Rad2Deg; }
三、傳送功能實現
在傳送門上增加一個collider,設置為Trigger,當玩家與之發生碰撞的時候設置玩家的位置數據
- 玩家的位置=傳送點的位置,
- 玩家相對與傳送點的朝向=傳送前,玩家相對於傳送門的朝向
部分代碼如下
internal protected void OnTriggerEnter(Collider other) { other.transform.root.rotation = other.transform.root.rotation * Point.rotation * Render.rotation; other.transform.root.position = Point.position; }
總結
本項目整體難度不大,大約花費時間2天
目前項目已經開源,地址為http://git.oschina.net/CodeGize/PortalGame,可以前往下載