通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!

  • 博客主页:https://blog.csdn.net/zhangay1998
  • 欢迎点赞 收藏 ⭐留言 如有错误敬请指正!
  • 本文由 God Y.原创,首发于 CSDN
  • 未来很长,值得我们全力奔赴更美好美好的生活✨

目录

      • 引言
  • 通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,憨憨学妹都学会了!
    • 导入一个资源包
    • 第一人称视角控制、人物自由移动和移动声音控制
        • Unity场景设置
        • 脚本控制
    • 枪械开火、换弹、换枪动画设置
    • 枪械开火、换弹、换枪脚本实现
    • ⭐️枪械开火特效设置
    • ✨游戏展示
  • 总结


引言

  • ☔️上海已经入梅,小雨蒙蒙笼罩了整个上海。
  • 窗外雨声滴滴答,室内键盘咔咔咔。
  • 正在无聊的时候呢,之前的学妹小云儿发来了消息~
  • 小云儿:学长哥哥,上次看完你的打飞机游戏,发现我差不多学会了哎~
  • 小Y(博主):那挺好呀,可以跟你的小姐妹们一起玩打飞机游戏了~
  • 小云儿:打飞机我们已经玩腻啦,想玩一款真正的射击游戏~就像CS那样刺激的啦!
  • 小Y:emm…你倒是挺喜欢玩刺激的哈~
  • 小云儿:嘿嘿~哥哥你不是说下次带人家玩更刺激的嘛,我这就来找你啦!
  • 小Y:好伐,但是一口气吃不成胖子,我现在先教你使用动画系统实现CS中的一些基本游戏操作,比- 如开枪、换枪、开火和换弹药等操作~
  • 小云儿:好咧哥哥,我小脑袋瓜本来也不够灵光,学这些正好!
  • 小Y:好咧,上一篇文章已经对Unity的动画基础做介绍了,现在我们就开始动手吧!
  • 小云儿:好咧哥哥,动手可以,不阔以动脚哦!


通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,憨憨学妹都学会了!

导入一个资源包

  • 小Y:话说小云儿,我上一篇文章介绍[Unity中的动画系统]你有认真看完一遍嘛?
  • 小云儿:看完啦,小Y哥哥~ 就是有的地方还没有太明白~
  • 小Y:那正好,借助制作这个游戏能让你对Unity的动画有一个更深刻的认识!
  • 小云儿:好呀好呀~
  • 小Y:第一步要新建一个工程,然后才能正式开始!
  • 小云儿:哎呀,小Y哥哥 这个我都会了,这么简单就不用再介绍啦~
  • 小Y:猴急猴急的呢,咱们慢慢来~

既然想要做一个CS那样的射击游戏,场景跟模型肯定得有啊
我们这就来导入一个简单的资源包,里面有简单的一个场景和几把枪械
通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第1张图片

  • 小云儿:场景和枪械都有啦,接下来该写脚本了吧?
  • 我:是的呢,小云儿你变聪明了!
  • 小云儿:哼唧,跟着哥哥学必须变聪明!

第一人称视角控制、人物自由移动和移动声音控制

  • 小Y:那第一步就是写一个挂在人物身上的脚本,让角色可以自由移动。
  • 小云儿:好啊,先让角色动起来~
  • 小Y:还要加上第一人称视角控制,这样才有CS的既视感
  • 小云儿:对的对的,如果能给人物移动加上声音就更好了
  • 小Y:没错,还要给人物移动,奔跑和跳跃加上声音,这样就更有感觉了!

Unity场景设置

  • 首先,我们在场景中新建一个游戏对象GameObject,将其改名为FPSController

  • 然后给他添加上角色控制器Character ControllerAudio Source

  • 角色控制器Character Controller可以更容易的处理有碰撞的运动

  • Audio SourceUnity 中的 Audio 组件,其主要用来播放游戏场景中的 - AudioClipAudioClip 就是导入到 Unity 中的声音文件。

  • 其次,将场景中默认创建的Camera删掉或者取消激活,我们这里会自己新建一个Camera使用,所以暂时用不到这个默认的相机

  • 在这个游戏对象下再新建一个GameObject,改名为FirstPersonCharacter,给他添加上CameraAudioListener组件

  • 这个Camera就是我们能看到的第一视角,AudioListener是游戏中的声音接收器,用来接收场景中的声音,一般都挂在相机上

