在之前的文章Unity 3D Input System的使用-CSDN博客中,我介绍了如何用Input System来实现一个FPS游戏的移动控制,这里将进一步完善这个游戏。
以下是游戏的演示效果:
fps_demo
添加武器模型
首先是增加主角玩家的武器,我们可以在网上搜索到很多免费的3D资源,例如在以下网址可以下载到一个很不错的3D模型,里面包括了相关的动画。Animated Assault Rifle - Download Free 3D model by JUST (@teenjust500) [46a12c6] (sketchfab.com)
点击下载为FBX格式,并保存到本地。然后打开我们之前的Unity项目,新建一个models文件夹,把下载的3D模型的FBX文件以及相应的材质文件都放到这个目录下。 把这个模型拖动到Player的PlayerCameraRoot下,可以设置模型的scale以调整适合我们的场景。这里我设置的缩放比例是0.08。然后调整一下这个模型的位置,使得能在摄像机里面恰当的显示。点击Play按钮可以看看效果。
这个模型包括了一些动画场景,其中的Idle,Shoot和Reload是FPS中需要用到的。点击展开models里面的HandWithGloves模型,把其中的一个动画,例如Armature|Reload拖动到刚才创建的Game Object,这样就会自动创建Animator,把idle, reload和shoot这三个动画拖动到Animator,然后创建transition,如下图:
在Animator的Parameters里面,新增两个Trigger类型的参数,分别为Reload和Shoot,再增加一个IsReload的Bool类型参数。然后点击从Any State切换到Reload State的线段,在Condition里面选择Reload。点击从Any State切换到Shoot State的线段,在Condition里面选择Shoot以及IsReload为false。
点击Reload这个State,然后添加一个Behavior Script,命名为ReloadControl,其代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ReloadControl : StateMachineBehaviour
{// OnStateEnter is called when a transition starts and the state machine starts to evaluate this stateoverride public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex){animator.SetBool("IsReload", true);}// OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks//override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)//{// //}// OnStateExit is called when a transition ends and the state machine finishes evaluating this stateoverride public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex){animator.SetBool("IsReload", false);}// OnStateMove is called right after Animator.OnAnimatorMove()//override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)//{// // Implement code that processes and affects root motion//}// OnStateIK is called right after Animator.OnAnimatorIK()//override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)//{// // Implement code that sets up animation IK (inverse kinematics)//}
}
增加Input Action
在项目的Assets->Input目录下,点击之前创建的PlayerInputAsset,增加一个Reload Action,Type是Button,然后添加一个Binding绑定到键盘的R键。增加一个Shoot Action,Type也是Button,Interactions里面增加一个Press,Trigger Behavior设置为Press Only,然后绑定到鼠标的左键。增加一个Shoot Release Action,Type也是Button,Interactions里面增加一个Press,Trigger Behavior设置为Release Only,也是绑定到鼠标的左键。
打开PlayerInputAsset这个脚本文件,在里面增加以下代码:
public bool reload;public bool shoot;public long shootPressTS = 0;public bool firstShoot;public void OnShoot(InputValue value) {shoot = true;if (shootPressTS==0) {firstShoot = true;} else {firstShoot = false;}shootPressTS = DateTime.UtcNow.Ticks;}public void OnShootRelease(InputValue value) {shoot = false;shootPressTS = 0;