Photon Unity Networking基礎(chǔ)教程 6 - Player Camera Work

這部分將會知道你創(chuàng)建CameraWork腳本,再你玩游戲的時(shí)候讓相機(jī)跟隨你的角色。這個(gè)腳本和網(wǎng)絡(luò)沒什么關(guān)系,所以簡短介紹。

主要內(nèi)容

  • 創(chuàng)建CameraWork腳本

創(chuàng)建CameraWork腳本

  1. 新建一個(gè)C#腳本,命名為CameraWork

  2. 把CameraWork的內(nèi)容替換成下面的代碼

     using UnityEngine;
     using System.Collections;
     
     namespace Com.MyCompany.MyGame
     {
         /// <summary>
         /// Camera work. Follow a target
         /// </summary>
         public class CameraWork : MonoBehaviour
         {
             #region Public Properties
     
             [Tooltip("The distance in the local x-z plane to the target")]
             public float distance = 7.0f;
     
             [Tooltip("The height we want the camera to be above the target")]
             public float height = 3.0f;
     
             [Tooltip("The Smooth time lag for the height of the camera.")]
             public float heightSmoothLag = 0.3f;
     
             [Tooltip("Allow the camera to be offseted vertically from the target, for example giving more view of the sceneray and less ground.")]
             public Vector3 centerOffset = Vector3.zero;
     
             [Tooltip("Set this as false if a component of a prefab being instanciated by Photon Network, and manually call OnStartFollowing() when and if needed.")]
             public bool followOnStart = false;
     
             #endregion
     
             #region Private Properties
             // cached transform of the target
             Transform cameraTransform;
     
             // maintain a flag internally to reconnect if target is lost or camera is switched
             bool isFollowing;
             // Represents the current velocity, this value is modified by SmoothDamp() every time you call it.
             private float heightVelocity = 0.0f;
             // Represents the position we are trying to reach using SmoothDamp()
             private float targetHeight = 100000.0f;
             #endregion
     
             #region MonoBehaviour Messages
             /// <summary>
             /// MonoBehaviour method called on GameObject by Unity during initialization phase
             /// </summary>
             void Start()
             {
                 // Start following the target if wanted.
                 if (followOnStart)
                 {
                     OnStartFollowing();
                 }
             }
     
             /// <summary>
             /// MonoBehaviour method called after all Update functions have been called. This is useful to order script execution. For example a follow camera should always be implemented in LateUpdate because it tracks objects that might have moved inside Update.
             /// </summary>
             void LateUpdate()
             {
                 // The transform target may not destroy on level load, 
                 // so we need to cover corner cases where the Main Camera is different everytime we load a new scene, and reconnect when that happens
                 if (cameraTransform == null && isFollowing)
                 {
                     OnStartFollowing();
                 }
     
                 // only follow is explicitly declared
                 if (isFollowing)
                 {
                     Apply();
                 }
             }
             #endregion
     
             #region Public Methods
             /// <summary>
             /// Raises the start following event. 
             /// Use this when you don't know at the time of editing what to follow, typically instances managed by the photon network.
             /// </summary>
             public void OnStartFollowing()
             {
                 cameraTransform = Camera.main.transform;
                 isFollowing = true;
                 // we don't smooth anything, we go straight to the right camera shot
                 Cut();
             }
             #endregion
             
             #region Private Methods
             /// <summary>
             /// Follow the target smoothly
             /// </summary>
             void Apply()
             {
                 Vector3 targetCenter = transform.position + centerOffset;
     
                 // Calculate the current & target rotation angles
                 float originalTargetAngle = transform.eulerAngles.y;
                 float currentAngle = cameraTransform.eulerAngles.y;
     
                 // Adjust real target angle when camera is locked
                 float targetAngle = originalTargetAngle;
                 currentAngle = targetAngle;
                 targetHeight = targetCenter.y + height;
     
                 // Damp the height
                 float currentHeight = cameraTransform.position.y;
                 currentHeight = Mathf.SmoothDamp(currentHeight, targetHeight, ref heightVelocity, heightSmoothLag);
     
                 // Convert the angle into a rotation, by which we then reposition the camera
                 Quaternion currentRotation = Quaternion.Euler(0, currentAngle, 0);
     
                 // Set the position of the camera on the x-z plane to:
                 // distance meters behind the target
                 cameraTransform.position = targetCenter;
                 cameraTransform.position += currentRotation * Vector3.back * distance;
     
                 // Set the height of the camera
                 cameraTransform.position = new Vector3(cameraTransform.position.x, currentHeight, cameraTransform.position.z);
     
                 // Always look at the target    
                 SetUpRotation(targetCenter);
             }
     
             /// <summary>
             /// Directly position the camera to a the specified Target and center.
             /// </summary>
             void Cut()
             {
                 float oldHeightSmooth = heightSmoothLag;
                 heightSmoothLag = 0.001f;        
                 Apply();        
                 heightSmoothLag = oldHeightSmooth;
             }
     
             /// <summary>
             /// Sets up the rotation of the camera to always be behind the target
             /// </summary>
             /// <param name="centerPos">Center position.</param>
             void SetUpRotation(Vector3 centerPos)
             {
                 Vector3 cameraPos = cameraTransform.position;
                 Vector3 offsetToCenter = centerPos - cameraPos;        
     
                 // Generate base rotation only around y-axis
                 Quaternion yRotation = Quaternion.LookRotation(new Vector3(offsetToCenter.x, 0, offsetToCenter.z));        
     
                 Vector3 relativeOffset = Vector3.forward * distance + Vector3.down * height;
                 cameraTransform.rotation = yRotation * Quaternion.LookRotation(relativeOffset);        
     
             }
             #endregion
         }
     }
    
  3. 保存腳本