脚本控制

  • 主要是控制人物的行走、移动、跳跃

  • 还有人物身上的一些声音的控制

  • 定义一个值用来声明人物是否是行走状态,再定义两个参数分别用来用来处理移动速度和奔跑速度

  • 然后还有对第一人称视角的控制

  • 以及几个声音数组,用来控制人物行走,奔跑和跳跃的不同声音

  • 这块地方实现的方法有好多种,所以这里只是提供一种方法作为参考

  • 这里写的有点多,嫌麻烦的可直接复制这个脚本的代码挂在我们的FPSController身上即可

直接上代码,挂载到我们的角色控制器FPSController上就行

using System;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
using UnityStandardAssets.Utility;
using Random = UnityEngine.Random;

namespace UnityStandardAssets.Characters.FirstPerson
{
     
    [RequireComponent(typeof (CharacterController))]
    [RequireComponent(typeof (AudioSource))]
    public class FirstPersonController : MonoBehaviour
    {
     
        [SerializeField] private bool m_IsWalking;
        [SerializeField] private float m_WalkSpeed;
        [SerializeField] private float m_RunSpeed;
        [SerializeField] [Range(0f, 1f)] private float m_RunstepLenghten;
        [SerializeField] private float m_JumpSpeed;
        [SerializeField] private float m_StickToGroundForce;
        [SerializeField] private float m_GravityMultiplier;
        [SerializeField] private MouseLook m_MouseLook;
        [SerializeField] private bool m_UseFovKick;
        [SerializeField] private FOVKick m_FovKick = new FOVKick();
        [SerializeField] private bool m_UseHeadBob;
        [SerializeField] private CurveControlledBob m_HeadBob = new CurveControlledBob();
        [SerializeField] private LerpControlledBob m_JumpBob = new LerpControlledBob();
        [SerializeField] private float m_StepInterval;
        [SerializeField] private AudioClip[] m_FootstepSounds;    //从中随机选择的一组足迹声音。
        [SerializeField] private AudioClip m_JumpSound;           //角色离开地面时发出的声音。
        [SerializeField] private AudioClip m_LandSound;           //角色触地时播放的声音。

        private Camera m_Camera;
        private bool m_Jump;
        private float m_YRotation;
        private Vector2 m_Input;
        private Vector3 m_MoveDir = Vector3.zero;
        private CharacterController m_CharacterController;
        private CollisionFlags m_CollisionFlags;
        private bool m_PreviouslyGrounded;
        private Vector3 m_OriginalCameraPosition;
        private float m_StepCycle;
        private float m_NextStep;
        private bool m_Jumping;
        private AudioSource m_AudioSource;

        private void Start()
        {
     
            m_CharacterController = GetComponent<CharacterController>();
            m_Camera = Camera.main;
            m_OriginalCameraPosition = m_Camera.transform.localPosition;
            m_FovKick.Setup(m_Camera);
            m_HeadBob.Setup(m_Camera, m_StepInterval);
            m_StepCycle = 0f;
            m_NextStep = m_StepCycle/2f;
            m_Jumping = false;
            m_AudioSource = GetComponent<AudioSource>();
			m_MouseLook.Init(transform , m_Camera.transform);
        }

        private void Update()
        {
     
            RotateView();
            // 跳转状态需要在这里读取,以确保它不会丢失
            if (!m_Jump)
            {
     
                m_Jump = CrossPlatformInputManager.GetButtonDown("Jump");
            }

            if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
            {
     
                StartCoroutine(m_JumpBob.DoBobCycle());
                PlayLandingSound();
                m_MoveDir.y = 0f;
                m_Jumping = false;
            }
            if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
            {
     
                m_MoveDir.y = 0f;
            }
            m_PreviouslyGrounded = m_CharacterController.isGrounded;
        }
        private void PlayLandingSound()
        {
     
            m_AudioSource.clip = m_LandSound;
            m_AudioSource.Play();
            m_NextStep = m_StepCycle + .5f;
        }
        private void FixedUpdate()
        {
     
            float speed;
            GetInput(out speed);
            //始终沿着相机向前移动,因为这是它瞄准的方向
            Vector3 desiredMove = transform.forward*m_Input.y + transform.right*m_Input.x;

            //获取被接触曲面的法线以沿其移动
            RaycastHit hitInfo;
            Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down, out hitInfo,
                               m_CharacterController.height/2f, Physics.AllLayers, QueryTriggerInteraction.Ignore);
            desiredMove = Vector3.ProjectOnPlane(desiredMove, hitInfo.normal).normalized;

