unity应用实例——从头撸一个全新的FPS游戏(1)

2023-11-04

从今天开始打算从头开始搞一个全新的FPS游戏,引擎使用的是unity2017,所有美术资源都计划从商店购买或是网上下载(自己实在搞不来),主要玩法是玩家需要穿越多个地图到达目的地,每个地图类似于一个地牢,规定时间到地牢的门才会打开,在这之前玩家会遇到怪物追杀和哨兵把守,玩家突破重重阻碍直到逃出最后一个地牢即可胜利。在这里主要是做一下记录和总结,有不足之处希望指正。

这一篇是整个系列的准备工作。首先创建一个空物体作为玩家控制的对象,添加一个Character Controller组件。然后需要添加一个玩家控制角色的脚本,主要负责使玩家视角跟随对象,并控制角色移动、跳跃等。这种脚本比较熟悉了,因为是fps游戏,不用给玩家自己设置动画,所以我手撸了一个简易版的,效果满意。下面是脚本代码。

using System;
using UnityEngine;
public class player : MonoBehaviour
{
    [HideInInspector]
    public float m_mouserate;//鼠标灵敏度

    [SerializeField]
    private float m_gravity;
    [SerializeField]
    private float m_steptime;
    [SerializeField]
    private float m_jumpspeed;
    [SerializeField]
    private float m_movespeed;
    [SerializeField]
    private float m_crouchmovespeed;

    public Camera m_camera;
    private CharacterController m_player;

    public Transform m_eyes;//眼睛
    public AudioClip[] m_stepsound = new AudioClip[4];
    public AudioClip m_jumpsound;
    public AudioSource m_audio;

    private float m_y = 0;
    private float m_timer = 0;//用来计算播放走路音效的时间间隔

    void Start()
    {
        m_camera = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();

        m_player = gameObject.GetComponent<CharacterController>();
        m_audio = gameObject.GetComponent<AudioSource>();

    }


    private void FixedUpdate()
    {
        //声音设置
        gameObject.GetComponent<AudioSource>().volume = datamanager.m_volume;

        playermove();

        float deltay = Input.GetAxis("Mouse X");
        float deltax = Input.GetAxis("Mouse Y");
        Cameramove(m_mouserate * deltax, m_mouserate * deltay);

        if (!GroundCheck())
        {
            m_y -= m_gravity * Time.deltaTime;
        }
    }

    #region 主角移动和脚步声音
    public void playermove()
    {

        m_timer += Time.deltaTime;

        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");

        if (GroundCheck())
        {
            if (Input.GetKeyDown(KeyCode.Space))//起跳
            {
                Jump();
                m_timer = -m_steptime / 2;//这个值是随意设置的,只是为了起跳时不播放走路音效
            }
        }

            if (m_player.velocity.magnitude != 0 && m_timer > m_steptime)
            {
                m_audio.PlayOneShot(m_stepsound[UnityEngine.Random.Range(0, 4)]);//PlayOneShot可以直接播放一次指定AudioClip
                m_timer = 0;
            }

        //移动
        m_player.Move(gameObject.transform.TransformDirection(new Vector3(x, m_y, z) * m_movespeed * Time.deltaTime));
    }

    public void Jump()
    {
        m_y = m_jumpspeed;
        m_audio.PlayOneShot(m_jumpsound);
    }
    #endregion

    #region 摄像头角度移动
    public void Cameramove(float deltax, float deltay)
    {
        //鼠标控制摄像头角度
        Vector3 angle = m_camera.transform.eulerAngles;
        angle.x -= deltax;
        angle.y += deltay;
        if (angle.x > 35 && angle.x < 90) angle.x = 35;
        if (angle.x < 325 && angle.x > 270) angle.x = 325;//控制上下视野

        m_camera.transform.eulerAngles = angle;
        //主角角度与摄像头角度同步
        angle.x = angle.z = 0;
        transform.eulerAngles = angle;
        //摄像机跟随眼睛
        m_camera.transform.position = m_eyes.transform.position;
    }
    #endregion

    //检测是否在地上
    private bool GroundCheck()
    {
        RaycastHit hitInfo;
        if (Physics.SphereCast
            (transform.position, m_player.radius, Vector3.down, out hitInfo,
             0.3f, Physics.AllLayers, QueryTriggerInteraction.Ignore))
            return true;
        else return false;
    }

    public void Relax()
    {
        m_movespeed /= 100;
    }
    public void Resume()
    {
        m_movespeed *= 100;
    }
}

这样的话角色控制就实现了,再写一个描述玩家血量和死亡的脚本,因为有多个脚本需要知道玩家死亡这件事(如ui脚本等),所以创建一个委托。这里playui是后面创建的ui管理脚本。

