unity,射手游戏

news2024/12/23 11:02:23

文章目录

  • 介绍
  • 一,制作玩家具体函数脚本PlayerCharacter
  • 三、 制作玩家控制脚本 PlayerController,调用上面的函数方法
  • 四、 制作子弹脚本 shell
  • 五、 给玩家挂载脚本
  • 六、 制作坦克脚本
  • 七、 给坦克添加组件
  • 八、 开始游戏,播放动画
  • 九、 下载


介绍

3d游戏。
玩家自由移动。
持枪发射子弹。
随机生成的坦克追踪玩家。
坦克发射子弹攻击玩家。
hp归零死亡

在这里插入图片描述


一,制作玩家具体函数脚本PlayerCharacter

设置float:移动速度、转动速度、子弹发射速度、现在生命值、最大生命值、两次攻击时间间隔。

设置bool:是否正在攻击、是否死亡

其他组件:角色控制器、生命值滑动条、最大生命值颜色(绿色)、最小生命值颜色(红色)、音频源、动画器、粒子系统

public float speed;
public float turnSpeed;
public float health;
public float attackTime;
public float health;
float healthMax;

bool isAlive;
bool attacking = false;

CharacterController cc;
Animator animator;
public Slider healthSlider;                             
public Image healthFillImage;                          
public Color healthColorFull = Color.green;
public Color HealthColorNull = Color.red;

public ParticleSystem explosionParticles;
public Rigidbody shell;
public Transform muzzle;

start方法,获取动画器、角色控制器、生命值最大化、bool设置活着、更新血条滑块、死亡爆炸效果设置为不可见。
animator = GetComponentInChildren<Animator>();
        cc = GetComponent<CharacterController>();
        healthMax = health;
        isAlive = true;
        RefreshHealthHUD();
        explosionParticles.gameObject.SetActive(false);
玩家被攻击,生命值减少amount,更新血条,如果生命值小于零,死亡
 public void TakeDamage(float amount)
    {
        health -= amount;
        RefreshHealthHUD();
        if (health <= 0f && isAlive)
        {
            Death();
        }
    }
更新血条,滑块的value值更新一次,血条由100%的绿色,变成百分之(health / healthMax)的绿色。
  public void RefreshHealthHUD()
    {
        healthSlider.value = health;
        healthFillImage.color = Color.Lerp(HealthColorNull, healthColorFull, health / healthMax);
    }
死亡,角色是否活着设置为否,播放粒子特效,当粒子系统的持续时间结束后,粒子系统对象就会被销毁,设置玩家为不可见。
 public void Death()
    {
        isAlive = false;
        explosionParticles.transform.parent = null;
        explosionParticles.gameObject.SetActive(true);
        ParticleSystem.MainModule mainModule = explosionParticles.main;
        Destroy(explosionParticles.gameObject, mainModule.duration);
        gameObject.SetActive(false);

    }
角色移动,传入一个向量值,必须在活着、没有攻击才能移动。
角色控制器使用simplemove函数,移动的时候,控制“speed”动画,开始播放
 public void Move(Vector3 v)
    {
        if (!isAlive) return;
        if (attacking) return;
        Vector3 movement = v * speed;
        cc.SimpleMove(movement);
        if(animator)
        {
            animator.SetFloat("Speed", cc.velocity.magnitude);
        }
    }
人物旋转函数,玩家往哪里跑,角色人物头就转向哪里
设置目标位置、当前位置
四元数转向
使用球面插值,平滑转动
  public void Rotate(Vector3 lookDir)
    {
        var targetPos = transform.position + lookDir;
        var characterPos = transform.position;

        //去除Y轴影响
        characterPos.y = 0;
        targetPos.y = 0;
        //角色面朝目标的向量
        Vector3 faceToDir = targetPos - characterPos;
        //角色面朝目标方向的四元数
        Quaternion faceToQuat = Quaternion.LookRotation(faceToDir);
        //球面插值
        Quaternion slerp = Quaternion.Slerp(transform.rotation, faceToQuat, turnSpeed * Time.deltaTime);

        transform.rotation = slerp;
    }