            m_MoveDir.x = desiredMove.x*speed;
            m_MoveDir.z = desiredMove.z*speed;


            if (m_CharacterController.isGrounded)
            {
     
                m_MoveDir.y = -m_StickToGroundForce;

                if (m_Jump)
                {
     
                    m_MoveDir.y = m_JumpSpeed;
                    PlayJumpSound();
                    m_Jump = false;
                    m_Jumping = true;
                }
            }
            else
            {
     
                m_MoveDir += Physics.gravity*m_GravityMultiplier*Time.fixedDeltaTime;
            }
            m_CollisionFlags = m_CharacterController.Move(m_MoveDir*Time.fixedDeltaTime);

            ProgressStepCycle(speed);
            UpdateCameraPosition(speed);

            m_MouseLook.UpdateCursorLock();
        }
        private void PlayJumpSound()
        {
     
            m_AudioSource.clip = m_JumpSound;
            m_AudioSource.Play();
        }
        private void ProgressStepCycle(float speed)
        {
     
            if (m_CharacterController.velocity.sqrMagnitude > 0 && (m_Input.x != 0 || m_Input.y != 0))
            {
     
                m_StepCycle += (m_CharacterController.velocity.magnitude + (speed*(m_IsWalking ? 1f : m_RunstepLenghten)))*
                             Time.fixedDeltaTime;
            }
            if (!(m_StepCycle > m_NextStep))
            {
     
                return;
            }
            m_NextStep = m_StepCycle + m_StepInterval;

            PlayFootStepAudio();
        }

        private void PlayFootStepAudio()
        {
     
            if (!m_CharacterController.isGrounded)
            {
     
                return;
            }
            // 从数组中拾取并播放随机的足迹声音,不包括索引0处的声音
            int n = Random.Range(1, m_FootstepSounds.Length);
            m_AudioSource.clip = m_FootstepSounds[n];
            m_AudioSource.PlayOneShot(m_AudioSource.clip);
            // 将拾取的声音移动到索引0,以便下次不再拾取
            m_FootstepSounds[n] = m_FootstepSounds[0];
            m_FootstepSounds[0] = m_AudioSource.clip;
        }

        private void UpdateCameraPosition(float speed)
        {
     
            Vector3 newCameraPosition;
            if (!m_UseHeadBob)
            {
     
                return;
            }
            if (m_CharacterController.velocity.magnitude > 0 && m_CharacterController.isGrounded)
            {
     
                m_Camera.transform.localPosition =
                    m_HeadBob.DoHeadBob(m_CharacterController.velocity.magnitude +
                                      (speed*(m_IsWalking ? 1f : m_RunstepLenghten)));
                newCameraPosition = m_Camera.transform.localPosition;
                newCameraPosition.y = m_Camera.transform.localPosition.y - m_JumpBob.Offset();
            }
            else
            {
     
                newCameraPosition = m_Camera.transform.localPosition;
                newCameraPosition.y = m_OriginalCameraPosition.y - m_JumpBob.Offset();
            }
            m_Camera.transform.localPosition = newCameraPosition;
        }


        private void GetInput(out float speed)
        {
     
            // Read input
            float horizontal = CrossPlatformInputManager.GetAxis("Horizontal");
            float vertical = CrossPlatformInputManager.GetAxis("Vertical");

            bool waswalking = m_IsWalking;

#if !MOBILE_INPUT
            // 在独立构建中,步行/跑步速度通过按键进行修改。
            //跟踪角色是在行走还是在跑步
                        m_IsWalking = !Input.GetKey(KeyCode.LeftShift);
#endif
            // set the desired speed to be walking or running
            speed = m_IsWalking ? m_WalkSpeed : m_RunSpeed;
            m_Input = new Vector2(horizontal, vertical);

            // 如果组合长度超过1,则规范化输入:
            if (m_Input.sqrMagnitude > 1)
            {
     
                m_Input.Normalize();
            }

            // 只有当运动员准备跑步、正在跑步并且要使用fovkick时,处理速度变化以提供fovkick
            if (m_IsWalking != waswalking && m_UseFovKick && m_CharacterController.velocity.sqrMagnitude > 0)
            {
     
                StopAllCoroutines();
                StartCoroutine(!m_IsWalking ? m_FovKick.FOVKickUp() : m_FovKick.FOVKickDown());
            }
        }


