unity官方教程TANKS,難度系數中階。
跟著官方教程學習Unity,通過本教程你可以學會使用Unity開發游戲的基本流程。
一、環境
Unity 版本 > 5.2
Asset Store 里面搜索 Tanks!Tutorial ,下載導入
二、項目設置
為了便于開發,很多時候我們選用的窗口布局是 2by3 Layout,然后將 Project 面板拖動到 Hierarchy 面板下面,如下圖所示
三、場景設置
項目設置完畢后,就進入場景設置環節
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 中
3、保存場景,點擊 Play 試玩一下
通過今天的教程,你可以學會
- 場景設置,基本的物體操作
- 編程控制物體移動
下期教程繼續。。。