开火脚本
必须活着、不正在开火才能调用
生成一个子弹刚体,玩家自身位置,枪口方向转向,设置发射速度
播放开火音效
动画器播放开火动作
延迟attachtime发射一次,设置发射频率
 public void Fire()
    {
        if (!isAlive) return;
        if (attacking) return;

        Rigidbody shellInstance = Instantiate(shell, muzzle.position, muzzle.rotation) as Rigidbody;
        shellInstance.velocity = launchForce * muzzle.forward;
        shootAudioSource.Play();

        if(animator)
        {
            animator.SetTrigger("Attack");
        }


        attacking = true;
        Invoke("RefreshAttack", attackTime);
    }

发射时间间隔脚本,时间未到,不能发射
 void RefreshAttack()
    {
        attacking = false;
    }

三、 制作玩家控制脚本 PlayerController,调用上面的函数方法

start方法获取角色控制器
void Start ()
    {
        character = GetComponent<PlayerCharacter>();
	}
固定帧数刷新。
鼠标左键调用点击开火函数
键盘wsad控制人物移动
人物移动的方向和人物转向的方向保持一致
void FixedUpdate()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            character.Fire();
        }

        var h = Input.GetAxis("Horizontal");
        var v = Input.GetAxis("Vertical");
        character.Move(new Vector3(h, 0, v));
        var lookDir = Vector3.forward * v + Vector3.right * h;
        if (lookDir.magnitude != 0)
        {
            character.Rotate(lookDir);
        }
    }

四、 制作子弹脚本 shell

设置float参数:子弹生存时间、爆炸半径、爆炸力量、最大伤害

设置bool参数:子弹是否正在旋转

设置其他:音频源、层级、粒子系统
    public float lifeTimeMax = 2f;
    public AudioSource explosionAudioSource;
    public ParticleSystem explosionParticles;
    public float explosionRadius;
    public float explosionForce = 1000f;
    public float damageMax = 100f;
    public LayerMask damageMask;
    public bool isRotate = false;

start方法,添加扭矩,模拟子弹旋转

 void Start ()
    {
        if(isRotate)
        {
            GetComponent<Rigidbody>().AddTorque(transform.right * 1000);
        }
    }
触发器碰撞检测
在当前游戏对象的位置上创建一个球形的检测区域,并检测该区域内是否有与指定层级(damageMask)匹配的碰撞器(colliders)。如果有,则返回一个碰撞器数组(Collider[]),其中包含了所有与当前游戏对象在指定半径(explosionRadius)内发生碰撞的游戏对象的碰撞器。通常用于实现爆炸伤害、碰撞检测等功能。	
遍历数组,计算伤害
播放粒子特效
 private void OnTriggerEnter(Collider other)
    {
        Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius, damageMask);

        foreach(var collider in colliders)
        {
            var targetCharacter = collider.GetComponent<PlayerCharacter>();
            if (targetCharacter)
            {
                targetCharacter.TakeDamage(CalculateDamage(collider.transform.position));
            }
        }
        explosionParticles.transform.parent = null;
	     explosionAudioSource.Play();
        explosionParticles.Play();

        ParticleSystem.MainModule mainModule = explosionParticles.main;
	    // Destroy(explosionParticles.gameObject, mainModule.duration);
        Destroy(gameObject);
    }

计算伤害,传入向量值
距离越小,伤害比例越大
设置最低伤害Mathf.Max()函数,最低伤害为2
float CalculateDamage(Vector3 targetPosition)
    {
        
        var distance = (targetPosition - transform.position).magnitude;
        //距离越小,伤害比例越大
        var damageModify = (explosionRadius - distance) / explosionRadius;
        var damage = damageModify * damageMax;
        return Mathf.Max(2f, damage);
    }

五、 给玩家挂载脚本

设置参数,添加预制体子弹
在这里插入图片描述


六、 制作坦克脚本

设置导航网格、play对象
	 NavMeshAgent agent;
    PlayerCharacter character;
    Transform targetTrans;
start函数,获取玩家实例,
导航网格寻找玩家
延迟1秒后,每隔三秒发射一次子弹
 void Start ()
    {
        character = GetComponent<PlayerCharacter>();
        agent = GetComponent<NavMeshAgent>();

        targetTrans = GameObject.FindGameObjectWithTag("Player").transform;
        
        InvokeRepeating("FireControl", 1, 3);
    }
