[Unity3D]Unity3D遊戲開發之自由視角下的角色控制,unity3d遊戲開發
各位朋友,大家好,我是秦元培,歡迎大家關注我的部落格,我的部落格地址是blog.csdn.net/qinyuanpei。在上一篇文章<[Unity3D]Unity3D遊戲開發之角色控制漫談>一文中,博主與大家分享自己在角色控制方面的一些感悟。今天呢,我們繼續來探討Unity3D角色控制的內容,今天博主將解決在上一篇文章中沒有解決的問題,即自由視角下的角色控制。是博主非常喜歡的《古劍奇譚》遊戲,在這款遊戲中就使用了博主今天要講解的自由視角,所謂自由視角是指玩家可以按照自身座標系向著四個不同的方向移動,當玩家按下滑鼠右鍵時,可以繞Y軸按照一定的角度旋轉攝像機,在旋轉的過程中,角色將旋轉相應的角度。在移動的過程中,攝像機會保持與玩家間的一定距離,然後跟隨角色進行移動。好了,下面我們正式開始今天的內容吧!
在開始今天的內容前,首先讓我們來學習下Unity3D中較為重要的一部分知識,理解這些知識是我們開始學習今天內容的基礎。
1、Input.GetAxis():該方法用於在Unity3D中根據座標軸名稱返回虛擬座標系中的值,通常情況下,使用控制器和鍵盤輸入時此值範圍在-1到1之間。這段話怎麼理解呢?我們來看下面這段指令碼:
using UnityEngine;using System.Collections;public class example : MonoBehaviour {//水平速度public float HorizontalSpeed = 2.0F;//垂直速度public float VerticalSpeed = 2.0F;void Update() {//水平方向float h = HorizontalSpeed * Input.GetAxis("Mouse X");//垂直方向float v = VerticalSpeed * Input.GetAxis("Mouse Y");//旋轉transform.Rotate(v, h, 0);}}這段指令碼呢是根據滑鼠的位置來旋轉物體從而實現對物體的觀察,從這段指令碼中我們可以看出,通過擷取輸入軸的辦法,我們可以獲得滑鼠移動的方向進而實現對於物體的旋轉控制。在Unity3D中我們可以通過Edit->Project Setting->Input來查看項目中的座標軸名稱:
在後面,我們還將使用這種方式,大家可以對這個方法有進一步的瞭解。
2、歐拉角eulerAngles:該值是Vector3類型的值,x、y、z分別代表繞x軸旋轉x度,繞y軸旋轉y度,繞z軸旋轉z度。因此,該值最為直觀的形式是可以允許我們直接以一個三維向量的形式來修改一個物體的角度,例如下面的指令碼:
float mY = 5.0;void Update () {mY += Input.GetAxis("Horizontal");transform.eulerAngles =new Vector3(0,mY, 0);} 如果你已經理解了上面的話,那麼不出意外的,這段指令碼會如你所願的,按照滑鼠在水平方向上移動的方向繞Y軸旋轉。通常情況下,我們不會單獨設定歐拉角其中一個軸,例如eulerAngles.x = 10,因為這將導致位移和不希望的旋轉。當設定它們一個新的值時,要同時設定全部。好在我們可以通過Quaternion.Euler()方法將一個Vector3類型的值轉化為一個四元數,進而通過修改Transform.Rotation來實現相同的目的。
3、插值:所謂插值是指在離散資料的基礎上補插連續函數,使得這條連續曲線通過全部給定的離散資料點。插值是離散函數逼近的重要方法,利用它可通過函數在有限個點處的取值狀況,估算出函數在其他點處的近似值。在某些情況下,如果我們希望過程中處理得較為平滑,此時我們就可以使用插值的方法來實現對中間過程的類比。在Unity3D中我們可以使用兩種插值方法,即線性插值Lerp,球形插值SLerp。我們來看下面的指令碼:
void Rotating (float horizontal, float vertical){// Create a new vector of the horizontal and vertical inputs.Vector3 targetDirection = new Vector3(horizontal, 0f, vertical);// Create a rotation based on this new vector assuming that up is the global y axis.Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up);// Create a rotation that is an increment closer to the target rotation from the player's rotation.Quaternion newRotation = Quaternion.Lerp(rigidbody.rotation, targetRotation, turnSmoothing * Time.deltaTime);// Change the players rotation to this new rotation.rigidbody.MoveRotation(newRotation);}插值的方法很簡單,只要我們給出初始和結束的狀態、時間就可以了,大家可以自己看API。
好了,有了這三部分的基礎,我們就可以開始今天的內容了,今天的指令碼分為兩個部分,第一部分是角色控制的部分,主要負責的角色在情境中的移動、轉身和動畫處理。第二部分是相機控制的部分,主要涉及相機旋轉、相機縮放的相關內容。下面,我們分別來講這兩個部分,情境依然是博主自己在做的小遊戲:
本次的主角呢,是博主非常喜歡的角色謝滄行,好了,我們回到今天的內容裡吧!在第一部分,主要的是完成角色向各個方向的轉身,這裡博主定義四個方向(其實八個方向是一樣的!),指令碼如下:
using UnityEngine;using System.Collections;public class NoLockiVew_Player : MonoBehaviour {/*自由視角下的角色控制*//*作者:秦元培*///玩家的行走速度public float WalkSpeed=1.5F;//重力public float Gravity=20;//角色控制器private CharacterController mController;//動畫組件private Animation mAnim;//玩家方向,預設向前private DirectionType mType=DirectionType.Direction_Forward;[HideInInspector]//玩家狀態,預設為Idlepublic PlayerState State=PlayerState.Idle;//定義玩家的狀態枚舉public enum PlayerState{Idle,Walk}//定義四個方向的枚舉值,按照逆時針方向計算protected enum DirectionType{Direction_Forward=90,Direction_Backward=270,Direction_Left=180,Direction_Right=0}void Start () { //擷取角色控制器 mController=GetComponent<CharacterController>(); //擷取動畫組件 mAnim=GetComponentInChildren<Animation>();}void Update () {MoveManager();//MouseEvent();}//玩家移動控制void MoveManager(){//移動方向Vector3 mDir=Vector3.zero;if(mController.isGrounded){//將角色旋轉到對應的方向if(Input.GetAxis("Vertical")==1){SetDirection(DirectionType.Direction_Forward);mDir=Vector3.forward * Time.deltaTime * WalkSpeed;mAnim.CrossFade("Walk",0.25F);State=PlayerState.Walk;}if(Input.GetAxis("Vertical")==-1){SetDirection(DirectionType.Direction_Backward);mDir=Vector3.forward * Time.deltaTime * WalkSpeed;mAnim.CrossFade("Walk",0.25F);State=PlayerState.Walk;}if(Input.GetAxis("Horizontal")==-1){SetDirection(DirectionType.Direction_Left);mDir=Vector3.forward * Time.deltaTime * WalkSpeed;mAnim.CrossFade("Walk",0.25F);State=PlayerState.Walk;}if(Input.GetAxis("Horizontal")==1){SetDirection(DirectionType.Direction_Right);mDir=Vector3.forward * Time.deltaTime * WalkSpeed;mAnim.CrossFade("Walk",0.25F);State=PlayerState.Walk;}//角色的Idle動畫if(Input.GetAxis("Vertical")==0 && Input.GetAxis("Horizontal")==0){mAnim.CrossFade("Idle",0.25F);State=PlayerState.Idle;}}//考慮重力因素mDir=transform.TransformDirection(mDir);float y=mDir.y-Gravity *Time.deltaTime;mDir=new Vector3(mDir.x,y,mDir.z);mController.Move(mDir);}//設定角色的方向,有問題void SetDirection(DirectionType mDir){if(mType!=mDir){transform.Rotate(Vector3.up*(mType-mDir));mType=mDir;}}}這裡定義四個方向,是按照逆時針方向轉的,相鄰的兩個方向間相差90度,所以我們只需要將當前的角度和目標角度相減就可以轉到目標角度的方向(其實這是以前寫的代碼,現在回頭再看,直接用歐拉角似乎更為簡單啊,呵呵)。這裡主要的內容就是這樣了。下面我們來看相機控制部分的代碼吧,這裡的代碼參考了MouseOrbit指令碼,主要完成了滑鼠右鍵旋轉控制,博主在此基礎上增加了相機縮放的代碼。提到相機縮放,其實就是根據滑鼠滾輪滾動的方向和大小重新計算角色與相機的距離,與之類似地還有小地圖的放縮,其實同樣是通過修改距離來實現的。博主今天的一個體會是官方的代碼能自己寫一遍的最好自己寫一遍,這樣好多東西就能在這個過程中給理解了。我們一起來看指令碼
using UnityEngine;using System.Collections;public class NoLockView_Camera : MonoBehaviour {//觀察目標public Transform Target;//觀察距離public float Distance = 5F;//旋轉速度private float SpeedX=240;private float SpeedY=120;//角度限制private float MinLimitY = 5;private float MaxLimitY = 180;//旋轉角度private float mX = 0.0F;private float mY = 0.0F; //滑鼠縮放距離最值private float MaxDistance=10;private float MinDistance=1.5F;//滑鼠縮放速率private float ZoomSpeed=2F;//是否啟用差值public bool isNeedDamping=true;//速度public float Damping=2.5F;void Start () {//初始化旋轉角度mX=transform.eulerAngles.x;mY=transform.eulerAngles.y;}void LateUpdate () {//滑鼠右鍵旋轉if(Target!=null && Input.GetMouseButton(1)){ //擷取滑鼠輸入mX += Input.GetAxis("Mouse X") * SpeedX * 0.02F;mY -= Input.GetAxis("Mouse Y") * SpeedY * 0.02F;//範圍限制mY = ClampAngle(mY,MinLimitY,MaxLimitY);}//滑鼠滾輪縮放Distance-=Input.GetAxis("Mouse ScrollWheel") * ZoomSpeed;Distance=Mathf.Clamp(Distance,MinDistance,MaxDistance);//重新計算位置和角度Quaternion mRotation = Quaternion.Euler(mY, mX, 0);Vector3 mPosition = mRotation * new Vector3(0.0F, 0.0F, -Distance) + Target.position;//設定相機的角度和位置if(isNeedDamping){ //球形插值 transform.rotation = Quaternion.Lerp(transform.rotation,mRotation, Time.deltaTime*Damping); //線性插值 transform.position = Vector3.Lerp(transform.position,mPosition, Time.deltaTime*Damping); }else{ transform.rotation = mRotation; transform.position = mPosition;}//將玩家轉到和相機對應的位置上if(Target.GetComponent<NoLockiVew_Player>().State==NoLockiVew_Player.PlayerState.Walk){Target.eulerAngles=new Vector3(0,mX,0);}}private float ClampAngle (float angle,float min,float max) {if (angle < -360) angle += 360;if (angle > 360) angle -= 360;return Mathf.Clamp (angle, min, max);} }
這裡很多朋友可能對我設定一個狀態很不理解吧,這其實是為了讓玩家有一個自由查看角色的機會,否則當玩家按下滑鼠右鍵的話,角色就會轉向相機正對著的位置,這樣玩家就看不到角色的正面了。當然,這裡用到了插值,這樣能使角色在轉身的時候平滑一點,效果會更好。
唉,不知不覺已經這個時候了,開學已經一周了,這學期我們只上九周課,然後就是實習、畢設、找工作一大堆事情在等著我們。可是不知道為什麼博主宿舍的同學居然還能每天什麼事情都不做,從早上一直看電視劇到晚上十點,雖然這件事情和博主沒有什麼關係吧,可是整個宿舍的人都安安靜靜地做著自己的事情,就有這麼一個人整天聲音開得很大在那裡外放,這樣真的好嗎?以前和這個人鬧過一次,因為他聚了一幫人在宿舍打麻將,我覺得吵就說了他一頓,結果就和我僵上了。說真的,博主對目前的專業真的沒有什麼情感,大學四年裡最讓博主開心的事情就是博主學會了好多自己想要學的東西,認識了幾個不錯的老師和朋友,僅此而已。或許我們註定要越走越遠吧,因為我們根本就不是同一種人。
前幾天網上有人通過部落格聯絡到博主,希望博主能到他哪裡工作,可惜博主目前仍然有一大堆的瑣事纏身,不然離開這喧囂吵鬧的宿舍,去做博主喜歡的事情,去尋找博主自己的夢想,博主相信,博主一定可以做得更好吧。人生或許就是這樣,你越是在乎的可能越讓你得不到,你無心插柳可能會得到一片綠蔭。對於未來,不管怎麼樣,坦然面對就好了,博主改變不了周圍的這群人,只能努力地去改變自己。好了,晚安吧!
效果示範(2M的限制讓很多展示都無可奈何)
每日箴言:所有的悲傷,總會留下一絲歡樂的線索。所有的遺憾,總會留下一處完美的角落。我在冰封的深海,找尋希望的缺口。卻在午夜驚醒時,驀然瞥見絕美的月光。——幾米
喜歡我的部落格請記住我的名字:秦元培,我部落格地址是blog.csdn.net/qinyuanpei。
轉載請註明出處,本文作者:秦元培,本文出處:http://blog.csdn.net/qinyuanpei/article/details/39125353
問Unity3D中,第三人稱視角使用角色控制器的Move函數移動時,怎實現由滑鼠左右移動控制運動朝向?
Vector3 movement = Vector3 .forward* walkSpeed;
movement *= Time.deltaTime;
CharacterController cc = this.GetComponent<CharacterController>();
cc.Move(movement);
Move不是絕對運動,是按方向的
[Unity3D]手機3D遊戲開發:怎使用Unity3D中內建的重力感應
汪 汪海的實驗室 海的實驗室- - 各種圖形學實驗和資料結構實驗以及其他一切瑣碎雜亂的小筆記們都相遇在此齊聚一堂共同守候 0 - - 各種圖形學實驗和資料結構實驗以及其他一切瑣碎雜亂的小筆記們都相遇在此齊聚一堂共同守候 0error(s), 0 warning(s) 這神奇時刻的到來 error(s), 0 warning(s) 這神奇時刻的到來學習Unity指令碼推薦:Unity3D官網索引重力感應在手機遊戲的開發中非常常見。Unity3D本身集合了重力感應的相關內容。一個簡單的JS指令碼示範一下重力感應的使用。CSDNGravity.js://物體的貼圖var round : Texture2D;//物體在螢幕中顯示的X Y座標var x = 0;var y = 0;//物體螢幕顯示的最大 X Y 範圍var cross_x = 0;var cross_y = 0;function Start(){//初始化賦值cross_x = Screen.width - round.width;cross_y = Screen.height - round.height;}function OnGUI () {//整體顯示 x y z 重力感應的重力分量GUI.Label(Rect(0,0,480,100),"position is " + Input.acceleration);//繪製物體GUI.DrawTexture(Rect(x,y,256,256),round);}function Update(){//根據重力分量修改物體的位置這裡乘以30的意思是讓物體移動的快一些x += Input.acceleration.x * 30;y += -Input.acceleration.y * 30;//避免物體超出螢幕if(x < 0){x = 0;}else if(x > cross_x){x = cross_x;}if(y < 0){y = 0;}else if(y > cross_y){y = cross_y;}}這裡的Input是指Unity中的輸入,acceleration便是其重力了,x和y分別代表其重力分量。建立完畢之後只需要添加紋理圖片即可:12