Survival Shooter 学习
using UnityEngine; using System.Collections; namespace CompleteProject { /// <summary> /// 摄像机跟随 /// </summary> public class CameraFollow : MonoBehaviour { /// <summary> /// 摄像机跟随的目标 /// </summary> public Transform target; /// <summary> /// 相机的移动速度 /// </summary> public float smoothing = 5f; /// <summary> /// 摄像机相对于目标的偏移 /// </summary> Vector3 offset; void Start () { //计算偏移 offset = transform.position - target.position; } void FixedUpdate () { //计算相机要移动到的位置 Vector3 targetCamPos = target.position + offset; //移动相机 transform.position = Vector3.Lerp (transform.position, targetCamPos, smoothing * Time.deltaTime); } } }
CameraFollow
using UnityEngine; namespace CompleteProject { /// <summary> /// 敌人管理 /// </summary> public class EnemyManager : MonoBehaviour { /// <summary> /// 玩家生命 /// </summary> public PlayerHealth playerHealth; /// <summary> /// 敌人预设 /// </summary> public GameObject enemy; /// <summary> /// 每次孵化敌人的间隔 /// </summary> public float spawnTime = 3f; /// <summary> /// 孵化敌人的位置 /// </summary> public Transform[] spawnPoints; void Start () { InvokeRepeating ("Spawn", spawnTime, spawnTime); } /// <summary> /// 孵化敌人 /// </summary> void Spawn () { //如果玩家当前生命<=0,不处理 if(playerHealth.currentHealth <= 0f) { return; } //随机找一个孵化点 , spawnPoints.Length); //在这个孵化点孵化敌人 Instantiate (enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation); } } }
EnemyManager
using UnityEngine; using System.Collections; namespace CompleteProject { /// <summary> /// 玩家攻击 /// </summary> public class EnemyAttack : MonoBehaviour { /// <summary> /// 每次攻击的时间间隔 /// </summary> public float timeBetweenAttacks = 0.5f; /// <summary> /// 每次攻击照成的伤害 /// </summary> ; /// <summary> /// 敌人Animator /// </summary> Animator anim; /// <summary> /// 玩家 /// </summary> GameObject player; /// <summary> /// 玩家生命 /// </summary> PlayerHealth playerHealth; /// <summary> /// 敌人生命 /// </summary> EnemyHealth enemyHealth; /// <summary> /// 玩家是否在攻击范围内 /// </summary> bool playerInRange; /// <summary> /// 下次攻击的计时器 /// </summary> float timer; void Awake () { player = GameObject.FindGameObjectWithTag ("Player"); playerHealth = player.GetComponent <PlayerHealth> (); enemyHealth = GetComponent<EnemyHealth>(); anim = GetComponent <Animator> (); } void OnTriggerEnter (Collider other) { //如果碰到玩家 if(other.gameObject == player) { //设置标志位为true playerInRange = true; } } void OnTriggerExit (Collider other) { //如果玩家离开 if(other.gameObject == player) { //设置标志位为false playerInRange = false; } } void Update () { //每帧增加计时器的时间 timer += Time.deltaTime; //当计时器的时间大于等于每次攻击的时间间隔 //玩家在攻击范围内 //敌人的当前血量大于0 ) { //攻击 Attack (); } //如果玩家的生命值小于等于0 ) { //animator触发PlayerDead动画 anim.SetTrigger ("PlayerDead"); } } /// <summary> /// 攻击 /// </summary> void Attack () { //重置攻击计时器 timer = 0f; //如果玩家当前生命大于0 ) { //伤害玩家 playerHealth.TakeDamage (attackDamage); } } } }
EnemyAttack
using UnityEngine; namespace CompleteProject { public class EnemyHealth : MonoBehaviour { /// <summary> /// 敌人初始生命 /// </summary> ; /// <summary> /// 敌人当前生命 /// </summary> public int currentHealth; /// <summary> /// 敌人死亡后下沉的速度 /// </summary> public float sinkSpeed = 2.5f; /// <summary> /// 被玩家击杀时,玩家获得的得分 /// </summary> ; /// <summary> /// 死亡声音 /// </summary> public AudioClip deathClip; Animator anim; AudioSource enemyAudio; /// <summary> /// 敌人受到伤害时的粒子系统 /// </summary> ParticleSystem hitParticles; CapsuleCollider capsuleCollider; /// <summary> /// 敌人是否死亡 /// </summary> bool isDead; /// <summary> /// 敌人是否下沉 /// </summary> bool isSinking; void Awake () { anim = GetComponent <Animator> (); enemyAudio = GetComponent <AudioSource> (); hitParticles = GetComponentInChildren <ParticleSystem> (); capsuleCollider = GetComponent <CapsuleCollider> (); //设置当前生命为初始生命 currentHealth = startingHealth; } void Update () { //如果敌人在下沉 if(isSinking) { //移动敌人在y轴的位置 transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime); } } /// <summary> /// 受到伤害 /// </summary> /// <param name="amount">伤害数值</param> /// <param name="hitPoint">受到伤害的位置</param> public void TakeDamage (int amount, Vector3 hitPoint) { //如果敌人死亡,不处理 if(isDead) return; //播放受伤声音 enemyAudio.Play (); //减少当前血量 currentHealth -= amount; //将受伤的粒子系统的位置设置为受到伤害的位置 hitParticles.transform.position = hitPoint; //播放粒子系统 hitParticles.Play(); //如果当前血量<=0 ) { //调用死亡函数 Death (); } } /// <summary> /// 死亡 /// </summary> void Death () { //修改死亡标志位 isDead = true; //将碰撞器改为触发器 capsuleCollider.isTrigger = true; //触发animator的dead动画 anim.SetTrigger ("Dead"); //播放敌人死亡声音 enemyAudio.clip = deathClip; enemyAudio.Play (); } /// <summary> /// 敌人开始下沉 /// </summary> public void StartSinking () { //关闭NavMeshAgent GetComponent <NavMeshAgent> ().enabled = false; //将Rigidbody设置为kinematic GetComponent <Rigidbody> ().isKinematic = true; //将下沉标志位设置为true isSinking = true; //添加玩家的得分 ScoreManager.score += scoreValue; //销毁敌人 Destroy (gameObject, 2f); } } }
EnemyHealth
using UnityEngine; using System.Collections; namespace CompleteProject { /// <summary> /// 敌人移动 /// </summary> public class EnemyMovement : MonoBehaviour { /// <summary> /// 玩家的位置 /// </summary> Transform player; /// <summary> /// 玩家的生命 /// </summary> PlayerHealth playerHealth; /// <summary> /// 敌人生命 /// </summary> EnemyHealth enemyHealth; /// <summary> /// NavMeshAgent /// </summary> NavMeshAgent nav; void Awake () { player = GameObject.FindGameObjectWithTag ("Player").transform; playerHealth = player.GetComponent <PlayerHealth> (); enemyHealth = GetComponent <EnemyHealth> (); nav = GetComponent <NavMeshAgent> (); } void Update () { //如果敌人生命和玩家生命都大于0 && playerHealth.currentHealth > ) { //敌人移动到玩家位置 nav.SetDestination (player.position); } //否则关闭NavMeshAgent else { nav.enabled = false; } } } }
EnemyMovement
using UnityEngine; using UnityEngine.UI; using System.Collections; using UnityEngine.SceneManagement; namespace CompleteProject { /// <summary> /// 玩家生命 /// </summary> public class PlayerHealth : MonoBehaviour { /// <summary> /// 游戏开始时玩家的生命 /// </summary> ; /// <summary> /// 玩家的当前生命 /// </summary> public int currentHealth; /// <summary> /// 生命滑动条 /// </summary> public Slider healthSlider; /// <summary> /// 玩家受到伤害时的图片 /// </summary> public Image damageImage; /// <summary> /// 玩家死亡的声音剪辑 /// </summary> public AudioClip deathClip; /// <summary> /// 伤害图片变透明的速度 /// </summary> public float flashSpeed = 5f; /// <summary> /// 伤害图片的颜色 /// </summary> public Color flashColour = new Color(1f, 0f, 0f, 0.1f); Animator anim; AudioSource playerAudio; PlayerMovement playerMovement; PlayerShooting playerShooting; /// <summary> /// 玩家是否死亡 /// </summary> bool isDead; /// <summary> /// 玩家是否受到伤害 /// </summary> bool damaged; void Awake () { anim = GetComponent <Animator> (); playerAudio = GetComponent <AudioSource> (); playerMovement = GetComponent <PlayerMovement> (); playerShooting = GetComponentInChildren <PlayerShooting> (); //设置当前血量为起始血量 currentHealth = startingHealth; } void Update () { //如果玩家受到伤害,修改伤害图片的颜色 if(damaged) { damageImage.color = flashColour; } //没有受到伤害,伤害图片渐隐 else { damageImage.color = Color.Lerp (damageImage.color, Color.clear, flashSpeed * Time.deltaTime); } //设置伤害标志位false damaged = false; } /// <summary> /// 玩家受到伤害 /// </summary> /// <param name="amount">受到伤害的数值</param> public void TakeDamage (int amount) { //设置伤害标志位true damaged = true; //减少当前血量 currentHealth -= amount; //将当前血量应用到血量滑动条上 healthSlider.value = currentHealth; //播放受伤的声音 playerAudio.Play (); //如果当前血量<=0并且玩家死亡的标志位位true. && !isDead) { Death (); } } /// <summary> /// 玩家死亡 /// </summary> void Death () { //修改死亡标志位 isDead = true; //关闭射击特效 playerShooting.DisableEffects (); //触发死亡动画 anim.SetTrigger ("Die"); //播放死亡声音 playerAudio.clip = deathClip; playerAudio.Play (); //关闭移动和射击脚本 playerMovement.enabled = false; playerShooting.enabled = false; } /// <summary> /// 重新开始 /// </summary> public void RestartLevel () { //加载场景 SceneManager.LoadScene (); } } }
PlayerHealth
using UnityEngine; using UnitySampleAssets.CrossPlatformInput; namespace CompleteProject { /// <summary> /// 玩家移动 /// </summary> public class PlayerMovement : MonoBehaviour { /// <summary> /// 玩家移动速度 /// </summary> public float speed = 6f; /// <summary> /// 玩家移动方向 /// </summary> Vector3 movement; /// <summary> /// Animator /// </summary> Animator anim; /// <summary> /// Rigidbody /// </summary> Rigidbody playerRigidbody; #if !MOBILE_INPUT /// <summary> /// 地面 /// </summary> int floorMask; /// <summary> /// 射线的长度 /// </summary> float camRayLength = 100f; #endif void Awake () { #if !MOBILE_INPUT floorMask = LayerMask.GetMask ("Floor"); #endif anim = GetComponent <Animator> (); playerRigidbody = GetComponent <Rigidbody> (); } void FixedUpdate () { //获取水平和垂直的输入 float h = CrossPlatformInputManager.GetAxisRaw("Horizontal"); float v = CrossPlatformInputManager.GetAxisRaw("Vertical"); //处理玩家的移动 Move (h, v); //处理玩家的旋转 Turning (); //处理玩家的动画 Animating (h, v); } /// <summary> /// 移动 /// </summary> /// <param name="h"></param> /// <param name="v"></param> void Move (float h, float v) { movement.Set (h, 0f, v); //设置移动速度 movement = movement.normalized * speed * Time.deltaTime; //刚体移动 playerRigidbody.MovePosition (transform.position + movement); } /// <summary> /// 旋转 /// </summary> void Turning () { #if !MOBILE_INPUT //从鼠标点击的屏幕位置创建射线 Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition); //接收射线撞击到地面的数据 RaycastHit floorHit; //发射射线 if(Physics.Raycast (camRay, out floorHit, camRayLength, floorMask)) { //创建一个玩家到撞击点的向量 Vector3 playerToMouse = floorHit.point - transform.position; //保证这个向量的y为0 playerToMouse.y = 0f; //根据这个向量创建四元数 Quaternion newRotatation = Quaternion.LookRotation (playerToMouse); //刚体旋转 playerRigidbody.MoveRotation (newRotatation); } #else Vector3 turnDir = new Vector3(CrossPlatformInputManager.GetAxisRaw("Mouse X") , 0f , CrossPlatformInputManager.GetAxisRaw("Mouse Y")); if (turnDir != Vector3.zero) { Vector3 playerToMouse = (transform.position + turnDir) - transform.position; playerToMouse.y = 0f; Quaternion newRotatation = Quaternion.LookRotation(playerToMouse); playerRigidbody.MoveRotation(newRotatation); } #endif } /// <summary> /// 播放动画 /// </summary> /// <param name="h">水平输入值</param> /// <param name="v">垂直输入值</param> void Animating (float h, float v) { bool walking = h != 0f || v != 0f; anim.SetBool ("IsWalking", walking); } } }
PlayerMovement
using UnityEngine; using UnitySampleAssets.CrossPlatformInput; namespace CompleteProject { /// <summary> /// 玩家射击 /// </summary> public class PlayerShooting : MonoBehaviour { /// <summary> /// 没发子弹造成的伤害 /// </summary> ; /// <summary> /// 每发子弹的时间间隔 /// </summary> public float timeBetweenBullets = 0.15f; /// <summary> /// 射击范围 /// </summary> public float range = 100f; /// <summary> /// 发射子弹的计时器 /// </summary> float timer; /// <summary> /// 射击射线 /// </summary> Ray shootRay; /// <summary> /// 射击击中点 /// </summary> RaycastHit shootHit; /// <summary> /// 可以受到射击的层 /// </summary> int shootableMask; /// <summary> /// /// </summary> ParticleSystem gunParticles; /// <summary> /// 枪的线条渲染器 /// </summary> LineRenderer gunLine; /// <summary> /// 枪的声音 /// </summary> AudioSource gunAudio; /// <summary> /// 枪的灯光 /// </summary> Light gunLight; /// <summary> /// /// </summary> public Light faceLight; /// <summary> /// 效果的显示时间 /// </summary> float effectsDisplayTime = 0.2f; void Awake () { //获取可以射击的层 shootableMask = LayerMask.GetMask ("Shootable"); gunParticles = GetComponent<ParticleSystem> (); gunLine = GetComponent <LineRenderer> (); gunAudio = GetComponent<AudioSource> (); gunLight = GetComponent<Light> (); //faceLight = GetComponentInChildren<Light> (); } void Update () { //每帧增加计时器的时间 timer += Time.deltaTime; #if !MOBILE_INPUT //如果按下发射按键,计时器大于两次发射子弹的间隔时,时间比例不等于0 ) { //射击 Shoot (); } #else || CrossPlatformInputManager.GetAxisRaw() && timer >= timeBetweenBullets) { Shoot(); } #endif //如果计时器超过特效显示的时间 if(timer >= timeBetweenBullets * effectsDisplayTime) { //关闭射击效果 DisableEffects (); } } public void DisableEffects () { gunLine.enabled = false; faceLight.enabled = false; gunLight.enabled = false; } /// <summary> /// 射击 /// </summary> void Shoot () { //重置计时器 timer = 0f; //播放射击声音 gunAudio.Play (); gunLight.enabled = true; faceLight.enabled = true; //先停止粒子特效,然后再播放特效 gunParticles.Stop (); gunParticles.Play (); //设置线条渲染器的第一个位置 gunLine.enabled = true; gunLine.SetPosition (, transform.position); //设置 射击射线的 起点和方向 shootRay.origin = transform.position; shootRay.direction = transform.forward; //发射射线,碰到敌人 if(Physics.Raycast (shootRay, out shootHit, range, shootableMask)) { //敌人受到伤害 EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> (); if(enemyHealth != null) { enemyHealth.TakeDamage (damagePerShot, shootHit.point); } //设置线条渲染器的第二个位置为射击点的位置 gunLine.SetPosition (, shootHit.point); } //没有碰到敌人,设置线条渲染器的第2个位置 else { gunLine.SetPosition (, shootRay.origin + shootRay.direction * range); } } } }
PlayerShooting
using UnityEngine; namespace CompleteProject { /// <summary> /// 游戏结束管理 /// </summary> public class GameOverManager : MonoBehaviour { /// <summary> /// 玩家生命 /// </summary> public PlayerHealth playerHealth; /// <summary> /// Animator /// </summary> Animator anim; void Awake () { anim = GetComponent <Animator> (); } void Update () { //如果玩家生命值小于等于0 ) { //Animator设置GameOver触发器 anim.SetTrigger ("GameOver"); } } } }
GameOverManager
using UnityEngine; using System.Collections; using UnityEngine.UI; using UnityEngine.Audio; #if UNITY_EDITOR using UnityEditor; #endif /// <summary> /// 暂停管理 /// </summary> public class PauseManager : MonoBehaviour { public AudioMixerSnapshot paused; public AudioMixerSnapshot unpaused; /// <summary> /// Canvas /// </summary> Canvas canvas; void Start() { canvas = GetComponent<Canvas>(); } void Update() { //按esc键 切换游戏状态 if (Input.GetKeyDown(KeyCode.Escape)) { canvas.enabled = !canvas.enabled; Pause(); } } /// <summary> /// 暂停游戏 /// </summary> public void Pause() { Time.timeScale = Time.timeScale == ? : ; Lowpass (); } /// <summary> /// 调整声音 /// </summary> void Lowpass() { ) { paused.TransitionTo(.01f); } else { unpaused.TransitionTo(.01f); } } /// <summary> /// 退出游戏 /// </summary> public void Quit() { //调用编辑器的退出 #if UNITY_EDITOR EditorApplication.isPlaying = false; //调用正常的退出 #else Application.Quit(); #endif } }
PauseManager
using UnityEngine; using UnityEngine.UI; using System.Collections; namespace CompleteProject { /// <summary> /// 玩家分数管理 /// </summary> public class ScoreManager : MonoBehaviour { /// <summary> /// 玩家分数 /// </summary> public static int score; /// <summary> /// 显示玩家分数的文本 /// </summary> Text text; void Awake () { text = GetComponent <Text> (); //重置玩家分数 score = ; } void Update () { //更新玩家分数的显示 text.text = "Score: " + score; } } }
ScoreManager
视频:https://pan.baidu.com/s/1geIxFs3
项目:https://pan.baidu.com/s/1gfDonkf
Survival Shooter 学习的更多相关文章
- JSBinding + SharpKit / 实战:转换 Survival Shooter
从 asset store 下载 Survival Shooter (商店里有2个版本,一种是给Unity5用的,一个是给Unity4.6用的,我们这个实验用的是后者,版本是2.2.如果) 1 删除多 ...
- Space Shooter 学习
using UnityEngine; using System.Collections; /// <summary> /// 背景滚动 /// </summary> publi ...
- Unity3D项目之 Survival Shooter 记录
1.导入资源 2.把预设文件的环境拖到场景中, 3.位置归0 4.保存场景 5.删除默认灯光,把预设灯光拖到场景中,位置归0 6.新建一个 Quad 7.旋转90度,设置缩放100,100,1 重命名 ...
- 【Unity3D】资源对象、预设、查找对象、组合模式等知识点
1.解释对象与资源区别于联系,根据官方案例,分别总结资源和对象组织的规则/规律. 下载并查看了Adam和Survival Shooter tutorial两个官方资源案例,这些案例作为资源,可以 ...
- UGUI全面实践教程
UGUI全面实践教程 试读文档下载地址:http://pan.baidu.com/s/1hq3UYGk 介绍:UGUI是Unity官方推出的最新UI系统.本教程为国内唯一的UGUI专向资料.本教程 ...
- apex-utility-ai-unity-survival-shooter
The AI has the following actions available: Action Function Shoot Fires the Kalashnikov Reload Reloa ...
- Unity代码热更新方案 JSBinding + SharpKit 首页
目前Unity的代码更新方案有很多,主要以lua为主. JSBinding + SharpKit 是一种新的技术,他做了两件事情: JSBinding将C#导出到 JavaScript (引擎是 Mo ...
- unity学习笔记1--Space Shooter
其实我一直觉得我是个模棱两可的人,就计算机这块来说,自己还是想制作游戏什么的,但是又得考虑到现实就业的问题,所以现在自己主要在学安卓和javaweb.现在大概是心血来潮吧,突然想追逐下自己的理想,虽然 ...
- R语言学习路线和常用数据挖掘包(转)
对于初学R语言的人,最常见的方式是:遇到不会的地方,就跑到论坛上吼一嗓子,然后欣然or悲伤的离去,一直到遇到下一个问题再回来.当然,这不是最好的学习方式,最好的方式是——看书.目前,市面上介绍R语言的 ...
随机推荐
- 2.17 C++类与const关键字
参考: http://www.weixueyuan.net/view/6348.html 总结: const成员变量的初始化只有唯一的一条途径:参数初始化表. const成员函数可以使用类中的所有成员 ...
- 栈回溯简单实现(x86)
0x01 栈简介 首先局部变量的分配释放是通过调整栈指针实现的,栈为函数调用和定义局部变量提供了一块简单易用的空间,定义在栈上的变量不必考虑内存申请和释放.只要调整栈指针就可以分配和释放内存. ...
- <Hadoop重装><centos><NameNode失效>
Overview 记一次真真切切的NameNode单点故障. 学校机房着火之后,刀片机上的四台服务器,唯独就NameNode彻底宕掉了,去机房看了下硬盘都坏了.. 所以只能换一个master咯.基本上 ...
- 什么是wsgi,uwsgi,uWSGI
WSGI: web服务器网关接口,是一套协议.用于接收用户请求将请求进行初次封装,然后将请求交给web框架 实现wsgi协议的模块: 1,wsgiref,本质就是编写一个socket服务端,用于接收用 ...
- Oracle流程控制语句
1.选择语句 1.1 IF...THEN...END IF语句 DECLARE MY_AGE INT; IF MY_AGE IS NULL THEN DBMS_OUTPUT.put_line('AGE ...
- [转载] About Career Promotion and Tutoring from Zhihu Web FAQer (Quoted Entirely Without Personal Idea. Delete Immediately If Pirated)
问题: 如何下列各类公司的互联网IT类工作待遇排名? 下列各公司岗位待遇序号从小到大依次降低: 美国互联网总部special offer(15万刀起薪) : 股份制银行总行,证券公司,基金公司IT部门 ...
- 河工大第十届ACM省赛随笔
比赛成果达到了预期目标,不过还是很遗憾没有更进一步,刚到河工大的时候就想吐槽,拥挤的机房,难受的键盘鼠标,还有规定食堂的,饭票.一切都和河大比赛是给我的感觉不一样,再加上热身赛的那天我背着一大包东西, ...
- 序列化 json 模块
什么是序列化? 将python中的列表,字典,元组,集合转换成字符串的过程就叫做序列化,反之叫做反序列化. 我们把变量从内存中变成可存储或传输的过程称之为序列化,序列化之后,就可以把序列化后的内容写入 ...
- 如何利用Power BI 制作动态搜索界面
最近Power BI有了最新更新,想着利用 Power BI 工具制造一个动态的搜索界面,比如动态切换搜索引擎,分别从百度.360.搜狗等搜索苹果最新新闻.通过一番测试,最终实现了相关功能. 数据加载 ...
- batch normalization在测试时的问题
验证: 在测试时可以一张图,但设置use_global_stats:true,已经验证,第一台4gpu上,路径:/home/guangcong/projects/unlabeled-video/tra ...