开火控制函数,调用共同使用的fire()方法。
 void FireControl()
    {
        character.Fire();
    }

update()函数,不断追踪玩家的位置,
转向玩家
void Update ()
    {
        agent.destination = targetTrans.position;
        transform.LookAt(targetTrans);
    }

七、 给坦克添加组件

在这里插入图片描述


八、 开始游戏,播放动画

在这里插入图片描述

人物移动、坦克移动

在这里插入图片描述


九、 下载

https://pan.baidu.com/s/1RVemZY_THhhpD0v_IcQS2w

提取码:tdq9





+

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/418310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

seata学习笔记

Seata 官网&#xff1a; https://seata.io/zh-cn/index.html 是什么&#xff1f; Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式…

MySQL中的float类型慎用!慎用!慎用!

在前端输入一串数字后有时候展示值与输入的内容一致&#xff0c;有时候却不一致。经分析&#xff0c;原来是MySQL数据库中字该字段的类型是float&#xff0c;该字段的值超过6位有效数字后就会进行四舍五入截取&#xff0c;举例来说&#xff1a;假设float类型字段的输入值是1234…

十八、MySQL 变量、分支结构IF、CASE...WHEN详解

文章目录一、变量1.1 系统变量1.1.1 系统变量分类1.1.2 查看系统变量1.2 用户变量1.2.1 用户变量分类1.2.2 会话用户变量1.2.3 局部变量1.2.4 对比会话用户变量与局部变量二、定义条件与处理程序2.1 案例分析2.2 定义条件2.3 定义处理程序2.4 案例解决三、流程控制3.1 分支结构…

[C++]类与对象下篇

目录 类与对象下篇&#xff1a;&#xff1a; 1.再谈构造函数 2.static成员 3.友元 4.内部类 5.匿名对象 6.拷贝对象时的编译器优化 7.再次理解封装 8.求12...n(不能使用乘除法、循环、条件判断) 9.计算日期到天数的转换 10.日期差值 11.打印日期 12.累加天数 类与对象下篇&…

数据结构与算法七 堆

一 堆 1.1 堆定义 堆是计算机科学中一类特殊的数据结构的统称&#xff0c;堆通常可以被看做是一棵完全二叉树的数组对象。 堆的特性&#xff1a; 它是完全二叉树&#xff0c;除了树的最后一层结点不需要是满的&#xff0c;其它的每一层从左到右都是满的&#xff0c;如果最后…

4月最新编程排行出炉,第一名ChatGPT都在用~

作为一名合格的&#xff08;准&#xff09;程序员&#xff0c;必做的一件事是关注编程语言的热度&#xff0c;编程榜代表了编程语言的市场占比变化&#xff0c;它的变化更预示着未来的科技风向和机会&#xff01; 快跟着一起看看本月排行有何看点&#xff1a; 4月Tiobe排行榜前…

【CSS】使用 固定定位 实现顶部导航栏 ( 核心要点 | 固定定位元素居中设置 | 代码示例 )

文章目录一、核心要点分析1、顶部导航栏要点2、固定定位垂直居中设置二、代码示例一、核心要点分析 实现下图所示功能 : 上方有一个固定导航栏 , 水平居中设置 ;左右两侧各一个广告栏 , 垂直居中设置 ; 1、顶部导航栏要点 顶部导航栏要点 : 使用固定定位 , 上边偏移设置为 0 …

Linux Ubuntu虚拟机下载安装以及初始配置--VMware、Ubuntu、Xshell、Xftp

一、下载准备 Ubuntu系统下载链接&#xff08;系统本身&#xff09;&#xff1a;官网链接 VMware虚拟机下载链接&#xff08;搭载Ubuntu系统&#xff09;&#xff1a;网盘链接密码XMKD Xshell下载链接&#xff08;虚拟机远程连接&#xff09;&#xff1a;官网链接 Xftp下载…

MySQL索引数据结构入门

之前松哥写过一个 MySQL 系列&#xff0c;但是当时是基于 MySQL5.7 的&#xff0c;最近有空在看 MySQL8 的文档&#xff0c;发现和 MySQL5.7 相比还是有不少变化&#xff0c;同时 MySQL 又是小伙伴们在面试时一个非常重要的知识点&#xff0c;因此松哥打算最近再抽空和小伙伴们…

