炫酷跑酷教程(完)——人物控制
前言:
本文為跑酷系列的完結篇。前兩期傳送門:
炫酷跑酷教程(1)——簡單的動態地圖生成與人物動作
炫酷跑酷教程(2)——多樣化的道路生成與簡單UI
前2篇文章中主要講解的是如何搭建地圖,文本顯示,以及簡單的人物控制。本期我們從遊戲的細節入手,讓角色的動作更多,使之更接近一個商業化遊戲的完成度。Lets begin:
動作分析:
通過參照神廟逃亡遊戲,我們可以分析出該遊戲有一下動作:
1.前跑
2.左右移動
3.左轉
4.右轉
5.跳躍
6.下滑
其中1,2已經在第一篇文章的時候實現。3,4雖然沒有寫出來,但是在第二篇文章的時候就已經實裝了,這次會重新講解一下。本篇文章著重實現5,6功能。
動畫狀態機:
工欲善其事必先利其器。在開始動作功能實現之前,先搭建好我們玩家的的動畫狀態機。選擇我們之前新建好的動畫控制器,打開Animator視圖,將我們需要使用的動作拖入其中。如圖:
在旁邊的Parameters菜單新建2個BOOL控制開關,並命名為IsJump 與IsSlide.如圖:
然後將新建的2個狀態應用到動作之上,並去掉Has Exit Time的勾選,如圖:
代碼實現:
完成上面準備工作後,就可以進行我們的實現環節了。
左轉右轉功能:
左轉右轉,就是將玩家自身繞Y軸旋轉正或負90度的效果。但是要是在一幀內直接修改完成的話,效果就會很突兀。於是我們使用DoTween插件來完成這個功能,於是先引用Dotween插件。然後在 PlayerController.cs文件中寫入以下代碼:
if (Input.GetKeyDown(KeyCode.J) && isTurnleftEnd) //如果按下J鍵且左轉完成 { isTurnleftEnd = false; //更新轉向狀態 transform.Rotate(Vector3.up,-90); Quaternion tmpQuaternion = transform.rotation; //計算轉向後的四元數並保存 transform.Rotate(Vector3.up, 90); //角度回滾 Tween tween = transform.DORotateQuaternion(tmpQuaternion, 0.3f); //使用DoTween插件進行轉向的平滑運動 tween.OnComplete(() => isTurnleftEnd = true); //動畫結束後轉向狀態更新 }
通過這段代碼,我們實現了在遊戲中按下J鍵人物向自己的方向左轉,右轉也是同理,這裡就不再細說。
跳躍功能:
跳躍功能有以下2部分組成:
1.跳躍動作播放
2.玩家位置升高
首先我們先實現玩家的跳躍動作的播放,我們在UPdata函數中寫入以下代碼:
if (Input.GetKeyDown(KeyCode.Space) && playController.isGrounded) { isJumpState = true; //更新跳躍狀態 playAnimtor.SetBool("IsJump", true); //播放跳躍動畫 }
按下空格,就會看到玩家已經能夠播放跳躍這個動作了,但是這還不夠,我們還需要將玩家的位置身高才算完成,那麼我們這個時候還需要在代碼中寫入以下代碼,才能夠實現這個功能。如下:
if (isJumpState) //如果現在正在進行跳躍 { MoveIncrements.y += jumpPower*Time.deltaTime;//根據設置好的跳躍高度進行平滑運動 } else { MoveIncrements.y += playController.isGrounded ? 0f : -5.0f * Time.deltaTime * 1f; //更新重力 } playController.Move(MoveIncrements);
可能有同學看不懂這一段,我來解釋一下。我們這個遊戲裡面使用的是charactercontroller.move();函數。這個函數移動是通過調用函數時的參數來進行移動的,它是一個增量的移動函數。如果你在玩家的坐標為(1,1,1)時調用這個函數,並給了一個(1,1,1)參數。那麼下一幀,玩家的坐標就會改變為(2,2,2)。我們在代碼中更改了MoveIncrements的Y值,那麼下一幀玩家的坐標就會在前進的基礎上,向上運動設置好的Y值,就實現了玩家高度的改變。
下滑功能:
原理與跳躍動畫播放相同,只不過不需要進行高度差調整。只需要簡單的在代碼中寫入如下代碼就行了。如下:
if (Input.GetKeyDown(KeyCode.K)) { playAnimtor.SetBool("IsSlide", true); }
完成後:
動畫事件:
經過了以上的步驟,細心的同學會發現我們只對動畫的開關進行了打開操作,並沒有進行關閉操作。而且我們還去掉了Has Exit Time的勾選,這樣就會導致我們在播放一個動畫完成後,不能夠退出這個動畫,出現人物停止的情況。有多種方法可以解決這個問題,例如寫一個延時函數,延遲的時間為動畫的播放時間,當打開動畫播放開關的時候,調用這個函數,這樣在動畫播放完成後就能夠順利的關閉動畫了。但是我們這使用的是不同的方法,我們採用的是給動畫添加一個事件,在動畫播放到一定進度,就執行這個事件。為了實現這個功能,我們需要先獲得運行時動畫控制器RuntimeAnimatorController,與當前角色的能夠播放的動畫數組。如下:
RuntimeAnimatorController nowController; //現在的運行時動畫控制器 AnimationClip[] cilps; //播放的動畫數組 void Start () { nowController = playAnimtor.runtimeAnimatorController; cilps = nowController.animationClips; }
添加成功後,事件的具體實現:
for (int i=0;i<cilps.Length; i++) { if (cilps[i].events.Length<=0) { switch (cilps[i].name) //通過動畫的名字進行設置 { case "JUMP00": //是跳躍 AnimationEvent endEvent = new AnimationEvent(); //實例化一個動畫事件 endEvent.functionName = "JumpEnd"; //事件的方法是「JumpEnd」 endEvent.time = cilps[i].length - (20.0f / 56.0f) * 1.83f; //事件的執行時間(這個可按需求進行調節) cilps[i].AddEvent(endEvent); //這個跳躍動畫添加這個事件 break; } } } public void JumpEnd() { playAnimtor.SetBool("IsJump", false); //動畫狀態回滾 }
這樣完成後,我們就可以在動畫播放到設置好的進度時,關閉動畫的播放開關,使得遊戲人物動作切換更加流暢了。
結語:
經過這3期文章,我們已經實現了一個跑酷小遊戲的DEMO,是不是覺得很有趣?要是你看到這還沒有完成的話,那就加把勁干吧。本期的工程地址還是上2期的地址,已經進行了更新,有興趣的同學可以下載試玩一把哦。
好了,末尾老規矩(滑稽),打個廣告:想學習遊戲開發的同學,歡迎來http://www.levelpp.com/圍觀哦。
推薦閱讀:
※2D動畫的3D體積感:AngerForce幕後故事
※關於遊戲中松耦合那些事……
※修正Shader文字描邊的跨字採樣錯誤
※兩個平均年齡十一歲的小男孩,做了兩款遊戲