unity官方教程-TANKS(一)

unity官方教程TANKS,難度系數中階。
跟著官方教程學習Unity,通過本教程你可以學會使用Unity開發游戲的基本流程。

clipboard.png

一、環境

Unity 版本 > 5.2
Asset Store 里面搜索 Tanks!Tutorial ,下載導入

二、項目設置

為了便于開發,很多時候我們選用的窗口布局是 2by3 Layout,然后將 Project 面板拖動到 Hierarchy 面板下面,如下圖所示

clipboard.png

三、場景設置

項目設置完畢后,就進入場景設置環節

1、新建一個場景,命名為 Main
2、刪除場景中的 Directional Light
3、找到 Prefabs 文件夾下的 LevelArt,將其拖入 Hierarchy 內,這個 prefab 是我們的游戲地形
4、打開菜單 Windows->Lighting->Settings,取消 Auto Generate 和 Baked GI,將 Environment Lighting Source 改為 Color,并將顏色設置為(72,62,113),點擊 Generate Lighting,這一步主要是渲染設置
5、調整 Main Camera 位置為 (-43,42,-25),旋轉屬性為 (40,60,0),投影改為正交 Orthographic,Clear Flags 改為 Solid Color ,Background 顏色設置為(80,60,50),Clear Flags不設置也可以,這個設置主要影響的是相機移動到看不到場景內的物體時屏幕顯示的天空盒還是自己設置的 Solid Color 顏色

四、坦克設置

現在要往場景里加坦克了

1、在 Models 文件夾里面找到 Tank,將其拖拽到 Hierarchy 中
2、選中 Tank,在Inspector面板將 Layer 設置為 Players,跳出對話框時選 No,this object only
3、給 Tank 添加一個 Rigidbody Component,展開 Constraints 選項,勾選 Freeze Position Y 和 Freeze Rotation X Z,因為地面位于 XZ 平面,所以限定坦克不能在 Y 方向移動并且只能沿 Y 軸轉動
4、給 Tank 添加一個 Box Collider Component,將其中心 Center 調整為(0,0.85,0),尺寸 Size 調整為(1.5,1.7,1.6)
5、給 Tank 添加兩個 Audio Source Component,將第一個 Audio Source 的 AudioClip 屬性填充為 Engine Idle(坦克不動時的音頻),并勾選 Loop,將第二個 Audio Source 的 Play On Awake 取消
6、選中 Project 面板的 Prefabs 文件夾,將 Tank 拖入到該文件夾,至此我們就創建好了坦克 Prefab
7、將 Prefabs 文件夾中的 DustTrail 拖到 Hierarchy 面板中的 Tank 物體上,使其成為 Tank 的子物體,并Crtl + D(windows)復制一個,然后重命名為 LeftDustTrail 和 RightDustTrail,這是特效 - 坦克運動過程地面揚起的土
8、調整 LeftDustTrail 的 position 為(-0.5,0,-0.75),RightDustTrail 的position 為(0.5,0,-0.75)

以上過程便制作好了游戲主角 Tank,下面就要編程控制它運動了

1、找到 ScriptsTank 文件夾下的 TankMovement.cs,將其拖入到 Tank 物體上,打開 TankMovement.cs

public class TankMovement : MonoBehaviour
{public int m_PlayerNumber = 1;         public float m_Speed = 12f;            public float m_TurnSpeed = 180f;       public AudioSource m_MovementAudio;    public AudioClip m_EngineIdling;       public AudioClip m_EngineDriving;      public float m_PitchRange = 0.2f;/*private string m_MovementAxisName;     private string m_TurnAxisName;         private Rigidbody m_Rigidbody;         private float m_MovementInputValue;    private float m_TurnInputValue;        private float m_OriginalPitch;         private void Awake(){m_Rigidbody = GetComponent<Rigidbody>();}private void OnEnable (){m_Rigidbody.isKinematic = false;m_MovementInputValue = 0f;m_TurnInputValue = 0f;}private void OnDisable (){m_Rigidbody.isKinematic = true;}private void Start(){m_MovementAxisName = "Vertical" + m_PlayerNumber;m_TurnAxisName = "Horizontal" + m_PlayerNumber;m_OriginalPitch = m_MovementAudio.pitch;}*/private void Update(){// Store the player's input and make sure the audio for the engine is playing.}private void EngineAudio(){// Play the correct audio clip based on whether or not the tank is moving and what audio is currently playing.}private void FixedUpdate(){// Move and turn the tank.}private void Move(){// Adjust the position of the tank based on the player's input.}private void Turn(){// Adjust the rotation of the tank based on the player's input.}
}

里面已經有一些代碼了,下面我們就對其擴充來控制坦克移動
Unity控制物體移動的方法主要有兩種:
①非剛體(Update)
obj.transform.position = obj.transform.position+移動向量*Time.deltaTime;
obj.transform.Translate(移動向量*Time.deltaTime);
②剛體(FixedUpdate)
GetComponent<Rigidbody>().velocity
GetComponent<Rigidbody>().AddForce
GetComponent<Rigidbody>().MovePosition

由于我們的坦克是剛體,且移動被限制在了 XZ 平面,此時最好的方式是采用 MovePosition
獲取用戶輸入