PyQt5学习笔记一、安装PyQt5和在PyCharm中配置工具

一、安装PyQt5 1. 可以在cmd窗口安装PyQt5和工具 可以在cmd窗口使用命令 pip install PyQt5 安装PyQt5&#xff0c;若指定版本使用命令 pip install PyQt5version&#xff0c;此时同时安装了PyQt5和sip。参考链接 在cmd命令窗口安装Python模块_Mr. 李大白的博客-CSDN博客htt…

potPlay——记忆播放位置、各种快捷键

potPlay——记忆播放位置、各种快捷键potPlay——各种快捷键简洁版完整版快捷键列表potPlay——记忆播放位置potPlay——各种快捷键 简洁版 Q 复位 亮度&#xff0c;对比度&#xff0c;色度复位键 W/E 调暗/调亮 R/T 对比度 Y/U 饱和度 I/O 色彩度 D 上一帧 F 下一帧 M 静音 …

Docker开启并配置远程安全访问

前言 在工作学习中&#xff0c;为了提高项目部署效率&#xff0c;一般会在Idea中直接使用Docker插件连接服务器Docker容器&#xff0c;然后将项目打包与DockerFile一起build成Docker镜像部署运行。但是不可能服务器总是跟着主机的&#xff0c;因此呢时常会面临的一个问题就是从…

【微信小程序】-- uni-app 项目--- 购物车 -- 配置 tabBar 效果(五十一)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…

事务的ACID特性

1. 絮絮叨叨 重温Apache ORC时&#xff0c;发现ORC支持ACID想起自己之前一度不知道ACID是哪些单词的缩写&#xff0c;更别提面试中常提到的事物隔离级别等知识了因此&#xff0c;特地学习一下数据库中事务的ACID 2. ACID 2.1 What’s transaction&#xff1f; 考虑一个真实…

42.原型对象 prototype

目录 1 面向对象与面向过程 2 原型对象 prototype 3 在内置对象中添加方法 4 constructor 属性 5 实例对象原型 __proto__ 6 原型继承 7 原型链与instanceof 7.1 原型链 7.2 instanceof 8 案例-模态框 1 面向对象与面向过程 编程思想有 面向过程 与 面向…

几何-九种二次曲面类型

&#xff08;一&#xff09;椭圆锥面 &#xff08;1&#xff09;把z平方看成一个一直变大的常数&#xff0c;那么可以看出延z方向&#xff0c;是一个一直变大的椭圆。 &#xff08;2&#xff09;把一个x或y赋予0&#xff0c;显然是一个两条关于原点对称的直线。 由上即可判断…

不小心删除了文件能恢复吗 误删除文件怎么找回

电脑是我们平时工作或者生活、学习中使用频率非常高的电子设备&#xff0c;已经成为了我们日常生活中不可或缺的一部分。删除文件是电脑使用过程中常见的一种操作&#xff0c;因为电脑的储存空间是有限的&#xff0c;我们需要对电脑数据进行清理&#xff0c;避免电脑储存空间占…

视觉检测相比于人工目视检测有哪些优势

技术的发展可以给我们带来好的结果。 是其中之一。 这在现代工业生产中非常常见。 视觉检测设备可以更好地检测生产中的错误和产品质量问题&#xff0c;提高工业生产的效率和自动化水平&#xff0c;提高工业生产的准确性&#xff0c;加快工作进度&#xff0c;节约时间&#xff…

docker too many open files解决方式

1&#xff1a;问题描述 今天在环境上执行docker ps命令失败&#xff0c;如下提示 [rootcontrol02 ~]# docker ps -a lgrep nginx Cannot connect to the Docker daemon at unix:///var/run/docker.sock, Is the docker daemon running?2&#xff1a;查看节点docker状态 看信…

【Arduino 和 HC-12 远程无线通信模块】

【Arduino 和 HC-12 远程无线通信模块】 1. 概述2. HC-12 无线通信模块3. Arduino 和 HC-123.1 原理图3.2 示例 01 – Arduino 代码3.3 AT 命令:3.4 例子 023.5 代码说明:4. HC-12 无线通信:使用加速度计的步进电机控制4.1 原理图4.2 代码说明:1. 概述 在本Arduino教程中,…