3Dunity游戏项目实战——第一人称射击游戏

本文详细介绍了一款Unity3D游戏的设计与实现过程,包括游戏策划、场景搭建、角色控制、敌人AI、UI设计等内容。文章通过具体代码示例讲解了如何实现第一人称射击游戏的核心玩法。
该文章已生成可运行项目,

代码及资料

一、游戏策划

1.1 游戏介绍

在游戏场景中,会有若干个敌人出生点,定时生成一些敌人,敌人会主动寻找并攻击主角。游戏目的就是生存下去,消灭僵尸敌人,获得更高的积分。

1.2 UI界面

在游戏界面,包括主角的生命值,弹药数量,得分以及瞄准星。
游戏失败后,出现一个重新开始的按钮。

1.3 主角

第一人称视角无法看到主角自己,在屏幕上只能看到一致端起来的M16枪械,键盘W、S、A、D键控住主角上下左右移动,鼠标移动来旋转视角。

1.4 敌人

敌人是一个护士模样的僵尸,具有自动寻路的功能,躲避障碍物,并攻击主角。

二、游戏场景

  1. 打开工程,导入模型、动画、音效等资源。
  2. 打开场景Scene,该场景中使用LightmapLight Probe表现静态和动态模型的光影效果。
  3. 选择场景模型,为其添加Mesh Collider多边形碰撞组件。在开发中,模型通常复杂,会准备两组模型,一组质量较高用于显示,另一组用于物理碰撞。

三、主角

主角是看不见的,只能看到主角手里的枪械,尽管如此还是要为主角创建碰撞体,并控制其移动。

3.1 角色控制器

  1. 创建一个空游戏体,Tag设为player
  2. 为主角添加Character Controller角色控制器,这样主角行走时就不会穿模
  3. 为主角添加Rigidbody组件,取消重力模拟,选中Is Kinermaic使其不受物理推演影响。
  4. 创建Player脚本
//Player.cs  完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
   
   

    //组件
    public Transform m_transform;
    CharacterController m_ch;

    //枪口transform
    Transform m_muzzlepoint;
    //射击时,射线能射到的碰撞层
    public LayerMask m_layer;
    //射中目标后的粒子效果
    public Transform m_fx;
    //射击音效
    public AudioSource m_audio;
    public AudioClip m_shootClip; //声音
    //射击间隔时间
    float m_shootTimer = 0;

    //摄像机Transform
    Transform m_camTransform;
    Vector3 m_camRot; //相机旋转角度
    float m_camHeight = 1.4f; //相机高度

    //角色移动速度
    float m_movSpeed = 3.0f;

    //重力
    float m_grivity = 2.0f;

    //生命值
    public int m_life = 5;

    // Start is called before the first frame update
    void Start()
    {
   
   
        //获取组件
        m_transform = this.transform;
        m_ch = this.GetComponent<CharacterController>();
        m_audio = this.GetComponent<AudioSource>();


        //获取摄像机
        m_camTransform = Camera.main.transform;

        //获取枪口
        m_muzzlepoint = m_camTransform.transform.Find("M16/weapon/muzzlepoint").transform;

        //设置相机初始位置
        Vector3 pos = m_transform.position;
        pos.y += m_camHeight;
        m_camTransform.position = pos;

        //设置摄像机的初始旋转角度
        /*
         * rotation是Quaternion类型,可以随时改变旋转角度
         * eulerAngles是Vector3类型,不能随时变化的,是一个定值
         */
        m_camTransform.rotation = m_transform.rotation; 
        m_camRot = m_camTransform.eulerAngles;

        //锁定鼠标
        Cursor.lockState = CursorLockMode.Locked;

    }


    // Update is called once per frame
    void Update()
    {
   
   
        //如果生命值为0,什么也不做
        if (m_life <= 0) return;
        

        //更新射击间隔时间
        m_shootTimer -= Time.deltaTime;
        //鼠标左键射击
        if(Input.GetMouseButton(0) && m_shootTimer <= 0)
        {
   
   
            m_shootTimer = 0.1f;
            //射击音效
            m_audio.PlayOneShot(m_shootClip);
            //减少弹药,更新UI
            GameManager.Instance.SetAmmo(1);

            //RaycastHit用来保存射线探测结果
            RaycastHit info;

            //从muzzlepoint的位置,向摄像机面向的正方向射出一根射线
            //射线只能与m_layer指定的层碰撞,Vector3.forward指(0,0,1)即z方向的单位向量
            bool hit = Physics.Raycast(m_muzzlepoint.position, 
                m_camTransform.TransformDirection(Vector3.forward), out info, 100, m_layer);

            //如果射中了Tag为enemy的物体
            if (info.transform.tag.CompareTo("enemy") == 0)
            {
   
   
                Enemy enemy = info.transform.GetComponent<Enemy>();
                //敌人减少生命
                enemy.OnDamage(1);
            }
            //在射中的地方释放一个粒子效果
            Instantiate(m_fx, info.point, info.transform.rotation);
        }
        Control();

    }


    
    //控制角色移动以及视角变化
    void Control()
    {
   
   
        float xm = 0, ym = 0, zm = 0;

        //获取鼠标移动距离
        float rh = Input.GetAxis("Mouse X"); //右为正
        float rv = Input.GetAxis("Mouse Y"); // 上为正


        //旋转摄像机,z控制着倾斜程度,使保持不变
        m_camRot.x -= rv;   //上下旋转镜头是x控制,上为减
        m_camRot.y += rh;   //左右旋转镜头是y控制,左为减
        m_camTransform.eulerAngles = m_camRot;

        //使主角面向方向与摄像机一致,即只有y轴跟着镜头转动,其他两个方向轴不动
        Vector3 camrot = m_camTransform.eulerAngles;
        camrot.x = 0;
        camrot.z = 0;
        m_transform.eulerAngles = camrot;

        //重力运动
        ym -= m_grivity * Time.deltaTime;

        //上下左右运动
        if (Input.GetKey(KeyCode.W))
        {
   
   
            zm += m_movSpeed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.S))
        {
   
   
            zm -= m_movSpeed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.A))
        {
   
   
            xm -= m_movSpeed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.D))
        {
   
   
            xm += m_movSpeed * Time.deltaTime;
        }

        //移动,会根据角色的朝向,相对前后左右移动
        m_ch.Move(m_transform.TransformDirection
本文章已经生成可运行项目
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值