        private void RotateView()
        {
     
            m_MouseLook.LookRotation (transform, m_Camera.transform);
        }


        private void OnControllerColliderHit(ControllerColliderHit hit)
        {
     
            Rigidbody body = hit.collider.attachedRigidbody;
            //如果角色在刚体上,不要移动刚体
            if (m_CollisionFlags == CollisionFlags.Below)
            {
     
                return;
            }

            if (body == null || body.isKinematic)
            {
     
                return;
            }
            body.AddForceAtPosition(m_CharacterController.velocity*0.1f, hit.point, ForceMode.Impulse);
        }
    }
}


枪械开火、换弹、换枪动画设置

  • 小Y:角色的基本移动和视角切换有了,那接下来就是对枪械进行动画设置了,接下来是重点,你可要好好听哦!
  • 小云儿:那必须的,小Y哥哥说的话我都要认真听!

在这个资源包中已经有基本的动画片段了,如下图,我们要做的就是使用Animation Controller将动画片段控制起来
通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第2张图片

拿MP5举例,看一下动画片段

通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第3张图片

动画控制值Animator配置

这里我们先来给神器AK47(阿卡47)来进行动画配置
点开这个
Animation Controller
就是这个默认界面
通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第4张图片

  • 然后将AK47的动画片段直接拖进去,分别是默认动画、开火动画和换弹动画
  • 然后新建两个Trigger类型的过度参数,因为我们的开火和换弹都是点击触发的,类似开关,所以这里选择使用Trigger,其实使用Bool也可以。这里只是提供一方法。
    如下图:
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第5张图片
  • 然后将过度参数,分别添加到对应的箭头上
  • 还要注意将过度参数从Normal向其他两个动画过度时,将这个Has Exit Time 参数取消勾选,上篇文章动画基础也介绍过了
  • 还没有理解的可以去上一篇文章看一下哦,把链接摆在这了,嘿嘿
    Unity零基础到进阶 ☀️| 近万字教程 对 Unity 中的 动画系统基础 全面解析+实战演练

通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第6张图片

  • 这里一同样的方式来给MP5喷子设置上动画控制器,方法都是一样的

  • 先添加动画过度参数,然后点击小箭头,将动画过度的条件添加上,Has Exit Time 参数配置好
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第7张图片

  • 看一下过度的实际动画过度效果,这里可能不够明显,因为两个动画间并没有很大的差异:
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第8张图片

  • 小云儿:小Y哥哥,这样动画控制器就配置好啦,接下来就是使用代码和实现动画的调用了对叭!

  • 小Y:没错,因为动画片段都是现成的,我们只需要把这个动画控制器 Animation Controller做好就可以了,是不是很简单呢~

  • 小云儿:动画很流畅,就是这个开火换弹太慢了,我想枪射的更快一点,有什么办法解决吗?

  • 小Y:Emma…有办法的!简单给你说一下,但是射太快也有缺点哦,就是子弹浪费的太快了哈哈~

我们在这个动画窗口中选择对应的动画状态,然后右面的属性面板中有一个Speed属性

从名字就可以知道他是控制动画的播放速度的,所以我们在这里将速度的值改的越大,它播放的速度就越快,那我们的换弹速度就会更快啦!
通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第9张图片


枪械开火、换弹、换枪脚本实现

  • 小Y:这里要进行代码编写控制动画了,你可要好好听哦!
  • 小云儿:好咧,小Y哥哥~ 我会做认真听讲的好孩子的!

其实这一块也很简单
我们首先在FPSController下新建一个GameObject,改名为:GunMansger
然后将AK47MP5喷子这三把枪的预制体拖到这个GunMansger下,并根据摄像机视角调整好视角。

我们这里只演示这三把枪,其实再多也一样,就是体力活啦~
如下图所示:

将三把枪的位置和视角都调整好之后,就开始上代码了

  • 首先 ,写一个挂在每个枪械上的脚本FPSGun,用于控制开火和换枪,包括动画和声音的播放
    代码很简单,先在Awake中找到挂载该脚本的游戏对象身上的Animator组件

  • OnEnable中播放readyClip音频,readyClip是切换到当前枪械时的声音
    然后定义了三个方法,分别是FireReloadSwitch,自然是开火、换弹和换枪的方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FPSGun : MonoBehaviour
{
     
    private Animator animator;

    public AudioClip fireClip;
    public AudioClip reloadClip;
    public AudioClip readyClip;

    private void Awake()
    {
     
        animator = GetComponent<Animator>();
    }
    private void OnEnable()
    {
     
        //播放准备声音
        AudioSource.PlayClipAtPoint(readyClip,transform.position);
    }

    public void Fire()
    {
     
        //将开火名称转换为哈希
        int fire = Animator.StringToHash("Fire");
        //播放开火动画
        animator.SetTrigger(fire);
        //播放声音
        AudioSource.PlayClipAtPoint(fireClip ,transform.position);
    }
    public void Reload()
    {
     
        int reload = Animator.StringToHash("Reload");
        animator.SetTrigger(reload);
        //播放声音
        AudioSource.PlayClipAtPoint(reloadClip, transform.position);

    }
    public void Switch()
    {
     
        //播放声音
        AudioSource.PlayClipAtPoint(readyClip, transform.position);

    }
}

将对应的枪械声音添加到各自枪械身上:

通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第10张图片 通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第11张图片 通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第12张图片

然后是管理枪支的脚本GunManger,这个脚本挂在我们刚创建的游戏对象GunMansger身上

在这个脚本中,我们要做的事情也很简单
就是管理枪械的切换和控制开火换弹
FPSGun 脚本中我们之定义了方法,并没与调用,所以正是这个脚本中调用了

  1. 首先,在该脚本中声明一个列表List,用于管理枪械:private List managerdGuns;
  2. 然后再声明一个FPSGun类,用于拿到当前手持的枪械:private FPSGun currentGun;
  3. AwakeNew一个FPSGun列表
    然后在Start中写一个简单的For循环,将我们之前在游戏对象GunMansger下添加的三把枪全添加到列表中去
    并且在列表大于0的情况下,将第一把枪赋值给我们定义的currentGun
  4. 最后在Update中进行判断当前枪械不为空的情况下可以进行开火、换弹和换枪!

这里有个小细节就是一定要在Awake中创建列表,然后再Start中将枪械添加上去
因为AwakeStart都是在程序运行的第一帧运行,但是AwakeStart执行的早!

上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GunManger : MonoBehaviour
{
     
    //管理枪支
    private List<FPSGun> managerdGuns;
    //当前的枪支
    private FPSGun currentGun;
    //枪支编号
    private int index=0;

    private void Awake()
    {
     
        managerdGuns = new List<FPSGun>();
    }
    private void Start()
    {
     
        for (int i = 0; i < transform.childCount; i++)
        {
     
            //添加每一把枪
            managerdGuns.Add(transform.GetChild(i).GetComponent<FPSGun>());
        }
        if (managerdGuns.Count>0)
        {
     
            //当前先使用的第一把枪
            currentGun = managerdGuns[index];
        }
    }
    private void Update()
    {
     
        //当前是否有一把枪
        if (!currentGun)
        {
     
            return;
        }
        if (Input.GetButtonDown("Fire"))
        {
     
            currentGun.Fire();//开火
        }
        if (Input.GetButtonDown("Reload"))
        {
     
            currentGun.Reload();//换单
        }
        if (Input.GetButtonDown("Switch"))
        {
     
            currentGun.Switch();//换枪
            currentGun.gameObject.SetActive(false);

            //方法二
            //计算新枪的编号
            index = ++index % managerdGuns.Count;
            currentGun = managerdGuns[index];//更新当前枪支
            currentGun.gameObject.SetActive(true);//新枪
        }
    }
}
  • 这里要注意一下,我在脚本中写的这三个键盘输入还需要在Unity中设置一下:Edit -> Project Setting ->Input
  • 如下图设置,这样我们按下Q键就是换枪,R键就是换弹,鼠标左键就是开火,同步游戏设置~
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第13张图片
  • 小Y:好啦,一个控制枪械开火、换弹、换枪的脚本就算实现啦,是不是很简单呢!
  • 小云儿:Emma…不是很难,但是好像也并没有小Y哥哥你说的这么简单哦~
  • 小Y:哈哈,其实真的很简单啦,只是你还不熟练而已,多练几次就好啦!
  • 小云儿:好咧小Y哥哥
  • 小Y:还有最后一个开火特效小模块没有解决,我来给你演示一般怎么简单添加的添加一个特效!

