精华内容
下载资源
问答
  • Unity,游戏。 本文设计了一个第一人称射击游戏的Demo开发过程,文中对射击游戏的基础功能做了一个详细介绍,适用于一个基础框架,可以用于一个射击游戏的完整开发,请品尝。
    • 📢博客主页:https://blog.csdn.net/zhangay1998
    • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
    • 📢本文由 God Y.原创,首发于 CSDN🙉
    • 📢未来很长,值得我们全力奔赴更美好美好的生活✨


    📢引言

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

      在这里插入图片描述

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

    在这里插入图片描述

    🎄导入一个资源包

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

    既然想要做一个CS那样的射击游戏,场景跟模型肯定得有啊
    我们这就来导入一个简单的资源包,里面有简单的一个场景和几把枪械
    **图

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

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

    • 小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将动画片段控制起来
    在这里插入图片描述

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

    换子弹

    动画控制值Animator配置

    这里我们先来给神器AK47(阿卡47)来进行动画配置
    点开这个
    Animation Controller
    就是这个默认界面
    在这里插入图片描述

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

    在这里插入图片描述

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

    • 先添加动画过度参数,然后点击小箭头,将动画过度的条件添加上,Has Exit Time 参数配置好
      在这里插入图片描述

    • 看一下过度的实际动画过度效果,这里可能不够明显,因为两个动画间并没有很大的差异:
      在这里插入图片描述

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

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

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

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

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

    从名字就可以知道他是控制动画的播放速度的,所以我们在这里将速度的值改的越大,它播放的速度就越快,那我们的换弹速度就会更快啦!
    在这里插入图片描述


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

    • 小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);
    
        }
    }
    

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

    然后是管理枪支的脚本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键就是换弹,鼠标左键就是开火,同步游戏设置~
      在这里插入图片描述
    • 小Y:好啦,一个控制枪械开火、换弹、换枪的脚本就算实现啦,是不是很简单呢!
    • 小云儿👩:Emma…不是很难,但是好像也并没有小Y哥哥你说的这么简单哦~
    • 小Y:哈哈,其实真的很简单啦,只是你还不熟练而已,多练几次就好啦!
    • 小云儿👩:好咧小Y哥哥
    • 小Y:还有最后一个开火特效小模块没有解决,我来给你演示一般怎么简单添加的添加一个特效!

    ⭐️枪械开火特效设置

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

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

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

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

    如下图所示,直接放枪口处即可:
    在这里插入图片描述

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

    • 然后我们在FPSGun脚本中添加两个方法,分别控制播放特效和取消特效:
       /// <summary>
        /// 播放开火特效
        /// </summary>
        public void PlayerFireEffect()
        {
            //启动特效
            muzzleFlash.SetActive(true);
            //0.2秒关闭
            Invoke("UnEffect", 0.1f);
        }
        /// <summary>
        /// 取消特效
        /// </summary>
        private void UnEffect()
        {
            muzzleFlash.SetActive(false);
        }
    
    • 然后新建一个脚本PlayerAudioAndEffect,这个脚本有点特殊,因为他不是挂在游戏对象身上的,而是挂在动画片段身上的,创建完脚本后会直接继承StateMachineBehaviour,然后会有几个override重写方法,我们只需要在OnStateEnter方法中使用即可
      在这里插入图片描述

    • 创建方法:要在Animator视窗中选中动画片段,然后Add Behaviour上去
      在这里插入图片描述

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

    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的工程资源包在这里可以下载,感兴趣的小伙伴赶紧去试一下吧!

    如果觉得文章还不错,可以三连支持一下博主哦,加油!
    在这里插入图片描述

    展开全文
  • 用javascript编写的第一人称射击游戏
  • 第一人称射击游戏

    2016-05-28 22:38:18
    《unity3d/2d手机游戏开发》书籍中的第一人称射击游戏
  • 第一人称射击游戏
  • 第一人称射击 这个项目是我迈向创建快速多人第一人称射击游戏第一步。 所需的统一版本:2019.3.14f1
  • 该资源为使用Unity做的一个第一人称射击游戏Demo,包含一个地图和几把枪械,在博主文章中有介绍怎样使用,可以前来学习哦
  • js实现第一人称射击游戏
  • 第一人称射击 第一人称射击游戏
  • 第一人称射击类游戏,FPS(First-person Shooter), 严格来说第一人称射击游戏属于ACT类游戏的一个分支,但和RTS类游戏一样,由于其在世界上的迅速风靡,使之发展成了一个单独的类型。 介绍:(截图) ...
  • unity第一人称射击游戏From Doom to Minecraft, the first-person perspective has really caught on with modern video games. 从《毁灭战士》到《我的世界》,第一人称视角已经真正吸引了现代视频游戏。 In this ...

    unity第一人称射击游戏

    From Doom to Minecraft, the first-person perspective has really caught on with modern video games.

    从《毁灭战士》到《我的世界》,第一人称视角已经真正吸引了现代视频游戏。

    In this comprehensive tutorial, you'll learn how to build a first person shooter of your own. You'll use the popular Unity 3D engine.

    在这个全面的教程中,您将学习如何构建自己的第一人称射击游戏。 您将使用流行的Unity 3D引擎。

    We'll provide all the assets you need, so you can focus on the gamedev coding itself.

    我们将提供您需要的所有资产,因此您可以专注于gamedev编码本身。

    Here are some things you'll do as part of this 8-hour tutorial:

    在这8小时的教程中,您将要做一些事情:

    • Importing the level and configuring the lighting

      导入关卡并配置照明
    • Creating your player

      创建您的播放器
    • Coding your player's movement and jump

      编码玩家的动作和跳跃
    • Mouse controls

      滑鼠控制
    • Sprinting and crouching

      冲刺和蹲伏
    • Animating your player's hands and weapons

      动画玩家的手和武器
    • Switching between weapons

      在武器之间切换
    • Player attack scripting

      玩家攻击脚本
    • Creating a zoom effect

      创建缩放效果
    • Animating the enemy

      动画敌人
    • Enemy AI

      敌人AI
    • Detecting and dealing damage

      检测和处理损坏
    • Creating sound effects

      创造音效
    • Displaying health and stamina using the player stats user interface

      使用玩家统计信息用户界面显示健康状况和耐力

    You can watch the video tutorial on the freeCodeCamp.org YouTube channel (8 hour watch).

    您可以在freeCodeCamp.org YouTube频道上观看视频教程(观看8小时)。

    ‌                                                                                           ‌

    翻译自: https://www.freecodecamp.org/news/unity-3d-first-person-shooter-game-tutorial/

    unity第一人称射击游戏

    展开全文
  • InfiniteSkills - Creating First-Person Shooter Games with Unity 在unity中制作第一人称射击游戏
  • C/C++ 3D游戏项目设计,基于directX编写的第一人称射击游戏游戏源码
  • 这是用unity 开发第一人称射击游戏,是根据教程做的,供初学者使用
  • Shooter:在线第一人称射击游戏
  • 人称射击游戏.zip

    2021-03-30 18:59:21
    人称射击demo
  • ArduFPS arduboy的第一人称射击游戏
  • FPS - 第一人称射击游戏

    千次阅读 2019-06-15 09:28:30
    第一人称射击类游戏,FPS(First-person shooting game), 严格来说第一人称射击游戏属于ACT类游戏的一个分支,但和RTS类游戏一样,由于其在世界上的迅速风靡,使之发展成了一个单独的类型。 FPS(First-person ...

    第一人称射击类游戏,FPS(First-person shooting game), 严格来说第一人称射击游戏属于ACT类游戏的一个分支,但和RTS类游戏一样,由于其在世界上的迅速风靡,使之发展成了一个单独的类型。

    FPS(First-person Shooting)第一人称视角射击游戏顾名思义就是以玩家的主观视角来进行射击游戏。玩家们不再像别的游戏一样操纵屏幕中的虚拟人物来进行游戏,而是身临其境的体验游戏带来的视觉冲击,这就大大增强了游戏的主动性和真实感。早期第一人称类游戏所带给玩家的一般都是的屏幕光线的刺激,简单快捷的游戏节奏。随着游戏硬件的逐步完善,以及各种游戏的不断结合。第一人称射击类游戏提供了更加丰富的剧情以及精美的画面和生动的音效。

    封闭型

    此类fps游戏的地图较为简单,地图四周经常会有高墙封闭起来,地图往往有几条固定的大路构成.地图中的各类物件往往与排列也很简单,其主要特征是地图规模较小,玩家一般在一定范围的区域内竞技。

    代表作为军团要塞,反恐精英,虚幻竞技场,使命召唤系列,荣誉勋章(PC版主要是联合袭击,先头部队,突出重围),守望先锋等

    沙盒型

    此类fps游戏中,玩家可以较为自由地在地图中游戏,地图中没有固定的路线,地图也较大,更富有战术的空间与观赏性,其一般带有剧情线索,玩家通过完成指定任务到达下一个关卡。

    代表作为孤岛危机(主要指1代),激战海陆空,闪点行动孤岛惊魂武装突袭,战地系列(战地1942,战地:越南,战地2,战地:自由竞技,战地2142,战地3,战地4,战地:硬仗等),荣誉勋章:空降神兵,行星边际2,H1Z1,绝地求生等

    展开全文
  • 第一人称射击游戏HUD插件Unity游戏素材资源,代码精良,运行稳定,支持多人游戏
  • 包含一个较为完整的UNITY第一人称射击游戏的教程,及其使用到的素材包,含角色武器模型。 《我的Unity 3D之旅》博客配套美术资源
  • 第一人称射击游戏实战——第一人称相机控制 创建一个Camera,命名为FP_Camera,标签改为MainCamera,将Camera作为FP_Player的子物体。 并把position改成 X=0,Y=2,Z=-0.2 创建C#脚本 ,命名为fps_FPCamera using ...

    第一人称射击游戏实战——第一人称相机控制

    创建一个Camera,命名为FP_Camera,标签改为MainCamera,将Camera作为FP_Player的子物体。
    并把position改成 X=0,Y=2,Z=-0.2
    创建C#脚本 ,命名为fps_FPCamera

    知识储备

    1.Transform中的关于旋转
    (1)Rotate
    Transform.Rotate(enlerAngles:Vector3,relativeTo:Spave=Space.Self):void
    作用:如果相对于留空或者设置为Space.Self,旋转角度Vector3被应用围绕自身轴做变换。如果相对于Space.World,旋转角度Vector3被应用围绕世界X,Y,Z轴。
    (2)eulerAngle
    Unity中默认的是先绕z轴,后x轴,后y轴的顺序欧拉旋转。这个要求是一个绝对值,注意:不要递增,不要超过360°。(注意:这不意味着单次的旋转角度不能超过360°,而是意味着即使超过了,需要做一个周期处理。因此属于(-360,360))
    (3)rotation
    旋转角度的存储用四元数。四元数是高阶的含有虚数的向量。我们可以将一个初始轴表示成四元数,也可以将一种绕某一个轴旋转一定角度的旋转变化表示成四元数。A*B表示对四元数B表示的轴经过四元数A表示的旋转变换得到了一个新的四元数(新的轴)。这就是左乘一个旋转变化可以得到新的轴。当然,本质上,每一个四元数都代表了一种旋转变换,我们将B这个初始轴,可以看成是物体围绕初始轴旋转了0度。因此B本身和A都是一种对物体的旋转变换。
    注意区别:
    1.Rotate是一种方法,而rotation是一种属性
    2.Rotate的旋转可以是以自身坐标系或者世界坐标系。而rotation是针对世界坐标系。
    3.Rotate的每一次旋转是在上一次的角度的基础上叠加,但是rotation的旋转是基于世界坐标系中初始状态一次性完成旋转。
    2.Quaternion四元数的表示
    Quaternion.AngleAxis(float angle,Vector3 axis)
    作用:返回一个绕轴线axis旋转angle角度的四元数变换。
    注意四元素的使用过程中,axis是一个单位向量。angle不能超过180°。
    3.静态、动态欧拉角
    静态欧拉角是相对于世界坐标系旋转,动态欧拉角是刚体自身作为参考系旋转。
    4.世界坐标系与自身坐标表示方法
    transform.up 世界坐标系Y轴
    transform.right 世界坐标系 X轴
    transform.forward 世界坐标系Z轴
    Vector3.right 表示(1,0,0),物体右轴或者世界坐标X轴正方向
    Vector3.left 表示(-1,0,0),物体左轴。。。
    Vector3.up 表示(0,1,0),物体上轴。。。
    Vector3.down 表示(0,-1,0),物体下轴。。。
    Vector3.forward 表示(0,0,1),物体前轴。。。
    Vector3.back 表示(0,0,-1),物体后轴。。。
    注意Vextor3系列主要功能只是对于单位向量的简写,具体是世界坐标系还是自身坐标系,定义是不同的。
    5.Mathf.Clamp(float value,float min,float max)
    该函数做一个限制,返回
    (1)max; value>max
    (2)value; min<=value<=max
    (3)min;value<=min
    利用分段函数对value的值做一个限制。

    编程思路

    前面两个部分中,对于用户的输入进行判断,同时转化成Vector2或者bool量为fps_PlayerParamer中的定义人物参数做一个赋值。那么,人物参数inputSmoothLook也需要在相机控制中被用到。因此一定需要找标签为player的游戏对象上的组件。Vector2中的x和y实际上代表的是鼠标的x方向和y方向上的移动方向和量。那么需要分类讨论:如果移动的是x方向,视角左右旋转,可以通过控制人物或者是camera来控制。此时若围绕Vector3.up顺时针(俯视)为正方向,与鼠标移动的x正方向相对应。如果移动的是y方上下向,视图上下旋转,可以通过camera来控制。此时若围绕Vector3.right顺时针(俯视)为正方向,但是注意:与鼠标移动的y的负方向相对应,因此此时鼠标的移动量*灵敏度在转化成相机的转动量的过程中,需要对转动角度加一个负号。
    另外,因为角度的表示不能超过360°,因此需要做周期性的处理。但是因为本游戏中基本都是用小角度旋转,因此只需要做一个周期即可。另外视角上具有一定的限制,例如控制相机抬头低头有一个限度,不能把脖子扭了。因此周期性处理完,就可以用Clamp的分段函数做一个限制。最后利用四元数完成旋转。
    注意:四元数旋转对应最后的代码,其中第一个yQuaternion并非一定要加。如果加上去,相当于告诉transform的y方向上有自由度,但是自由度为0。如果不加,相当于没有自由度。虽然本质是一样的,不过加上去就相当于刻意强调了player父物体本身不能在y轴上有自由度(不能绕X轴翻转)。这样的话也提高了代码的可读性。最后这段代码其实就是表达鼠标的移动对应父物体player和子物体camera在两个方向上的自由度,只不过父物体的其中一个自由度为0。

    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);//绕x轴旋转的角度(抬头低头)
    	public Vector2 rotationYLimit = new Vector2(-360,360);//绕y轴旋转的角度(左转右转)
    	public Vector3 positionOffset = new Vector3(0,2,-0.2f);//相机的初始位置
    	private Vector2 currentMouseLook=Vector2.zero;//初始角度
    	private float x_Angle=0;
    	private float y_Angle=0;
    	private fps_PlayerParameter parameter;
    	private Transform m_Transform;
    	void Start()
    	{
    		parameter = GameObject.FindGameObjectWithTag(Tag.player).GetComponent<fps_PlayerParameter>();
    		m_Transform = transform;
    		m_Transform = positionOffset;//初始位置
    	}
    	private void GetMouseLook()
    	{
    		currentMouseLook.x=parameter.inputSmoothLook.x;
    		currentMouseLook.y=parameter.inputSmoothLook.y;
    		currentMouseLook.x*=mouseLookSensitivity.x;
    		currentMouseLook.y*=mouseLookSensitivity.y;
    		currentMouseLook.y=-1;
    		//若鼠标向X正方向移动,那么应该物体绕Y轴顺时针旋转,但是如果鼠标向Y正方向移动,那么应该物体绕X轴顺时针旋转,但是如果这样,就会实现低头操作。可是鼠标向Y正方向移动是为了实现抬头操作。因此需要乘上-1.
    	}
    	private void UpdateInput()
    	{
    		if(parameter.inputSmoothLook==Vector2.zero)
    			return;
    		GetMouseLook();
    		y_Angle+=currentMouseLook.x;//每一次的移动都是在之前的基础上转动角度,因此X_Angle可以获得总的角度。
    		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_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)
    	}
    	void Update()
    	{
    		UpdateInput();
    	}
    	void LateUpdate()
    	{
    		Quaternion xQuaternion = Quaternion.AngleAxis(y_Axis,Verter3.up);
    		Quaternion yQuaternion = Quaternion.AngleAxis(0,Verter3.right);
    		m_transform.parent.rotation = xQuaternion*yQuaternion;
    		yQuaternion = Quaternion.AngleAxis(x_Angle,Verter3.right);
    		m_transform.rotation = xQuaternion*yQuaternion;
    	}
    }
    
    
    展开全文
  • 一个Camera的控制程序,适合第一人称射击游戏和飞行游戏
  • 本资源是射击游戏的地图,是个工厂,灯光已经渲染好了,直接导进去就能用,还包括地图附带的周围环境,包括油桶,烟囱,动态的烟,完全还原真实场景
  • unity3d 枪支武器包,FPS第一人称射击游戏,模型贴图完整,包含动画脚本。 http://www.6m5m.com/data/uploads/2014/03/21/31314532b9d31da624.jpg
  • ACR:AssaultCube重新加载(第一人称射击游戏
  • iphone 3d 设计游戏 源码 iphone 3d 设计游戏 源码
  • unity3d 第一人称射击游戏 Demo

    千次阅读 2014-10-26 20:24:47
    unity3d 第一人称射击游戏 Demo
  • unity3D 第一人称射击游戏

    千次阅读 2015-01-26 21:58:37
    今天和·1昨天学习了《第一人称射击游戏》 现在来做一个总结: 首先是对周围墙体、地面加上一个碰撞检测体:Msh Collider(主要作用就是为了是其他物体gameobject对象无穿越它) 再在上面加一个Navigation...
  • Unity第一人称射击游戏的移动 先上代码: `public class gamecontrol : MonoBehaviour { CharacterController playerController; Vector3 direction; public float speed = 1; public float jumpPower = 5; public...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,680
精华内容 1,872
关键字:

第一人称射击游戏