如果你剛剛開始與實(shí)時(shí)3d,向量和四元數(shù)學(xué),那么跟隨玩家角色的數(shù)學(xué)是復(fù)雜的。所以我嘗試在本教程中解釋這一點(diǎn)。但是如果你好奇,想學(xué)習(xí),不要猶豫與我們聯(lián)系,我們會盡最大努力解釋清楚。

然而,這個(gè)腳本不僅僅是瘋狂的數(shù)學(xué),設(shè)置也是重要的,以及控制何時(shí)應(yīng)該主動跟隨玩家的能力。理解這點(diǎn)很重要:我們?yōu)槭裁匆刂剖裁磿r(shí)候跟隨玩家。

通常,讓我們想象如果總是跟隨玩家會發(fā)生什么。當(dāng)你連接到一個(gè)充滿玩家的房間,其他玩家的每個(gè)CameraWork腳本為了一直看著自己的角色會相互打架...我們不想要這種,我們只想跟隨本地玩家角色,它代表的是計(jì)算機(jī)后面的用戶。

一旦我們定義了這個(gè)問題,我們只有一個(gè)攝像機(jī),但有多個(gè)Player實(shí)例,我們可以很容易找到幾種方法。

  • 僅在本地玩家上附加CameraWork腳本。
  • 通過關(guān)閉和打開來控制CameraWork行為,具體取決于要關(guān)注的Player是否是本地玩家。
  • 讓CameraWork連接到相機(jī),并注意當(dāng)場景中有一個(gè)本地玩家實(shí)例時(shí)只跟隨那個(gè)。

這3個(gè)選項(xiàng)并不詳盡,可以找到更多的方法,但在這3個(gè)選項(xiàng)中,我們將任意選擇第二個(gè)。上面的選項(xiàng)沒有更好或更壞,但是這是一個(gè)可能需要最少的編碼和最靈活的...“有趣...”我聽到你說:)

  • 我們暴露了一個(gè)公共屬性followOnStart,如果我們想在非聯(lián)網(wǎng)環(huán)境中使用它,我們可以設(shè)置為true,例如在我們的測試場景中,或者在完全不同的場景

  • 當(dāng)在我們的網(wǎng)絡(luò)游戲中運(yùn)行時(shí),當(dāng)我們檢測到Player是本地玩家時(shí),我們將調(diào)用公共方法OnStartFollowing()。這將在PlayerManager腳本中完成,該腳本PlayerManager在“Player Prefab Networking”一章中創(chuàng)建和解釋。

原文

http://doc.photonengine.com/en-us/pun/current/tutorials/pun-basics-tutorial/player-camera-work

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,939評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內(nèi)容