using UnityEngine;

public  delegate  void  onedelegate();

public class playerhp : MonoBehaviour
{
    private int m_hp;
    public int M_hp { get { return m_hp; } }

    public onedelegate diedelegate;

    void Start()
    {
        m_hp = 100;
    }
    void Update()
    {
        if (m_hp <= 0)
        {
            if(diedelegate!=null)
                diedelegate();
        }
    }
    public void bedammaged(int dam)
    {
        FindObjectOfType<playui>().HurtEffect();
        m_hp -= dam;
    }
}

  到这里准备工作还没有做完,我们知道,很多unity项目都需要创建一个对象池来提高效率,在本项目中也不例外:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//对象池
public class pool : MonoBehaviour
{
    public static pool instance;

    //用字典构造多个池子,每个类型的池子的名字为string类型,一个池子本质上是一个栈
    private static Dictionary<string, Stack<GameObject>> m_pool;
   
    void Awake()
    {
        m_pool = new Dictionary<string, Stack<GameObject>>();
        instance = this;//单例模式
    }

    //从池子得到物体
    public static GameObject GetPrefab(GameObject prefab, Vector3 position,Quaternion rotation)
    {
        //池子的名字,这样子命名是因为预制体实例化后会名字会加一个(Clone)
        string key = prefab.name + "(Clone)";

        if(!m_pool.ContainsKey(key))//没有这个栈
        {
            GameObject one = Instantiate(prefab, position, rotation);
            m_pool.Add(key, new Stack<GameObject>());
            one.SetActive(true);
            return one;
        }

        else if ( m_pool[key].Count > 0)//如果栈存在且有东西
        {
            GameObject one = m_pool[key].Pop();
            one.transform.position = position;
            one.transform.rotation = rotation;
            one.SetActive(true);
            return one;
        }
        else //栈存在,栈里没东西
        {
            GameObject one = Instantiate(prefab,position,rotation);
            one.SetActive(true);
            return one;
        }
     
    }

    //将已经实例化出的gameobject放入对应的池子
    public static GameObject PrefabReturn(GameObject one)
    {
        m_pool[one.name].Push(one);
        one.SetActive(false);
        return one;
    }
}

对象池脚本写好后,我把他挂在一个命名为pool的空物体上,这样准备工作就完成了。

下一篇武器系统:https://blog.csdn.net/qq_37553152/article/details/81904033

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

unity应用实例——从头撸一个全新的FPS游戏(1) 的相关文章

  • GCC 的使用及介绍

    一 GCC介绍 Linux系统下的GCC是GNU推出的功能强大 性能优越的多平台编译器 它可以在多种硬件平台上编译处可执行程序的超级编译器 其执行效率比一般的编译器的效率要高20 30 Gcc编译器能将C C 语言源程序 汇程式化序和目标程

