*@2019072103d *
1.导入所需的资源
链接:https://pan.baidu.com/s/1kLnu28aPiZ7ak6j4rADqsw 提取码:m71u
2.项目开发
2.1标签的封装
创建一个名为Tags的脚本,将项目中所有将要使用的标签以const常量的方式进行分装。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tags{
public const string player = "Player";//代表玩家
public const string gameController = "GameController";//代表游戏控制器
public const string enemy = "Enemy";//代表敌人
public const string fader = "Fader";//代表淡入淡出的画布
public const string mainCamera = "MainCamera";//代表主摄像机
}
2.2实现屏幕淡入淡出的效果
1.在场景面板中创建一个空物体,命名为FadeInOut,加入组件GUI Texture,color设置为黑色,Texture设置为swatch_black_dff(在导入的资源中搜索)
2.为物体FadeInOut创建一个脚本FadeInOut用来实现屏幕的渐隐渐现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;//SceneManager使用的命名空间
public class FadeInOut : MonoBehaviour
{
public float fadeSpeed = 1.5f;//设置渐隐渐现的速度
private bool sceneStarting = true;//设置场景开始,当场景开始时实现渐隐渐现的效果
private GUITexture tex;//设置一个GUITexture类型的组件名为tex
private void Start()
{
tex = this.GetComponent<GUITexture>();//给组件进行赋值
tex.pixelInset = new Rect(0, 0, Screen.width, Screen.height);//给组件初始化,位置为0,0,大小和屏幕一致
}
private void Update()
{
if (sceneStarting)
{
StartScene();//实现场景的渐现
}
}
private void FadeToClear()//实现渐现
{
tex.color = Color.Lerp(tex.color, Color.clear, fadeSpeed * Time.deltaTime);//fadeSpeed * Time.deltaTime表示速度
}
private void FadeToBlack()//实现渐隐
{
tex.color = Color.Lerp(tex.color, Color.black, fadeSpeed * Time.deltaTime);//tex.color表示当前的颜色,Color.black表示渐变后的颜色
}
private void StartScene()//渐现开始
{
FadeToClear();//场景开始实现渐现效果
if (tex.color.a <= 0.05f)//判断是否变为透明
{
tex.color = Color.clear;//将当前的颜色变为彻底透明
tex.enabled = false;//禁用GUI组件
sceneStarting = true;//将标识位设置为false
}
}
public void EndScene()//渐隐开始
{
tex.enabled = true;
FadeToBlack();
if (tex.color.a >= 0.95f)
{
SceneManager.LoadScene("Demo");//进行场景跳转到当前场景,进行重复加载
}
}
}
2.3按键输入封装
在场景面板中创建一个空物体,命名为GameController,将其Tag设置为GameController,同时设置脚本fps_Input
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class fps_Input : MonoBehaviour {
public class fps_InputAxis//自定义轴辅助类,存储自定义轴的信息
{
public KeyCode positive;//定义一个正向按键
public KeyCode negative;//定义一个负向按键
}
public Dictionary<string, KeyCode> buttons = new Dictionary<string, KeyCode>();//定义一个集合
public Dictionary<string, fps_InputAxis> axis = new Dictionary<string, fps_InputAxis>();//定义一个自定义轴集合
public List<string> unityAxis = new List<string>();//定义一个unity内部轴的集合
private void Start()
{
SetupDefault();
}
private void SetupDefault(string type = "")//设置默认的按键,type中的内容表示你要设置什么类型的东西,是按钮类型的、自定义轴还是uinty默认自带的轴
{
if(type == ""||type == "buttons")
{
if (buttons.Count == 0)//说明按钮没有进行过初始化
{
AddButton("Fire", KeyCode.Mouse0);//鼠标左键设置为开火键
AddButton("Reload", KeyCode.R);
AddButton("Jump", KeyCode.Space);
AddButton("Crouch", KeyCode.C);//蹲下按键
AddButton("Sprint", KeyCode.LeftShift);//加速按键
}
}
if (type == "" || type == "Axis")//初始化自定义轴
{
if (axis.Count == 0)
{
AddAxis("Horizontal", KeyCode.W, KeyCode.S);
AddAxis("Vertical", KeyCode.A, KeyCode.D);
}
}
if (type == "" || type == "UnityAxis")//初始化unity自定义的轴
{
if (unityAxis.Count == 0)
{
AddUnityAxis("Mouse X");
AddUnityAxis("Mouse Y");
AddUnityAxis("Horizontal");
AddUnityAxis("Vertical");
}
}
}
public void AddButton(string n,KeyCode k)//添加按钮的方法,两个参数表示按钮的名称和键位
{
if (buttons.ContainsKey(n))//判断按钮按键集合中是否包含该按钮
buttons[n] = k;//包含则加入键位
else
buttons.Add(n, k);//不包含则加入这个按钮和键位
}
private void AddAxis(string n,KeyCode pk,KeyCode nk)//添加自定义轴的方法,三个参数代表自定义轴的名称,正方向和负方向
{
if (axis.ContainsKey(n))
{
axis[n] = new fps_InputAxis() { positive = pk, negative = nk };
}
else
{
axis.Add(n, new fps_InputAxis() { positive = pk, negative = nk });
}
}
private void AddUnityAxis(string n)//添加unity自定义轴的方法
{
if (!unityAxis.Contains(n))
{
unityAxis.Add(n);
}
}
//外界获取调用的方法
public bool GetButton(string button)
{
if (buttons.ContainsKey(button))
{
return Input.GetKey(buttons[button]);//外界获取按钮的方法,只要按键没有被抬起就一直调用
}
return false;
}
public bool GetButtonDown(string button)
{
if (buttons.ContainsKey(button))
{
return Input.GetKeyDown(buttons[button]);//外界获取按钮按下的方法
}
return false;
}
public float GetAxis(string axis)//轴返回的值在-1到1之间,外界获取自定义轴的方法
{
if (this.unityAxis.Contains(axis))
{
return Input.GetAxis(axis);
}
else
return 0;
}
public float GetAxisRaw(string axis)//这里只返回三个值,-1,0,1
{
if (this.axis.ContainsKey(axis))//判断自定义轴是否包含这个轴
{
float val = 0;
if (Input.GetKey(this.axis[axis].positive))
return 1;//按下正向键返回1
if (Input.GetKey(this.axis[axis].negative))
return -1;
return val;
}
else if (unityAxis.Contains(axis))//如果自定义的轴不包含这个轴,就去unity自定义的轴去找
{
return Input.GetAxisRaw(axis);
}
else//都没有找到该轴
{
return 0;
}
}
}
2.4用户输入的参数封装及赋值
1.创建一个空物体,作为我们的主角,重命名为FP_Player,将其位置设置为X:16.44,Z:-45.65,加入一个组件character controller(角色控制器),将参数Center中的Y改为1,Radius改为0.4,后期所有的主角行为都通过角色控制器来操作。
2.书写一个脚本表示用户的输入状态,命名为fps_PlayerParameter,将脚本拖动到FP_Player中
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class fps_PlayerParameter : MonoBehaviour
{
[HideInInspector]//以下操作是通过用户的输入来操作,不需要显示在用户面板中,因此就隐藏属性
public Vector2 inputSmoothLook;//定义一个二维向量表示鼠标的输入
[HideInInspector]
public Vector2 inputMoveVector;//定义一个二维向量表示按键的输入
[HideInInspector]
public bool inputCrouch;//是否下蹲
[HideInInspector]
public bool inputJump;//是否跳跃
[HideInInspector]
public bool inputSprint;//是否冲刺
[HideInInspector]
public bool inputFire;//是否开火
[HideInInspector]
public bool inputReload;//是否装弹
}
3.创建一个脚本,为上述定义的变量进行赋值,命名为fps_FPInput,拖动到FP_Player中
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class fps_FPInput : MonoBehaviour
{
public bool LockCursor//由于是第一人称视角,不需要显示光标,锁定光标
{
get { return Cursor.lockState == CursorLockMode.Locked ? true : false; }//锁定返回true,反则返回false
set
{
Cursor.visible = value;//设定一个鼠标可见的变量
Cursor.lockState = value ? CursorLockMode.Locked : CursorLockMode.None;
}
}
private fps_PlayerParameter parameter;//给脚本的参数进行赋值
private fps_Input input;
void Start()
{
LockCursor = true;
parameter = this.GetComponent<fps_PlayerParameter>();//赋值parameter,通过该脚本所在物体中找到组件fps_PlayerParameter
input = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<fps_Input>();//赋值input,通过游戏物体的标签区寻找组件fps_Input
}
private void Update()
{
InitialInput();
}
private void InitialInput()//对变量进行赋值
{
parameter.inputMoveVector = new Vector2(input.GetAxis("Horizontal"), input.GetAxis("Vertical"));
parameter.inputSmoothLook = new Vector2(input.GetAxisRaw("Mouse X"), input.GetAxisRaw("Mouse Y"));//通过鼠标控制相机进行旋转来达到视觉旋转的特效
parameter.inputCrouch = input.GetButton("Crouch");
parameter.inputJump = input.GetButton("Jump");
parameter.inputFire = input.GetButton("Fire");
parameter.inputSprint = input.GetButton("Sprint");
parameter.inputReload = input.GetButton("Reload");
}
}
2.5第一人称相机控制
创建一个相机,标签命名为MainCamera,相机命名为FP_Camera,将其设置为FP_Player的子目录,为其新建一个脚本fps_FPCamera
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Camera))]//针对相机的操纵
public class fps_FPCamera : MonoBehaviour {
public Vector2 mouseLookSensitivity = new Vector2(5, 5);//调整鼠标灵敏度
public Vector2 rotationXLimit = new Vector2(87, -87);//相机旋转的垂直方向的角度范围
public Vector2 rotationYLimit = new Vector2(-360, 360);//相机旋转的水平方向的角度范围
public Vector3 positionOffset = new Vector3(0, 2,-0.2f);//
private Vector2 currentMouseLook = Vector2.zero;
private float x_Angle = 0;//x轴旋转角度默认为0
private float y_Angle = 0;
private fps_PlayerParameter parameter;//获取鼠标的输入
private Transform m_Transform;//避免重复调用
private void Start()
{
parameter = GameObject.FindGameObjectWithTag(Tags.player).GetComponent<fps_PlayerParameter>();
m_Transform = transform;
m_Transform.localPosition = positionOffset;
}
private void Update()
{
UpdateInput();
}
private void LateUpdate()//旋转处理
{
Quaternion xQuaternion = Quaternion.AngleAxis(y_Angle, Vector3.up);//对应y轴的旋转
Quaternion yQuaternino = Quaternion.AngleAxis(0, Vector3.left);//对应x轴的旋转
m_Transform.parent.rotation = xQuaternion * yQuaternino;
yQuaternino = Quaternion.AngleAxis(-x_Angle, Vector3.left);
m_Transform.rotation = xQuaternion * yQuaternino;
}
private void UpdateInput()
{
if (parameter.inputSmoothLook == Vector2.zero)//表示没有用户输入
return;
GetMouseLock();//用户有输入获取用户输入
y_Angle += currentMouseLook.x;//前者的y表示y轴的旋转,后者的x表示鼠标的输入轴向,鼠标的轴向对应视图中y轴的旋转
x_Angle += currentMouseLook.y;
y_Angle = y_Angle < -360 ? y_Angle += 360 : y_Angle;
y_Angle = y_Angle > 360 ? y_Angle -= 360 : y_Angle;//保证y轴的旋转保持在一定范围内
y_Angle = Mathf.Clamp(y_Angle, rotationYLimit.x, rotationYLimit.y);//
x_Angle = x_Angle < -360 ? x_Angle += 360 : x_Angle;
x_Angle = x_Angle > 360 ? x_Angle -= 360 : x_Angle;
x_Angle = Mathf.Clamp(x_Angle, -rotationXLimit.x, -rotationXLimit.y);
}
private void GetMouseLock (){//对用户输入进行处理
currentMouseLook.x = parameter.inputSmoothLook.x;
currentMouseLook.y = parameter.inputSmoothLook.y;
currentMouseLook.x *= mouseLookSensitivity.x;
currentMouseLook.y *= mouseLookSensitivity.y;
currentMouseLook.y *= -1;//修改y轴的方向
}
}
2.6角色控制参数的定义
在FP_Player物体下新建一个脚本fps_PlayerControl,用来控制角色参数的定义
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum PlayerState//设立枚举表示玩家的状态
{
None,//无状态
Idle,//站立状态
Walk,//行走状态
Crouch,//蹲伏状态
Run,//行走状态
}
public class fps_PlayerControl : MonoBehaviour {
private PlayerState state = PlayerState.None;//设置默认状态为无状态
public float sprintSpeed = 10.0f;//设置冲刺状态的相关速度
public float sprintJumpSpeed = 8.0f;
public float normalSpeed = 6.0f;//设置正常状态下的相关速度
public float normalJumpSpeed = 7.0f;
public float crouchSpeed = 2.0f;
public float crouchJumpSpeed = 5.0f;
public float crouchDeltaHeight = 0.5f;//定义玩家蹲伏的时候下降的高度
public float gravity = 20.0f;//定义一个重力加速度
public float cameraMoveSpheed = 8.0f;
public AudioClip jumpAudio;
private float speed;//代表玩家当前的速度
private float jumpSpeed;
private Transform mainCamera;//代表相机
private float standardCamHeight;//存储相机的标准高度
private float crouchingCamHeight;//存储蹲伏时相机的高度
private bool grounded = false;//表示玩家是否在地面
private bool walking = false;
private bool crouching = false;
private bool stopCrouching = false;
private bool runing = false;
private Vector3 normalControllerCenter = Vector3.zero;
private float normalControllerHeight = 0.0f;
private float timer = 0;//计时器默认为零
private CharacterController controller;
private AudioSource audioSource;//播放角色的脚步声
private fps_PlayerParameter parameter;
}
在物体FP_Player中新建一个组件Audio Source,同时在将工程面板下的Audio文件夹下的FootstepRock05拖动到AudioClip中,同时将JumpGeneric拖动到fps_PlayerControl的Junp Audio中