⭐️枪械开火特效设置

让我们再来添加一个简单的开火特效吧!

  • 在资源包中有一个叫MuzzleFlash的预设体,他是一个简单的材质搭配了Shader做的,我们这里直接拿来用就好了

  • 添加一个特效也有很多种方法,我们这里采用一个超级简单的办法

  • 就是直接将这个预制体拖到枪械上,并摆放好合适的位置

如下图所示,直接放枪口处即可:

或者更夸张一点就下图这样,随便怎么高兴怎么设计,这就是自己开发游戏的快乐吧!

  • 然后我们在FPSGun脚本中添加两个方法,分别控制播放特效和取消特效:
   /// 
    /// 播放开火特效
    /// 
    public void PlayerFireEffect()
    {
     
        //启动特效
        muzzleFlash.SetActive(true);
        //0.2秒关闭
        Invoke("UnEffect", 0.1f);
    }
    /// 
    /// 取消特效
    /// 
    private void UnEffect()
    {
     
        muzzleFlash.SetActive(false);
    }
  • 然后新建一个脚本PlayerAudioAndEffect,这个脚本有点特殊,因为他不是挂在游戏对象身上的,而是挂在动画片段身上的,创建完脚本后会直接继承StateMachineBehaviour,然后会有几个override重写方法,我们只需要在OnStateEnter方法中使用即可
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第14张图片

  • 创建方法:要在Animator视窗中选中动画片段,然后Add Behaviour上去
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第15张图片

代码也很简单,获取到当前的动画,然后在播放动画的时候展示特效即可,声音也可以在这里设置:

using UnityEngine;

public class PlayerAudioAndEffect : StateMachineBehaviour
{
     
    public bool fire = true;
    public bool reload = true;

    // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateinfo, int layerindex)
    {
     
        FPSGun currentGun = animator.GetComponent<FPSGun>();
        if (fire)
        {
     
            //获取开火声音
            AudioClip fireClip = currentGun.fireClip;
            //播放
            AudioSource.PlayClipAtPoint(fireClip, animator.transform.position);
            //播放特效
            currentGun.PlayerFireEffect();

        }
        if (reload)
        {
     
            //获取换单声音
            AudioClip reloadClip = currentGun.reloadClip;
            //播放
            AudioSource.PlayClipAtPoint(reloadClip, animator.transform.position);
        }
    }
}

✨游戏展示

小Y:每当进行到这一步,就是我们最激动人心的时刻啦!
小云儿:是的呢 小Y哥哥,快来给我演示一下成果吧~
小Y:好咧!

动图演示

  • 因为有些小伙伴懒得看视频演示,所以准备了动图演示,由于只能上传5M以内的图片,我可是煞费苦心剪辑出来的动图呀

    视频演示:

自制第一人称射击游戏简单游戏视频

总结

  • 小Y:因为时间和素材的原因,这篇文章只是把一个射击游戏的基本功能实现了,还有些地方不够完善。
  • 小云儿:是的呢,小Y哥哥~ 不过这些已经是将关键性的功能都实现啦,已经够我学的了!
  • 小Y:好咧,那这次就学到这里吧。我在文中提到的每一个步骤和细节都要仔细看哦,漏掉了一步可能就会出Bug啦!
  • 小云儿:那下次再见啦小Y哥哥,我这就回去自己动手做一遍!

文中没有做的地方还有挺多,比如一把枪的子弹限制,还有近战武器,投掷物和地图等等。

这些设置起来也都是比较麻烦的,但是作为一个第一人称射击游戏来说,本文中已经把最基础重要的功能给实现啦。

如果你想开发一款属于自己的射击游戏,那本文章可以作为一个启蒙Demo哦,可以让你知道原来网上一些很火的游戏我们也可以自己动手做!

该Demo的工程资源包在这里可以下载,感兴趣的小伙伴赶紧去试一下吧!

如果觉得文章还不错,可以三连支持一下博主哦,加油!
通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!_第16张图片

你可能感兴趣的:(Unity游戏,游戏,游戏开发,unity3d,第一人称射击游戏,新星计划)