文章目錄
- 一,什么是FPS游戲
- 二,功能實作思路與程序
- (1)新建角色
- (2)實作移動功能的思路
- (3)實作旋轉功能的思路
- (4)實作推進上升功能的思路
- (5)具體代碼
- (5)腳本的使用方法
- (6)最終效果
一,什么是FPS游戲
第一人稱射擊類游戲,FPS(First-person shooting game), 嚴格來說第一人稱射擊游戲屬于ACT類游戲的一個分支,但和RTS類游戲一樣,由于其在世界上的迅速風靡,使之發展成了一個單獨的型別,
FPS(First-person Shooting game)第一人稱視角射擊游戲顧名思義就是以玩家的主觀視角來進行射擊游戲,玩家們不再像別的游戲一樣操縱螢屏中的虛擬人物來進行游戲,而是身臨其境的體驗游戲帶來的視覺沖擊,這就大大增強了游戲的主動性和真實感,早期第一人稱類游戲所帶給玩家的一般都是的螢屏光線的刺激,簡單快捷的游戲節奏,隨著游戲硬體的逐步完善,以及各種游戲的不斷結合,第一人稱射擊類游戲提供了更加豐富的劇情以及精美的畫面和生動的音效,
二,功能實作思路與程序
(1)新建角色
新建專案,載入或者新建角色模型與槍械模型,另外,由于專案視角是第一人稱,所以建議將槍械設為攝像頭的子物體,并為了以后的對戰功能的開發,同樣建議將完成之后的角色模型集合以預制體的方式保存,完成之后的效果圖如下

(2)實作移動功能的思路
要實作鍵盤輸入控制移動功能,首先必須對鍵盤的輸入進行實時獲取,獲取的方法,是在腳本的Update()中進行獲取(PS:Update(): 當游戲正在運行,同時腳本是可用的,這個方法會在每幀重繪時呼叫),獲取用戶的輸入,得到用戶移動矢量的模(移動矢量的模即移動距離),
/**獲取用戶移動矢量的模的代碼如下**/
float _xMov = Input.GetAxisRaw("Horizontal");//獲取水平方向輸入
float _zMov = Input.GetAxisRaw("Vertical");//獲取垂直方向輸入
再乘以用戶移動矢量的標準矢量(PS:transform.right,transform.forward本質為標準矢量,且根據矢量的概念,一個非零矢量除以它的模,可得所需標準矢量,從而反推移動矢量的標準矢量乘以移動矢量的模可得出移動矢量),獲取移動矢量,考慮到玩家的移動受垂直與水平兩個移動矢量的影響,玩家運動的簡易模型如下圖

根據矢量三角形法則可知,玩家移動矢量等于水平矢量+垂直矢量(法則簡略圖如下)