    private void Start(){//在菜單Edit->Project Settings->Input設置,默認玩家1左右移動按鍵是 a 和 d,前后按鍵是 w 和 sm_MovementAxisName = "Vertical" + m_PlayerNumber;m_TurnAxisName = "Horizontal" + m_PlayerNumber;}private void Update(){//獲取用戶通過按鍵 w 和 s 的輸入量m_MovementInputValue = Input.GetAxis(m_MovementAxisName);//獲取用戶通過按鍵 a 和 d 的輸入量m_TurnInputValue = Input.GetAxis(m_TurnAxisName);}

移動和轉動

    private void Move(){Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;m_Rigidbody.MovePosition(m_Rigidbody.position + movement);}private void Turn(){float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;// 沿y軸轉動Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);m_Rigidbody.MoveRotation(m_Rigidbody.rotation * turnRotation);}

音效控制

    private void EngineAudio(){// 坦克是靜止的if (Mathf.Abs(m_MovementInputValue) < 0.1f && Mathf.Abs(m_TurnInputValue) < 0.1f){// 若此時播放的是坦克運動時的音效if (m_MovementAudio.clip == m_EngineDriving){m_MovementAudio.clip = m_EngineIdling;m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);//控制音頻播放速度m_MovementAudio.Play();}}else{if (m_MovementAudio.clip == m_EngineIdling){m_MovementAudio.clip = m_EngineDriving;m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);//控制音頻播放速度m_MovementAudio.Play();}}}

TankMovement.cs 完整代碼

using UnityEngine;public class TankMovement : MonoBehaviour
{public int m_PlayerNumber = 1;              // Used to identify which tank belongs to which player.  This is set by this tank's manager.public float m_Speed = 12f;                 // How fast the tank moves forward and back.public float m_TurnSpeed = 180f;            // How fast the tank turns in degrees per second.public AudioSource m_MovementAudio;         // Reference to the audio source used to play engine sounds. NB: different to the shooting audio source.public AudioClip m_EngineIdling;            // Audio to play when the tank isn't moving.public AudioClip m_EngineDriving;           // Audio to play when the tank is moving.public float m_PitchRange = 0.2f;           // The amount by which the pitch of the engine noises can vary.private string m_MovementAxisName;          // The name of the input axis for moving forward and back.private string m_TurnAxisName;              // The name of the input axis for turning.private Rigidbody m_Rigidbody;              // Reference used to move the tank.private float m_MovementInputValue;         // The current value of the movement input.private float m_TurnInputValue;             // The current value of the turn input.private float m_OriginalPitch;              // The pitch of the audio source at the start of the scene.private void Awake(){m_Rigidbody = GetComponent<Rigidbody>();}private void OnEnable(){// When the tank is turned on, make sure it's not kinematic.m_Rigidbody.isKinematic = false;// Also reset the input values.m_MovementInputValue = 0f;m_TurnInputValue = 0f;}private void OnDisable(){// When the tank is turned off, set it to kinematic so it stops moving.m_Rigidbody.isKinematic = true;}private void Start(){// The axes names are based on player number.m_MovementAxisName = "Vertical" + m_PlayerNumber;m_TurnAxisName = "Horizontal" + m_PlayerNumber;// Store the original pitch of the audio source.m_OriginalPitch = m_MovementAudio.pitch;}private void Update(){// Store the value of both input axes.m_MovementInputValue = Input.GetAxis(m_MovementAxisName);m_TurnInputValue = Input.GetAxis(m_TurnAxisName);EngineAudio();}private void EngineAudio(){// If there is no input (the tank is stationary)...if (Mathf.Abs(m_MovementInputValue) < 0.1f && Mathf.Abs(m_TurnInputValue) < 0.1f){// ... and if the audio source is currently playing the driving clip...if (m_MovementAudio.clip == m_EngineDriving){// ... change the clip to idling and play it.m_MovementAudio.clip = m_EngineIdling;m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);m_MovementAudio.Play();}}else{// Otherwise if the tank is moving and if the idling clip is currently playing...if (m_MovementAudio.clip == m_EngineIdling){// ... change the clip to driving and play.m_MovementAudio.clip = m_EngineDriving;m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);m_MovementAudio.Play();}}}private void FixedUpdate(){// Adjust the rigidbodies position and orientation in FixedUpdate.Move();Turn();}private void Move(){// Create a vector in the direction the tank is facing with a magnitude based on the input, speed and the time between frames.Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;// Apply this movement to the rigidbody's position.m_Rigidbody.MovePosition(m_Rigidbody.position + movement);}private void Turn(){// Determine the number of degrees to be turned based on the input, speed and time between frames.float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;// Make this into a rotation in the y axis.Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);// Apply this rotation to the rigidbody's rotation.m_Rigidbody.MoveRotation(m_Rigidbody.rotation * turnRotation);}
}

2、在將 TankMovement.cs 拖入到 Tank 上時,選擇 Tank 的第一個 Audio Source Component 拖入到TankMovement 的 Movement Audio上,并選擇 Engine Idling 為 EngineIdle 音頻,Engine Drving 為 EngineDrving 音頻,至此點擊 Apply,將我們后面對 Tank 的修改保存到 Tank prefab 中

clipboard.png

3、保存場景,點擊 Play 試玩一下

圖片描述

通過今天的教程,你可以學會

  • 場景設置,基本的物體操作
  • 編程控制物體移動

下期教程繼續。。。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254345.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254345.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254345.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Play框架的用戶驗證。

最近剛剛參與一個基于Play框架的管理平臺的升級工作&#xff0c;其中涉及到了用戶的驗證工作。第一次接觸play框架&#xff0c;直接看已有代碼&#xff0c;有點暈。因此&#xff0c;自己實現了一個簡單的用戶驗證功能。 首先&#xff0c;新建一個User類&#xff0c;包含兩個屬性…

C#條件運算符if-else的簡化格式

文章目錄博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 條件運算符&#xff08;&#xff1f;&#xff1a;&#xff09;是&#xff49;&#xff46;……&#xff45;&#xff4c;&#xff53;&#xff45;的簡化形式 其使用格式為&#xff1a…

碼率控制方式選擇

同碼率下的圖像質量或同圖像質量下的碼率。 AVCodecContext /** * the average bitrate * - encoding: Set by user; unused for constant quantizer encoding. * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the strea…

Fortran執行語句中的“雙冒號” ::

雙冒號“::”&#xff0c;通常出現于Fortran在變量聲明中&#xff0c;但是在特殊情況下&#xff0c;也會出現于數組中。例如&#xff1a; ... real,target,dimension(10):: a real,pointer,dimension(:):: pa,pb integer:: n3 ... pa > a(n::1) pb > a(n:10:1) ... 咋一看…

VS配置本地IIS以域名訪問

1.IIS下配置自己的網站&#xff0c;添加主機名 2.修改hosts文件&#xff08;C://Windows/System32/drivers/etc&#xff09; 3.VS中配置項目Web服務器&#xff08;選擇外部主機&#xff09; 轉載于:https://www.cnblogs.com/zuimeideshi520/p/7028544.html

try、catch、finally 和 throw-C#異常處理

文章目錄博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 異常是在程序執行期間出現的問題。C# 中的異常是對程序運行時出現的特殊情況的一種響應&#xff0c;比如嘗試除以零。 異常提供了一種把程序控制權從某個部分轉移到另一個部分的方式。…

Spark RDD/Core 編程 API入門系列 之rdd實戰(rdd基本操作實戰及transformation和action流程圖)(源碼)(三)...

本博文的主要內容是&#xff1a; 1、rdd基本操作實戰 2、transformation和action流程圖 3、典型的transformation和action RDD有3種操作&#xff1a; 1、 Trandformation 對數據狀態的轉換&#xff0c;即所謂算子的轉換 2、 Action 觸發作業&#xff0c;即所謂得結果…

用GDB調試程序

GDB概述GDB 是GNU開源組織發布的一個強大的UNIX下的程序調試工具。或許&#xff0c;各位比較喜歡那種圖形界面方式的&#xff0c;像VC、BCB等IDE的調試&#xff0c;但如果你是在 UNIX平臺下做軟件&#xff0c;你會發現GDB這個調試工具有比VC、BCB的圖形化調試器更強大的功能。所…

燈塔的出現給那些有想法,有能力而又缺乏資金的社區人士提供了一條途徑

2019獨角獸企業重金招聘Python工程師標準>>> 在上個月&#xff0c;BCH社區傳出基于比特幣現金的眾籌平臺Lighthouse&#xff08;燈塔&#xff09;正在復活的消息&#xff0c;并且有網友在論壇上貼出了部分網站圖片。當消息被證實為真&#xff0c;官網和項目的審核細…

PID 算法理解

PID 算法 使用環境&#xff1a;受到外界的影響不能按照理想狀態發展。如小車的速度不穩定的調節&#xff0c;盡快達到目標速度。 條件&#xff1a;閉環系統->有反饋 要求&#xff1a;快準狠 分類&#xff1a;位置式、增量式 增量式 輸入&#xff1a;前次速度、前前次速度、前…

C#字符串的基本操作

文章目錄簡介字符串判斷是否相等語法實例字符串比較大小語法實例判斷字符串變量是否包含指定字符或字符串語法實例查找字符串變量中指定字符或字符串出現的位置語法實例取子串語法實例插入子串語法實例刪除子串語法實例替換子串語法實例去除字符串空格語法實例博主寫作不容易&a…

C++利用SOCKET傳送文件

C利用SOCKET傳送文件 /*server.h*/ #pragma comment(lib, "WS2_32") #include <WinSock2.h> #include <iostream> //#include <stdio.h> #include <assert.h> #ifndef COMMONDEF_H #define COMMONDEF_H #define MAX_PACKET_SIZE 10240 …

三種方式在CentOS 7搭建KVM虛擬化平臺

KVM 全稱是基于內核的虛擬機&#xff08;Kernel-based Virtual Machine&#xff09;&#xff0c;它是一個 Linux的一個內核模塊&#xff0c;該內核模塊使得 Linux變成了一個Hypervisor&#xff1a;它由 Quramnet開發&#xff0c;該公司于 2008年被 Red Hat 收購 KVM的整體結構&…

(五)EasyUI使用——datagrid數據表格

DataGrid以表格形式展示數據&#xff0c;并提供了豐富的選擇、排序、分組和編輯數據的功能支持。DataGrid的設計用于縮短開發時間&#xff0c;并且使開發人員不需要具備特定的知識。它是輕量級的且功能豐富。單元格合并、多列標題、凍結列和頁腳只是其中的一小部分功能。具體功…

拾取模型的原理及其在THREE.JS中的代碼實現

1. Three.js中的拾取 1.1. 從模型轉到屏幕上的過程說開 由于圖形顯示的基本單位是三角形&#xff0c;那就先從一個三角形從世界坐標轉到屏幕坐標說起&#xff0c;例如三角形abc 乘以模型視圖矩陣就進入了視點坐標系&#xff0c;其實就是相機所在的坐標系&#xff0c;如下圖&am…

StringBuilder-C#字符串對象

博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 在C# 中&#xff0c;string是引用類型&#xff0c;每次改變string類對象的值&#xff0c;即修改字符串變量對應的字符串&#xff0c;都需要在內存中為新的字符串重新分配空間。在默寫特定的情況…

java 19 - 11 異常的注意事項

1 /*2 * 異常注意事項:3 * A:子類重寫父類方法時&#xff0c;子類的方法必須拋出相同的異常或父類異常的子類。(父親壞了,兒子不能比父親更壞)4 * B:如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常5 * C:如果被重寫的…

數組去重的各種方式對比

數組去重&#xff0c;是一個老生常談的問題了&#xff0c;在各廠的面試中也會有所提及&#xff0c;接下來就來細數一下各種數組去重的方式吧&#xff1b; 對于以下各種方式都統一命名為 unique&#xff0c;公用代碼如下&#xff1a; // 生成一個包含100000個[0,50000)隨機數的數…

Linux平臺Makefile文件的編寫基礎篇和GCC參數詳解

問&#xff1a;gcc中的-I.是什么意思。。。。看到了有的是gcc -I. -I/usr/xxxxx..那個-I.是什么意思呢 最佳答案 答&#xff1a;-Ixxx 的意思是除了默認的頭文件搜索路徑(比如/usr/include等&#xff09;外&#xff0c;同時還在路徑xxx下搜索需要被引用的頭文件。 所以你的gcc …