随机推荐

  • FPGA时序约束理论之多周期路径(6)

    1 单周期路径 前面的时钟周期约束 都是按照单周期关系进行分析数据路径 即数据的发起沿和采样沿是最邻近的一对时钟沿 如下图所示 默认情况下 保持时间的检查是以建立时间的检查为前提 即总是在建立时间的前一个时钟周期确定保持时间检查 也就是说
  • 基于Matlab的多线激光中心坐标值提取

    本文是基于给定的两张多线激光图片 如下图所示 需将图片中的激光线的中心线坐标提取出来并绘制激光中心线图形 因为是Matlab课程训练研究大作业 所以全文代码为Matlab 希望可以为相似作业的非专业同学提供一些帮助 文章目录 1 问题分析
  • docker-compose常用命令

    docker compose up d nginx 构建建启动nignx容器 docker compose exec nginx bash 登录到nginx容器中 docker compose down 删除所有nginx容器 镜像 doc
  • python 多分类逻辑回归_机器学习实践:多分类逻辑回归(softmax回归)的sklearn实现和tensorflow实现...

    本文所有代码及数据可下载 Scikit Learn 篇 Light 版 scikit learn内置了逻辑回归 对于小规模的应用较为简单 一般使用如下代码即可 from sklearn linear model logistic impor
  • Spring框架(SpringBoot)中redis报错(Could not get a resource from the pool、java.net.SocketTimeoutException)

    Spring框架 SpringBoot 中redis报错 在使用SpringBoot框架的时候 Spring一直会报两个特别纠结特别的烦的错误 尝试了很多种方法 都是失败的 不能成功 经过我坚持不懈的努力寻找 终于把问题给解决了 一 第一个
  • 灭鼠先锋

    奇技淫巧 cout lt lt LLLV
  • 编译器构造中自底向上的LALR(1)语法分析的语法分析表生成的实现

    提示 阅读本文需掌握编译原理的相关基础知识 本文中使用C 语言系统地实现了龙书中LALR 1 语法分析表的构造算法 首先计算增广文法的LR 0 项集族 每一个项集只包含内核项 计算过程中自动生成了LR 0 自动机 该自动机使用基于十字链表存
  • 【server组件】——mysql连接池的实现原理

    目录 1 池化技术 2 数据库连接池的定义 3 为什么要使用连接池 4 数据库连接池的运行机制 5 连接池与线程池的关系 6 CResultSet的设计 6 1构造函数 7 CDBConn的设计 6 1 构造函数 6 2 init 初始化连
  • 最大间隔问题

    问题描述 给定n个实数x1 x2 x3 xn 求这n个数在实轴上相邻2个数之间的最大间隔 假设对任何实数取整耗时O 1 设计解最大间隙问题的线性时间算法 算法设计 对于给定的n个实数x1 x2 x3 xn 计算它们的最大间隙 数据输入 输入
  • proc*c sqlcode=[-1405];sqlerr=[ORA-01405: fetched column value is NULL

    指示变量的值 及其代表的含义如下 0 操作成功 1 该指示变量对应的宿主变量返回了或插入 更新成了NULL值 2 从数据库存放数据到对应的宿主变量时 数据超长 并且不能推断出截断了多少字节的长度 gt 0 在FETHC或SELECT语句时
  • 5g空分复用技术_5G通信技术原理总结

    5G通信的基本流程框图 如上图 5G智能手机MIC输入的模拟信号会通过基带中的AD数模转换电路 完成采样 量化 编码 变成数字信号 具体过程如下如所示 信源编码 信源编码 上图中的编码 我们称之为信源编码 信源编码 说白了 就是把声音 画面
  • (2018-2021年)Uncertainty 相关SOTA文献笔记整理

    Uncertainty 文献笔记 ACL Word Level Uncertainty Estimation for Black Box Text Classifiers using RNNs Unsupervised Quality Es
  • Java口算练习软件(随机生成10道100以内的数学练习题)

    Java口算练习软件 使用Java编写口算练习软件 实现以下功能点 1 随机生成10道100以内的加减法练习题 2 设计GUI界面 包含 生成题目 上一题 检查答案 导出结果 导入题目 等按钮 这是一个Java程序 实现了一个口算练习软件
  • 第一章 计算机基础知识

    文章目录 第一章 计算机基础知识 1 计算机引论 1 1计算机发展的四个阶段 1 2计算机的发展现状计算机的未来 2 计算机硬件和软件基础 2 1计算机组成体系 2 2计算机硬件的组成 2 3常见的几种操作系统 3 计算机DOS命令行操作
  • Vue.config.js开发环境与生产环境配置

    Vue config js开发环境与生产环境配置 首先在项目根目录创建 env development 开发环境 env production 生产环境 VUE APP SERVICE URL VUE APP BASE API 生产环境配置
  • Java的 字节流 InputStream 类及其子类 FileInputStream 的使用

    import java io FileInputStream import java io FileNotFoundException import java io InputStream public class InputStreamT
  • 实验一 构建虚拟局域网

    实验一 构建虚拟局域网 实验目的 实验环境与设备 实验要求 过程如下 实验目的 为网络安全试验做准备 构建虚拟局域网的网络环境 利用VMware Workstation Pro 12虚拟机安装Windows 10 Windows8 实验环境
  • uni-app开发微信小程序,checkbox、radio等原生组件样式设置问题解决方案

    它们是原生的组件 修改样式只能在app vue里面修改 目前只知道这一种解决办法 如果你的UI给的图比较特殊 用css写比较困难 推荐使用图片代替 请看下面示例 正确设置 在App vue文件里设置 test vue文件 这里假设你使用ch
  • 【SQL】记住,永远不要在MySQL中使用“utf8”

    文章目录 缘由 那么什么是编码 什么是 UTF 8 MySQL 简史 为什么这件事情会让人如此抓狂 总结 缘由 最近我遇到了一个 bug 我试着通过 Rails 在以 utf8 编码的 MariaDB 中保存一个 UTF 8 字符串 然后出
  • unity应用实例——从头撸一个全新的FPS游戏(1)

    从今天开始打算从头开始搞一个全新的FPS游戏 引擎使用的是unity2017 所有美术资源都计划从商店购买或是网上下载 自己实在搞不来 主要玩法是玩家需要穿越多个地图到达目的地 每个地图类似于一个地牢 规定时间到地牢的门才会打开 在这之前玩