/**水平矢量,垂直矢量與玩家移動矢量的計算代碼如下**/
Vector3 _moveHoruzontal = transform.right * _xMov;//水平移動矢量=水平方向標準矢量*水平方向移動矢量的模(鍵盤水平方向輸入)
Vector3 _moveVertical = transform.forward * _zMov;//垂直移動矢量=垂直方向標準矢量*垂直方向移動矢量的模(鍵盤垂直方向輸入)
Vector3 _velocity = (_moveHoruzontal + _moveVertical).normalized * speed;//將玩家移動矢量歸一化為標準矢量,在乘以
然后將玩家移動矢量歸一化(normalized)為標準矢量,在將歸一化的標準矢量乘以速度矢量的模,獲取玩家速度矢量,最后將速度矢量乘以時間加上當前玩家剛體的位置,得出玩家最后應該移動到的位置,
(3)實作旋轉功能的思路
同理在腳本的Update()中進行獲取用戶的滑鼠輸入,將獲取的滑鼠X,Y軸移動角度乘以用戶視野旋轉速度,得到攝像頭與玩家剛體旋轉角度
(4)實作推進上升功能的思路
同理在腳本的Update()中進行獲取用戶的鍵盤輸入,當監聽到用戶輸入空格的時候,讓角色剛體像正上方移動,
(5)具體代碼
PlayerMoter.cs(代碼如下)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMoter : MonoBehaviour
{
[SerializeField]
private Camera cam;//攝像頭
private Vector3 velocity = Vector3.zero;
private Vector3 rotation = Vector3.zero;
private float cameraRotationX = 0f;
private float currentCamerRotationX = 0f;
private Vector3 thrusterForce = Vector3.zero;
[SerializeField]
private float cameraRotationLimit = 85f;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();//獲取剛體
}
public void Move(Vector3 _velocity)//移動
{
velocity = _velocity;
}
public void Rotate(Vector3 _rotation)//旋轉
{
rotation = _rotation;
}
// Update is called once per frame
void Update()
{
}
private void FixedUpdate()
{
PerformMovement();
PeformRotation();
}
public void RotarCamera(float _cameraRotation)//攝像頭旋轉
{
cameraRotationX = _cameraRotation;
}
public void ApplyThruster(Vector3 _thrusterForce)//應用推進力
{
thrusterForce = _thrusterForce;
}
void PerformMovement()//移動
{
if(velocity!=Vector3.zero)
{
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);//
}
if(thrusterForce!=Vector3.zero)
{
rb.AddForce(thrusterForce * Time.fixedDeltaTime,ForceMode.Acceleration);
}
}
void PeformRotation()//旋轉
{
rb.MoveRotation(rb.rotation * Quaternion.Euler(rotation));
if(cam!=null)
{
currentCamerRotationX -= cameraRotationX;
currentCamerRotationX = Mathf.Clamp(currentCamerRotationX,-cameraRotationLimit,cameraRotationLimit);
cam.transform.localEulerAngles = new Vector3(currentCamerRotationX, 0f, 0f);
}
}
}
PlayerControl.cs(代碼如下)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(ConfigurableJoint))]
[RequireComponent(typeof(PlayerMoter))]
public class PlayerControl : MonoBehaviour
{
[SerializeField]
private float speed = 5f;
private PlayerMoter moter;
[SerializeField]
private float lookSensitivity = 3f;//視角旋轉速度
[SerializeField]
private float thrustserForce = 1000f;//推進速度
[Header("Spring setting")]
[SerializeField]
private JointDriveMode jointMode=JointDriveMode.Position;
[SerializeField]
private float jointSpring = 20f;
[SerializeField]
private float jointMaxForce = 40f;
private PlayerMoter motor;
private ConfigurableJoint joint;
// Start is called before the first frame update
void Start()
{
moter = GetComponent<PlayerMoter>();
joint = GetComponent<ConfigurableJoint>();
}
// Update is called once per frame
void Update()
{
float _xMov = Input.GetAxisRaw("Horizontal");//獲取水平方向輸入
float _zMov = Input.GetAxisRaw("Vertical");//獲取垂直方向輸入
//transform.right,transform.forward本質為標準矢量,即有方向且模為1的矢量
Vector3 _moveHoruzontal = transform.right * _xMov;//水平移動矢量=水平方向標準矢量*水平方向移動矢量的模(鍵盤水平方向輸入)
Vector3 _moveVertical = transform.forward * _zMov;//垂直移動矢量=垂直方向標準矢量*垂直方向移動矢量的模(鍵盤垂直方向輸入)
Vector3 _velocity = (_moveHoruzontal + _moveVertical).normalized * speed;//將玩家移動矢量歸一化為標準矢量,在乘以
moter.Move(_velocity);
float _yRot = Input.GetAxisRaw("Mouse X");//獲取滑鼠X軸移動
Vector3 _rotation = new Vector3(0f, _yRot, 0f) * lookSensitivity;
moter.Rotate(_rotation);
float _xRot = Input.GetAxis("Mouse Y");//獲取滑鼠Y軸移動
float _cameraRotation = _xRot * lookSensitivity;
moter.RotarCamera(_cameraRotation);
Vector3 _thrusterForce = Vector3.zero;
if(Input.GetButton("Jump"))
{
_thrusterForce = Vector3.up * thrustserForce;//
SetJointSettings(0f);
}
else
{
SetJointSettings(jointSpring);
}
moter.ApplyThruster(_thrusterForce);
}
private void SetJointSettings(float _jointSpring)
{
joint.yDrive = new JointDrive {
mode = jointMode,
positionSpring= _jointSpring,
maximumForce=jointMaxForce
};
}
}
PlayerScript.cs(代碼如下)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerScript : MonoBehaviour
{
private const int Player_Up = 0;
private const int Player_Right = 1;
private const int Player_Down = 2;
private const int Player_Left = 3;
private int state = 0;
public int moveSpeed = 2;
void Awake()
{
state = Player_Up;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
float KeyVertical = Input.GetAxis("Vertical");
float KeyHorizontal = Input.GetAxis("Horizontal");
if(KeyVertical==-1)
{
setPlayerState(Player_Down);
}
else if(KeyVertical==1)
{
setPlayerState(Player_Up);
}
if(KeyHorizontal==1)
{
setPlayerState(Player_Right);
}
else if(KeyHorizontal==-1)
{
setPlayerState(Player_Left);
}
}
void setPlayerState(int NewState)
{
int rotateValue = (NewState - state) * 90;
Vector3 transformValue = new Vector3();
switch(NewState)
{
case Player_Up:
transformValue = Vector3.forward * Time.deltaTime;
break;
case Player_Down:
transformValue = (-Vector3.forward) * Time.deltaTime;
break;
case Player_Left:
transformValue = Vector3.left * Time.deltaTime;
break;
case Player_Right:
transformValue = (-Vector3.left) * Time.deltaTime;
break;
}
transform.Rotate(Vector3.up, rotateValue);
transform.Translate(transformValue * moveSpeed, Space.World);
state = NewState;
}
}
(5)腳本的使用方法
將PlayerScript.cs與PlayerControl.cs系結在玩家角色物件上,并給PlayerControl腳本系結攝像頭(如下圖)

(6)最終效果

【1】參考教程 https://www.bilibili.com/video/BV1Hz4y1R7ZY
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/287695.html
標籤:其他
